chainlesschain 0.166.26 → 0.166.29

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 (177) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/assets/{AIOps-Z8_dnLd8.js → AIOps-D4Dhiipq.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-C4bKCISV.js → ActionButton-P6fPjlUB.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-GztAv2jy.js → Analytics-CzeKpXdh.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-DEqNcuVx.js → AppLayout-Cj8CqntA.js} +4 -4
  6. package/src/assets/web-panel/assets/{Artifacts-D-R4Ehap.js → Artifacts-BOe7lviy.js} +1 -1
  7. package/src/assets/web-panel/assets/{Audit-mzzdTIlM.js → Audit-D6kxPJyo.js} +1 -1
  8. package/src/assets/web-panel/assets/{BackgroundAgents-DS2QupIC.js → BackgroundAgents-OVuYY65D.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-CQSirC39.js → Backup-UAlkEXOa.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-Bhuc-eOV.js → BaseInput-DikQWFIL.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-B-RLVGnt.js → Chat-CEpqrZcV.js} +6 -6
  12. package/src/assets/web-panel/assets/ChatBubbleRenderer-BLE9L1yw.js +1 -0
  13. package/src/assets/web-panel/assets/{Checkbox-DxwgBryW.js → Checkbox-D2mdaw7o.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-Cwrm-7nh.js → Codegen-CJ2LEcdr.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-DrSCT-nF.js → Col-ej56LWvr.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-DY2D9WNs.js → Community-D9neNmTp.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-o-tV0URw.js → Compact-BzWfgovR.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-Bndh6S8f.js → Compliance-dStoa8Mw.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-CSNQODak.js → Cowork-BxYPXbQl.js} +3 -3
  20. package/src/assets/web-panel/assets/{Cron-CTgxRHdy.js → Cron-DxOQIcrL.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-BJoGQzDI.js → Crosschain-BYyOjqVA.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-V0Ztm8ne.js → DID-c81gsUZq.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-B-38THOj.js → Dashboard-CHIjYxb2.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-B3FdOwMO.js → Dropdown-C7hRZzkL.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-YQDz4mUF.js → EmailListRenderer--h_ShKAT.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-DYE45IF9.js → FamilyGuardDashboard-Bq68asD0.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-DjBFjdRZ.js → Federation-DGKsWpUO.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-CVTXEa0R.js → FormItemContext-1HbCXJAf.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-B6Tkke8X.js → GenericCardRenderer-BlKJ93Fy.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-CD0hyAzT.js → Git-DJA-kxuw.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-CWOQQJr8.js → Governance-BWZPtzHj.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-lHYwUk-C.js → Inference-D3QXUTYP.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-Cledxv7t.js → KnowledgeGraph-BM37hWOP.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-D45mt-rM.js → Logs-Bpu4Of_0.js} +2 -2
  35. package/src/assets/web-panel/assets/MarkdownRenderer-DAZcw_ZS.js +1 -0
  36. package/src/assets/web-panel/assets/{Marketplace-Yy30UZPw.js → Marketplace-BZe0jmAU.js} +1 -1
  37. package/src/assets/web-panel/assets/{McpTools-Cil5l-bh.js → McpTools-_q_nfUnU.js} +3 -3
  38. package/src/assets/web-panel/assets/{Memory-DdJcnyqy.js → Memory-CIzcovHt.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileBridge-IrzFYHEv.js → MobileBridge-DZzo5UjF.js} +1 -1
  40. package/src/assets/web-panel/assets/{MobileProjects-D8q64LMd.js → MobileProjects-DVZr9bVO.js} +1 -1
  41. package/src/assets/web-panel/assets/{Mtc-CpdTJzW7.js → Mtc-pULSsEOx.js} +4 -4
  42. package/src/assets/web-panel/assets/{MtcAudit-C7Tvw2m6.js → MtcAudit-BLz9fiz0.js} +2 -2
  43. package/src/assets/web-panel/assets/{Multisig-Dmj9F5Kr.js → Multisig-B1qxfPkT.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-C9Xchob5.js → NLProgramming-Bkb9YB7P.js} +1 -1
  45. package/src/assets/web-panel/assets/{Notes-Bzq6Yry5.js → Notes-N0G87PD1.js} +4 -4
  46. package/src/assets/web-panel/assets/{NotificationSettings-DxG9eKb4.js → NotificationSettings-D0jB-hRv.js} +1 -1
  47. package/src/assets/web-panel/assets/{OrderTableRenderer-BS_IYoCe.js → OrderTableRenderer-soFvgov0.js} +1 -1
  48. package/src/assets/web-panel/assets/{Organization-kazsRvcq.js → Organization-BNBL1-7S.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-i4wP-hwn.js → Overflow-yqaJxwEo.js} +1 -1
  50. package/src/assets/web-panel/assets/{P2P-CfGeU3h-.js → P2P-1JHDOnl3.js} +2 -2
  51. package/src/assets/web-panel/assets/{PdhVaultBrowser-CS-VhVUx.js → PdhVaultBrowser-D1FgaOLV.js} +5 -5
  52. package/src/assets/web-panel/assets/{Permissions-DnEHXs0I.js → Permissions-DOQh1Wzv.js} +4 -4
  53. package/src/assets/web-panel/assets/{PersonalDataHub-DeD82qke.js → PersonalDataHub-SVa21bUw.js} +5 -5
  54. package/src/assets/web-panel/assets/{Pipeline-CMGGLgBY.js → Pipeline-Du3gCATi.js} +1 -1
  55. package/src/assets/web-panel/assets/{Privacy-CvHoFv32.js → Privacy-CPW8EDaC.js} +1 -1
  56. package/src/assets/web-panel/assets/{ProjectInit-DnJapCc1.js → ProjectInit-CAu5N0A_.js} +2 -2
  57. package/src/assets/web-panel/assets/{ProjectSettings-CqVdv3-g.js → ProjectSettings-DVTow6ty.js} +2 -2
  58. package/src/assets/web-panel/assets/{Projects-B_o8vcs_.js → Projects-CBUF9hPa.js} +1 -1
  59. package/src/assets/web-panel/assets/{Providers-CPKseoDW.js → Providers-B7pNEoaY.js} +1 -1
  60. package/src/assets/web-panel/assets/{QrScannerModal-_iBfKbPQ.js → QrScannerModal-BHs1Kx7e.js} +1 -1
  61. package/src/assets/web-panel/assets/{QuickAsk-CMrlZ69a.js → QuickAsk-IBrdC5B5.js} +1 -1
  62. package/src/assets/web-panel/assets/{Recommend-BwDtSZ0l.js → Recommend-BtkLuO-e.js} +1 -1
  63. package/src/assets/web-panel/assets/{RemoteSession-DomUAtn4.js → RemoteSession-Du4_izg3.js} +2 -2
  64. package/src/assets/web-panel/assets/{Reputation-Cuu2GCHr.js → Reputation-IEbMZN6v.js} +1 -1
  65. package/src/assets/web-panel/assets/{Row-C7GVts31.js → Row-D5UM_ivw.js} +1 -1
  66. package/src/assets/web-panel/assets/{RssFeed-DRKvgEog.js → RssFeed-DTTNnkdJ.js} +3 -3
  67. package/src/assets/web-panel/assets/{Search-BGI9wOeA.js → Search-B5f7ggJE.js} +1 -1
  68. package/src/assets/web-panel/assets/{Security-BlLaHy_L.js → Security-CsZp2uGu.js} +3 -3
  69. package/src/assets/web-panel/assets/{Services-DFqZbjmX.js → Services-BJhguqIh.js} +2 -2
  70. package/src/assets/web-panel/assets/{Skeleton-BCGxdooP.js → Skeleton-CAwO2JUK.js} +1 -1
  71. package/src/assets/web-panel/assets/{Skills-CwFKgcmm.js → Skills-hKJcP390.js} +1 -1
  72. package/src/assets/web-panel/assets/{Sla-CiXXh9eS.js → Sla-BCFiB8oS.js} +1 -1
  73. package/src/assets/web-panel/assets/{SpeechSettings-WSx2CLqO.js → SpeechSettings-Bi1Y-Tgf.js} +1 -1
  74. package/src/assets/web-panel/assets/{SyncSettings-BBIqQOtW.js → SyncSettings-ZHYDv46g.js} +2 -2
  75. package/src/assets/web-panel/assets/{Tasks-D1BGLjO1.js → Tasks-BMCSrUy-.js} +1 -1
  76. package/src/assets/web-panel/assets/{Templates-CUIl9axA.js → Templates-DF_FOEH8.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tenant-BFZJ0hNz.js → Tenant-C7Q2LriV.js} +1 -1
  78. package/src/assets/web-panel/assets/{Terminal-Cw-3eYVn.js → Terminal-C59ckWXW.js} +2 -2
  79. package/src/assets/web-panel/assets/{TimelineRenderer-bOVPB56L.js → TimelineRenderer-Biu1m6Uf.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tokens-Czfyq2VY.js → Tokens-CoHYWg3-.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trigger-C-o4uJY0.js → Trigger-DglXXzEp.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trust-BKq_S6iF.js → Trust-CBBLh73r.js} +1 -1
  83. package/src/assets/web-panel/assets/{UkeySign-fKlWUvMx.js → UkeySign-DuNdKeiD.js} +1 -1
  84. package/src/assets/web-panel/assets/{VideoEditing-DB5MLuS7.js → VideoEditing-BizHWVrh.js} +1 -1
  85. package/src/assets/web-panel/assets/{Wallet-WGXBn7IS.js → Wallet-ClUQGSKi.js} +4 -4
  86. package/src/assets/web-panel/assets/{WebAuthn-B8TC4EMF.js → WebAuthn-zyD7K5f5.js} +4 -4
  87. package/src/assets/web-panel/assets/{WorkflowEditor-DLY--KmM.js → WorkflowEditor-qbTI37Fi.js} +1 -1
  88. package/src/assets/web-panel/assets/{chat-Crw3XQaA.js → chat-CHv66tBY.js} +1 -1
  89. package/src/assets/web-panel/assets/{colors-CxhWauPV.js → colors-vBsvcJjY.js} +1 -1
  90. package/src/assets/web-panel/assets/{compact-item-Cp3ojtk5.js → compact-item-CdBQZWFX.js} +1 -1
  91. package/src/assets/web-panel/assets/{createContext-CRuRXjSo.js → createContext-CLE2XsPX.js} +1 -1
  92. package/src/assets/web-panel/assets/devWarning-DRQGMdYB.js +1 -0
  93. package/src/assets/web-panel/assets/{hasIn-XGW474dj.js → hasIn-Du5rnUSg.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-C73pqyDb.js → index-9nDAQkO-.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-DHNixOg_.js → index-B-3GrN7D.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-DUSVsOGS.js → index-BDaW0C3l.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-BXnNbbwa.js → index-BY0Jg8JC.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-Yq3bFbYX.js → index-Bdfg7CY3.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BW028Pwn.js → index-BnZkmomS.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DBcBsJYg.js → index-BojUN0eY.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DoUC5_ry.js → index-BrFwv-2v.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CPFam-me.js → index-Bu3v3PRU.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-J_08R33H.js → index-BuSZyAD0.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-WvNZXbIO.js → index-Bwqa-FcB.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-rsACoVT9.js → index-ByEfQiLz.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DhomnuaB.js → index-CKoOU-ne.js} +1 -1
  107. package/src/assets/web-panel/assets/index-CPJgV0Ho.js +1 -0
  108. package/src/assets/web-panel/assets/{index-DfPLIA-f.js → index-CRiOcWZ1.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-BuVA26SD.js → index-Ca0WeKz1.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-E-RSfImO.js → index-Cc53mZoS.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-C8UOVaUH.js → index-CigkcWWh.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-qzmihx1d.js → index-Cuvyt0vv.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-BUWZ57T4.js → index-CvHjeRw2.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BetOkRLs.js → index-CxmlGwpv.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-B5fJS-kn.js → index-Cz48QuqC.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-nJR64pA_.js → index-D-KoBLmE.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-Dp2nC5On.js → index-D-jjL85C.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-BYkjs7eP.js → index-DADajBnD.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-BElgeKJ0.js → index-DHdrZp_q.js} +3 -3
  120. package/src/assets/web-panel/assets/{index-QqAuH7-S.js → index-DHhNie07.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-jrIcbPUa.js → index-DnB7oqAR.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-Ctu98x57.js → index-DsyYG63S.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-CTE32qol.js → index-Dv9b_iFq.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-CdlfrcC-.js → index-DzYEc47A.js} +1 -1
  125. package/src/assets/web-panel/assets/index-OtXVaszG.js +1 -0
  126. package/src/assets/web-panel/assets/{index-CDIpH_8Q.js → index-aYAtijnz.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-38TRdZb6.js → index-dEhWAtoe.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-DxOtBFVy.js → index-q3sGyZnD.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-B45Vkh3T.js → index-sLcRd9pi.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-BVmSfIkJ.js → index-sz6sGerd.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-De2FN0xN.js → index-uHX8ZrJ9.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-W8_0yAi_.js → index-x_0JRAO3.js} +1 -1
  133. package/src/assets/web-panel/assets/{initDefaultProps-DAu-hgme.js → initDefaultProps-CThtsKhS.js} +1 -1
  134. package/src/assets/web-panel/assets/{motion-Db8yk0Hu.js → motion-BoqT16ZT.js} +1 -1
  135. package/src/assets/web-panel/assets/{move-Cii2jOin.js → move-1Jf6ZXg5.js} +1 -1
  136. package/src/assets/web-panel/assets/{mtc-parser-CnZBDkyZ.js → mtc-parser-DjfCYvnq.js} +1 -1
  137. package/src/assets/web-panel/assets/{omit-Buzt1FTL.js → omit-BaJPeP5Y.js} +1 -1
  138. package/src/assets/web-panel/assets/{pickAttrs-CpZ_NmE6.js → pickAttrs-B7nqrfVR.js} +1 -1
  139. package/src/assets/web-panel/assets/{placementArrow-mBrx3dYm.js → placementArrow-Dmb7i435.js} +1 -1
  140. package/src/assets/web-panel/assets/{responsiveObserve-DC_QzljB.js → responsiveObserve-B0TqfHJR.js} +1 -1
  141. package/src/assets/web-panel/assets/{slide-DT_UVED-.js → slide-C9PINvAM.js} +1 -1
  142. package/src/assets/web-panel/assets/{statusUtils-78t6eNLV.js → statusUtils-DAug5z5S.js} +1 -1
  143. package/src/assets/web-panel/assets/{styleChecker-CV_T1ULL.js → styleChecker-o6QvGnrq.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFlexGapSupport-s8edGuXD.js → useFlexGapSupport-CtZwQFCt.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFs-Pk9dH2HC.js → useFs-B0HVNsmA.js} +1 -1
  146. package/src/assets/web-panel/assets/{usePersonalDataHub-B_GqAm8c.js → usePersonalDataHub-CbLIg5eO.js} +1 -1
  147. package/src/assets/web-panel/assets/{vnode-Cxyss24q.js → vnode-uOK2NMHj.js} +1 -1
  148. package/src/assets/web-panel/assets/{zoom-0UY3cOuc.js → zoom-BhyA2sIv.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 +26 -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 +33 -10
  167. package/src/lib/sub-agent-context.js +37 -2
  168. package/src/lib/task-progress-tracker.js +223 -0
  169. package/src/repl/chat-repl.js +60 -10
  170. package/src/runtime/agent-core.js +186 -16
  171. package/src/runtime/agent-runtime.js +20 -1
  172. package/src/runtime/runtime-factory.js +1 -1
  173. package/src/assets/web-panel/assets/ChatBubbleRenderer-CBbMoVuE.js +0 -1
  174. package/src/assets/web-panel/assets/MarkdownRenderer-DJjPaOnM.js +0 -1
  175. package/src/assets/web-panel/assets/devWarning-CKAQY2zn.js +0 -1
  176. package/src/assets/web-panel/assets/index-Cetfwq8j.js +0 -1
  177. package/src/assets/web-panel/assets/index-DOpcRO2-.js +0 -1
@@ -1,8 +1,12 @@
1
1
  import crypto from "node:crypto";
2
+ import { types } from "node:util";
2
3
  import evolutionRun from "@chainlesschain/session-core/evolution-run";
3
4
 
4
5
  import { EvolutionEvidenceArtifactAdapter } from "./evolution-evidence-artifact-adapter.js";
5
- import { EVOLUTION_AGENT_MODEL_PROJECTION_RULESET_DIGEST } from "./evolution-evidence-projector.js";
6
+ import {
7
+ EVOLUTION_AGENT_MODEL_PROJECTION_RULESET_DIGEST,
8
+ EVOLUTION_PROJECTION_RULESET_DIGEST,
9
+ } from "./evolution-evidence-projector.js";
6
10
  import { EvolutionRunLedgerAdapter } from "./evolution-run-ledger-adapter.js";
7
11
  import { captureEvolutionRunWikiMaintenanceProducer } from "./evolution-run-wiki-maintenance-source.js";
8
12
  import { WIKI_MAINTENANCE_TRIGGER_KIND } from "./wiki-maintenance-trigger-ledger-adapter.js";
@@ -35,7 +39,7 @@ function requiredString(value, label) {
35
39
  return value;
36
40
  }
37
41
 
38
- function canonical(value) {
42
+ function canonical(value, seen = new Set()) {
39
43
  if (value === null || typeof value === "boolean") {
40
44
  return JSON.stringify(value);
41
45
  }
@@ -49,17 +53,44 @@ function canonical(value) {
49
53
  if (!value || typeof value !== "object") {
50
54
  throw new TypeError("Agent evolution evidence must be JSON-compatible");
51
55
  }
52
- if (Array.isArray(value)) {
53
- return `[${value.map(canonical).join(",")}]`;
56
+ if (types.isProxy(value) || seen.has(value)) {
57
+ throw new TypeError("Agent evolution evidence must be acyclic plain data");
54
58
  }
59
+ const array = Array.isArray(value);
55
60
  const prototype = Object.getPrototypeOf(value);
56
- if (prototype !== Object.prototype && prototype !== null) {
61
+ if (!array && prototype !== Object.prototype && prototype !== null) {
57
62
  throw new TypeError("Agent evolution evidence must use plain objects");
58
63
  }
59
- return `{${Object.keys(value)
60
- .sort()
61
- .map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`)
62
- .join(",")}}`;
64
+ const keys = Reflect.ownKeys(value).filter(
65
+ (key) => !(array && key === "length"),
66
+ );
67
+ if (
68
+ array &&
69
+ (keys.length !== value.length ||
70
+ keys.some((key, index) => key !== String(index)))
71
+ ) {
72
+ throw new TypeError("Agent evolution evidence arrays must be dense data");
73
+ }
74
+ seen.add(value);
75
+ try {
76
+ const entries = (array ? keys : keys.sort()).map((key) => {
77
+ const property = Object.getOwnPropertyDescriptor(value, key);
78
+ if (
79
+ typeof key !== "string" ||
80
+ !property?.enumerable ||
81
+ !("value" in property)
82
+ ) {
83
+ throw new TypeError(
84
+ "Agent evolution evidence cannot contain accessors or symbols",
85
+ );
86
+ }
87
+ const encoded = canonical(property.value, seen);
88
+ return array ? encoded : `${JSON.stringify(key)}:${encoded}`;
89
+ });
90
+ return array ? `[${entries.join(",")}]` : `{${entries.join(",")}}`;
91
+ } finally {
92
+ seen.delete(value);
93
+ }
63
94
  }
64
95
 
65
96
  function clone(value) {
@@ -106,6 +137,7 @@ export function createAgentEvolutionIngress({
106
137
  evidenceAdapter,
107
138
  runAdapter,
108
139
  sourceEnvelopeAuthority,
140
+ openCacheSourceRun = null,
109
141
  wikiMaintenanceProducer = null,
110
142
  releaseTrain = null,
111
143
  completionTriggerKind = WIKI_MAINTENANCE_TRIGGER_KIND.SESSION_END,
@@ -144,27 +176,40 @@ export function createAgentEvolutionIngress({
144
176
  sourceEnvelopeAuthority,
145
177
  );
146
178
  const descriptor = runAdapter.descriptor;
179
+ if (openCacheSourceRun !== null && typeof openCacheSourceRun !== "function")
180
+ throw new TypeError("cache source Run opener must be a function");
147
181
  let tail = Promise.resolve();
148
- let modelAdmissionFailure = null;
182
+ let admissionFailure = null;
183
+ let lastModelResponse = null;
184
+ let modelAdmissionPending = false;
149
185
 
150
- const serialize = (operation, latchModelFailure = false) => {
151
- const invoke = latchModelFailure
152
- ? async () => {
153
- try {
154
- return await operation();
155
- } catch (cause) {
156
- // Latch inside the serialized operation, before releasing the queue.
157
- // A complete() already queued by another caller cannot win this race.
158
- modelAdmissionFailure = ingressFailure(cause);
159
- throw modelAdmissionFailure;
160
- }
161
- }
162
- : operation;
186
+ const serialize = (operation) => {
187
+ const invoke = async () => {
188
+ if (admissionFailure !== null) throw admissionFailure;
189
+ try {
190
+ return await operation();
191
+ } catch (cause) {
192
+ // Every evidence boundary is fail-stop, not just model admission.
193
+ // Latch before releasing queued requests or completion operations.
194
+ admissionFailure ??= ingressFailure(cause);
195
+ throw admissionFailure;
196
+ }
197
+ };
163
198
  const pending = tail.then(invoke, invoke);
164
199
  tail = pending.catch(() => undefined);
165
200
  return pending;
166
201
  };
167
202
 
203
+ const cloneEvidence = (value) => {
204
+ if (admissionFailure !== null) throw admissionFailure;
205
+ try {
206
+ return clone(value);
207
+ } catch (cause) {
208
+ admissionFailure = ingressFailure(cause);
209
+ throw admissionFailure;
210
+ }
211
+ };
212
+
168
213
  const currentTimestamp = () => {
169
214
  const value = now();
170
215
  const iso = value instanceof Date ? value.toISOString() : value;
@@ -190,10 +235,16 @@ export function createAgentEvolutionIngress({
190
235
  }).projection;
191
236
  };
192
237
 
193
- const ingest = (kind, evidence, options = {}, modelRequest = null) =>
238
+ const ingest = (
239
+ kind,
240
+ evidence,
241
+ options = {},
242
+ modelRequest = null,
243
+ cacheRecord = false,
244
+ ) =>
194
245
  guardIngress(
195
246
  serialize(async () => {
196
- if (modelAdmissionFailure !== null) throw modelAdmissionFailure;
247
+ if (admissionFailure !== null) throw admissionFailure;
197
248
  const projection = appendStarted();
198
249
  if (projection.status === "completed") {
199
250
  throw new Error(
@@ -208,7 +259,17 @@ export function createAgentEvolutionIngress({
208
259
  options.occurredAt ?? currentTimestamp(),
209
260
  "Agent evidence occurredAt",
210
261
  );
211
- const payload = modelRequest ?? clone(evidence);
262
+ if (cacheRecord && lastModelResponse === null)
263
+ throw new Error("Cache receipt requires a recorded model response");
264
+ const payload = cacheRecord
265
+ ? {
266
+ schema: "chainlesschain.model-response-cache/v1",
267
+ requestKey: evidence.requestKey,
268
+ sourceRunId: descriptor.runId,
269
+ sourceEventId: lastModelResponse.eventId,
270
+ responseEvent: clone(lastModelResponse.event),
271
+ }
272
+ : (modelRequest ?? clone(evidence));
212
273
  const sourceEnvelope = await issueSourceEnvelope(
213
274
  Object.freeze({
214
275
  schema: AGENT_EVOLUTION_INGRESS_SCHEMA,
@@ -259,6 +320,21 @@ export function createAgentEvolutionIngress({
259
320
  derivationManifestDigest: persisted.manifest.digest,
260
321
  },
261
322
  });
323
+ if (kind === "model-input") {
324
+ lastModelResponse = null;
325
+ modelAdmissionPending = true;
326
+ } else if (kind === "response-completed" && modelAdmissionPending) {
327
+ lastModelResponse = { eventId, event: clone(payload.event) };
328
+ modelAdmissionPending = false;
329
+ }
330
+ if (cacheRecord)
331
+ return clone({
332
+ schema: "chainlesschain.model-response-cache-receipt/v1",
333
+ tenantId: descriptor.tenantId,
334
+ runId: descriptor.runId,
335
+ eventId,
336
+ artifact: persisted,
337
+ });
262
338
  if (modelRequest === null) return appended;
263
339
  // Resolve the published manifest and every attested component afresh.
264
340
  // The prototype call requires the real adapter's private state; an
@@ -284,49 +360,164 @@ export function createAgentEvolutionIngress({
284
360
  ) {
285
361
  throw new Error("Agent model projection Run frontier changed");
286
362
  }
287
- if (modelAdmissionFailure !== null) throw modelAdmissionFailure;
363
+ if (admissionFailure !== null) throw admissionFailure;
288
364
  return buildAgentModelRequest(
289
365
  modelRequest,
290
366
  resolved.bundle.modelProjection,
291
367
  );
292
- }, modelRequest !== null),
368
+ }),
293
369
  );
294
370
 
295
371
  const ingress = Object.freeze({
296
372
  schema: AGENT_EVOLUTION_INGRESS_SCHEMA,
297
373
  tenantId: descriptor.tenantId,
298
374
  runId: descriptor.runId,
375
+ createResponseCacheReceipt: async (input) => {
376
+ const snapshot = cloneEvidence(input);
377
+ const requestKey = snapshot?.requestKey;
378
+ if (
379
+ typeof requestKey !== "string" ||
380
+ !/^[a-f0-9]{64}$/.test(requestKey)
381
+ ) {
382
+ admissionFailure ??= ingressFailure(
383
+ new TypeError("Cache request key must be SHA-256"),
384
+ );
385
+ throw admissionFailure;
386
+ }
387
+ return ingest("model-response-cache", { requestKey }, {}, null, true);
388
+ },
389
+ replayResponseCache: async (input) => {
390
+ const snapshot = cloneEvidence(input);
391
+ const response = await guardIngress(
392
+ serialize(async () => {
393
+ const { receipt, requestKey } = snapshot;
394
+ if (
395
+ typeof requestKey !== "string" ||
396
+ !/^[a-f0-9]{64}$/.test(requestKey) ||
397
+ !receipt ||
398
+ receipt.schema !==
399
+ "chainlesschain.model-response-cache-receipt/v1" ||
400
+ receipt.tenantId !== descriptor.tenantId ||
401
+ !openCacheSourceRun
402
+ )
403
+ throw new Error("Invalid or cross-tenant response cache receipt");
404
+ const opened = openCacheSourceRun(receipt.runId);
405
+ const source = opened?.runAdapter;
406
+ if (
407
+ !(source instanceof EvolutionRunLedgerAdapter) ||
408
+ !(
409
+ opened.evidenceAdapter instanceof EvolutionEvidenceArtifactAdapter
410
+ ) ||
411
+ source.descriptor.tenantId !== descriptor.tenantId ||
412
+ source.descriptor.runId !== receipt.runId
413
+ )
414
+ throw new Error("Unbound response cache source Run");
415
+ const loaded = source.load();
416
+ const event = loaded.events.find(
417
+ (item) => item.eventId === receipt.eventId,
418
+ );
419
+ if (
420
+ loaded.projection?.status !== "completed" ||
421
+ event?.data?.evidenceKind !== "model-response-cache" ||
422
+ event.subjectId !== receipt.artifact?.evidenceId ||
423
+ event.artifactRef !== receipt.artifact?.manifest?.ref?.ref ||
424
+ event.payloadDigest !== receipt.artifact?.manifest?.digest
425
+ )
426
+ throw new Error(
427
+ "Cache receipt is not committed in a completed Run",
428
+ );
429
+ const resolved =
430
+ await EvolutionEvidenceArtifactAdapter.prototype.resolve.call(
431
+ opened.evidenceAdapter,
432
+ receipt.artifact,
433
+ );
434
+ const projection = resolved.bundle.modelProjection;
435
+ const record = projection.content;
436
+ if (
437
+ resolved.verification.verified !== true ||
438
+ resolved.verification.tenantId !== descriptor.tenantId ||
439
+ projection.rulesetDigest !== EVOLUTION_PROJECTION_RULESET_DIGEST ||
440
+ projection.visibility !== "model-visible" ||
441
+ projection.truncated ||
442
+ projection.injectionFindings.length !== 0 ||
443
+ record?.schema !== "chainlesschain.model-response-cache/v1" ||
444
+ record.requestKey !== requestKey ||
445
+ record.sourceRunId !== receipt.runId ||
446
+ record.responseEvent?.type !== "response-complete"
447
+ )
448
+ throw new Error(
449
+ "Cache response projection is not safe or request-bound",
450
+ );
451
+ const responseEvent = loaded.events.find(
452
+ (item) => item.eventId === record.sourceEventId,
453
+ );
454
+ if (
455
+ responseEvent?.data?.evidenceKind !== "response-completed" ||
456
+ responseEvent.sequence >= event.sequence
457
+ )
458
+ throw new Error("Cache receipt lacks its preceding model response");
459
+ // Reopen after asynchronous attestation checks; no cached Run authority.
460
+ if (digest(source.load()) !== digest(loaded))
461
+ throw new Error("Cache source Run changed during verification");
462
+ return clone(record.responseEvent);
463
+ }),
464
+ );
465
+ await ingest("model-response-cache-replayed", {
466
+ requestKey: snapshot.requestKey,
467
+ sourceReceipt: snapshot.receipt,
468
+ responseEvent: response,
469
+ });
470
+ return response;
471
+ },
299
472
  start: () => guardIngress(serialize(() => appendStarted())),
300
473
  prepareModelRequest: (request) => {
301
- if (modelAdmissionFailure !== null)
302
- return Promise.reject(modelAdmissionFailure);
474
+ if (admissionFailure !== null) return Promise.reject(admissionFailure);
303
475
  let snapshot;
304
476
  try {
305
477
  snapshot = snapshotAgentModelRequest(request);
306
478
  } catch (error) {
307
- modelAdmissionFailure = ingressFailure(error);
308
- return Promise.reject(modelAdmissionFailure);
479
+ admissionFailure = ingressFailure(error);
480
+ return Promise.reject(admissionFailure);
309
481
  }
310
482
  return ingest("model-input", snapshot, {}, snapshot);
311
483
  },
312
- ingestUserPrompt: (input, options) =>
313
- ingest("user-prompt", { input: clone(input) }, options),
314
- ingestAgentEvent: (event, options) => {
315
- const baseKind = CORE_EVENT_KINDS.get(event?.type);
484
+ ingestUserPrompt: async (input, options) =>
485
+ ingest("user-prompt", { input: cloneEvidence(input) }, options),
486
+ ingestAgentEvent: async (event, options) => {
487
+ if (admissionFailure !== null) throw admissionFailure;
488
+ let type;
489
+ try {
490
+ if (types.isProxy(event))
491
+ throw new TypeError("Agent event cannot be a Proxy");
492
+ const property =
493
+ event && typeof event === "object"
494
+ ? Object.getOwnPropertyDescriptor(event, "type")
495
+ : null;
496
+ if (property && !("value" in property))
497
+ throw new TypeError("Agent event type cannot be an accessor");
498
+ type = property?.value;
499
+ } catch (cause) {
500
+ admissionFailure = ingressFailure(cause);
501
+ throw admissionFailure;
502
+ }
503
+ const baseKind = CORE_EVENT_KINDS.get(type);
316
504
  if (!baseKind) {
317
505
  return Promise.resolve(Object.freeze({ ignored: true }));
318
506
  }
507
+ const snapshot = cloneEvidence(event);
319
508
  const kind =
320
- event.type === "tool-result" &&
321
- Boolean(event.error || event.result?.error || event.result?.isError)
509
+ type === "tool-result" &&
510
+ Boolean(
511
+ snapshot.error || snapshot.result?.error || snapshot.result?.isError,
512
+ )
322
513
  ? "tool-failed"
323
514
  : baseKind;
324
- return ingest(kind, { event: clone(event) }, options);
515
+ return ingest(kind, { event: snapshot }, options);
325
516
  },
326
517
  complete: (options = {}) =>
327
518
  guardIngress(
328
519
  serialize(async () => {
329
- if (modelAdmissionFailure !== null) throw modelAdmissionFailure;
520
+ if (admissionFailure !== null) throw admissionFailure;
330
521
  const loaded = runAdapter.load();
331
522
  let projection;
332
523
  if (loaded.projection?.status === "completed") {
@@ -122,7 +122,7 @@ function normalizeClock(clock) {
122
122
  });
123
123
  }
124
124
 
125
- function layout(stateRootDir, tenantId, runId) {
125
+ function layout(stateRootDir, tenantId, runId, initialize = true) {
126
126
  if (typeof stateRootDir !== "string" || stateRootDir.trim() === "") {
127
127
  throw new TypeError("stateRootDir is required");
128
128
  }
@@ -140,10 +140,11 @@ function layout(stateRootDir, tenantId, runId) {
140
140
  ledgerAuthorityRootDir: path.join(scope, "ledger-authority"),
141
141
  witnessFilePath: path.join(scope, "witness", "checkpoint.json"),
142
142
  });
143
- fs.mkdirSync(path.dirname(result.witnessFilePath), {
144
- recursive: true,
145
- mode: 0o700,
146
- });
143
+ if (initialize)
144
+ fs.mkdirSync(path.dirname(result.witnessFilePath), {
145
+ recursive: true,
146
+ mode: 0o700,
147
+ });
147
148
  return result;
148
149
  }
149
150
 
@@ -350,6 +351,26 @@ export function createAgentEvolutionRuntimeComposition({
350
351
  ...(witnessMaximumBytes === undefined ? {} : { witnessMaximumBytes }),
351
352
  });
352
353
  captureEvolutionLedgerFileBackend(backend);
354
+ const cacheSourceAuthorities = Object.freeze(
355
+ Object.fromEntries(
356
+ ["ledger", "witness"].map((kind) => [
357
+ kind,
358
+ Object.freeze({
359
+ trust: Object.freeze({ ...backend.descriptor[`${kind}Trust`] }),
360
+ signer: captureAuthority(
361
+ authorities[kind].signer,
362
+ "sign",
363
+ `cache ${kind} signer`,
364
+ ),
365
+ verifier: captureAuthority(
366
+ authorities[kind].verifier,
367
+ "verify",
368
+ `cache ${kind} verifier`,
369
+ ),
370
+ }),
371
+ ]),
372
+ ),
373
+ );
353
374
  const runAdapter = new EvolutionRunLedgerAdapter({
354
375
  descriptor: {
355
376
  tenantId,
@@ -459,6 +480,65 @@ export function createAgentEvolutionRuntimeComposition({
459
480
  const evolutionIngress = createAgentEvolutionIngress({
460
481
  evidenceAdapter,
461
482
  runAdapter,
483
+ openCacheSourceRun: (input) => {
484
+ const sourceRunId = identifier(input, "cache source runId");
485
+ const sourceStorage = layout(
486
+ storage.rootDir,
487
+ tenantId,
488
+ sourceRunId,
489
+ false,
490
+ );
491
+ if (!fs.existsSync(sourceStorage.witnessFilePath))
492
+ throw new Error("Cache source Run witness does not exist");
493
+ const sourcePorts = new EvolutionArtifactPorts({
494
+ tenantId,
495
+ audience,
496
+ artifactStore: new ArtifactStore({
497
+ dir: sourceStorage.artifactDir,
498
+ now: clock,
499
+ }),
500
+ envelopeSigner: ports.artifactEnvelopeSigner,
501
+ envelopeVerifier: ports.artifactEnvelopeVerifier,
502
+ currentAuthorityResolver: ports.artifactCurrentAuthorityResolver,
503
+ now: clock,
504
+ });
505
+ const sourceResolver = sourcePorts.createEvolutionLedgerArtifactResolver({
506
+ purpose: "evolution-ledger",
507
+ });
508
+ const sourceBackend = createEvolutionLedgerFileBackend({
509
+ rootDir: sourceStorage.ledgerRootDir,
510
+ authorityRootDir: sourceStorage.ledgerAuthorityRootDir,
511
+ witnessFilePath: sourceStorage.witnessFilePath,
512
+ witnessId: witnessIdInput ?? defaultWitnessId(tenantId, sourceRunId),
513
+ ledgerAuthority: cacheSourceAuthorities.ledger,
514
+ witnessAuthority: cacheSourceAuthorities.witness,
515
+ artifactResolver: sourceResolver,
516
+ secure,
517
+ clock,
518
+ ...(fsImpl === undefined ? {} : { fsImpl }),
519
+ ...(lock === undefined ? {} : { lock }),
520
+ ...(random === undefined ? {} : { random }),
521
+ ...(lockTimeoutMs === undefined ? {} : { lockTimeoutMs }),
522
+ ...(witnessMaximumBytes === undefined ? {} : { witnessMaximumBytes }),
523
+ });
524
+ return {
525
+ runAdapter: new EvolutionRunLedgerAdapter({
526
+ descriptor: { ...runAdapter.descriptor, runId: sourceRunId },
527
+ artifactPorts: sourcePorts,
528
+ ledger: sourceBackend.ledger,
529
+ ledgerArtifactResolver: sourceResolver,
530
+ now: clock,
531
+ }),
532
+ evidenceAdapter: new EvolutionEvidenceArtifactAdapter({
533
+ tenantId,
534
+ audience,
535
+ projector,
536
+ bundleVerifier,
537
+ artifactPorts: sourcePorts,
538
+ ...(evidenceTtlMs === undefined ? {} : { ttlMs: evidenceTtlMs }),
539
+ }),
540
+ };
541
+ },
462
542
  sourceEnvelopeAuthority: ports.sourceEnvelope,
463
543
  wikiMaintenanceProducer,
464
544
  releaseTrain,
@@ -9,9 +9,15 @@ export const EVOLUTION_DEPLOYMENT_DESCRIPTOR_SCHEMA =
9
9
  const DIGEST = /^sha256:[a-f0-9]{64}$/u;
10
10
  const SUPPORTED_COMMANDS = new Set([
11
11
  "agent",
12
+ "ask",
13
+ "chat",
14
+ "compact",
15
+ "complete",
16
+ "cowork",
12
17
  "desktop",
13
18
  "evolution",
14
19
  "marketplace",
20
+ "orchestrate",
15
21
  "serve",
16
22
  ]);
17
23
 
@@ -273,7 +279,17 @@ async function loadBuiltInFactories(commandName) {
273
279
  new GovernedKnowledgeQuarantineReleaseLedger(options),
274
280
  });
275
281
  }
276
- if (commandName === "agent" || commandName === "serve") {
282
+ if (
283
+ commandName === "agent" ||
284
+ commandName === "ask" ||
285
+ commandName === "chat" ||
286
+ commandName === "compact" ||
287
+ commandName === "complete" ||
288
+ commandName === "desktop" ||
289
+ commandName === "cowork" ||
290
+ commandName === "orchestrate" ||
291
+ commandName === "serve"
292
+ ) {
277
293
  const { createAgentEvolutionRuntimeComposition } =
278
294
  await import("./agent-evolution-runtime-composition.js");
279
295
  factories.createAgentEvolutionRuntimeComposition =
@@ -457,6 +457,19 @@ const RULESET_DIGEST = `sha256:${createHash("sha256")
457
457
  )
458
458
  .digest("hex")}`;
459
459
 
460
+ // Keep v2 and every Agent ruleset byte-identical for historical verification.
461
+ // New raw-event projections scan finite numeric scalars as well as strings;
462
+ // encrypted Raw remains unchanged, including the original numeric types.
463
+ const RAW_RULESET_V3 = Object.freeze({
464
+ ...RULESET,
465
+ schema: "chainlesschain.evolution-projection-rules/v3",
466
+ version: 3,
467
+ numericScalarPolicy: "safe-integer-sensitive-text-redaction-v1",
468
+ });
469
+ const RAW_RULESET_V3_DIGEST = `sha256:${createHash("sha256")
470
+ .update(`${RAW_RULESET_V3.schema}\0${JSON.stringify(RAW_RULESET_V3)}`, "utf8")
471
+ .digest("hex")}`;
472
+
460
473
  // A separate policy keeps existing v2 artifacts readable without changing
461
474
  // their meaning/digest. Agent messages are authenticated and scanned as whole
462
475
  // fields; the existing total model-content ceiling still applies. Never scan
@@ -512,6 +525,7 @@ export const EVOLUTION_AGENT_MODEL_PROJECTION_RULESET_DIGEST = `sha256:${createH
512
525
  .digest("hex")}`;
513
526
  const SUPPORTED_RULESETS = new Map([
514
527
  [RULESET_DIGEST, RULESET],
528
+ [RAW_RULESET_V3_DIGEST, RAW_RULESET_V3],
515
529
  [AGENT_MODEL_RULESET_V1_DIGEST, AGENT_MODEL_RULESET_V1],
516
530
  [EVOLUTION_AGENT_MODEL_PROJECTION_RULESET_V2_DIGEST, AGENT_MODEL_RULESET_V2],
517
531
  [EVOLUTION_AGENT_MODEL_PROJECTION_RULESET_DIGEST, AGENT_MODEL_RULESET],
@@ -1300,7 +1314,7 @@ function sanitizePayload(
1300
1314
  "Raw payload contains a non-finite number",
1301
1315
  );
1302
1316
  }
1303
- if (jsonText) {
1317
+ if (jsonText || ruleset.numericScalarPolicy) {
1304
1318
  if (Number.isInteger(value) && !Number.isSafeInteger(value)) {
1305
1319
  throw projectionError(
1306
1320
  EVOLUTION_PROJECTION_INVALID_CODE,
@@ -3107,7 +3121,7 @@ function validateBundleIntegrity(bundle) {
3107
3121
  }
3108
3122
  }
3109
3123
  if (
3110
- ruleset.jsonTextPolicy &&
3124
+ (ruleset.jsonTextPolicy || ruleset.numericScalarPolicy) &&
3111
3125
  canonicalJson(sanitizePayload(model.content, ruleset).content) !==
3112
3126
  canonicalJson(model.content)
3113
3127
  ) {
@@ -3347,7 +3361,7 @@ export class EvolutionEvidenceProjector {
3347
3361
  }
3348
3362
 
3349
3363
  project(input) {
3350
- return this.#project(input, RULESET);
3364
+ return this.#project(input, RAW_RULESET_V3);
3351
3365
  }
3352
3366
 
3353
3367
  projectAgentModelRequest(input) {
@@ -3615,10 +3629,14 @@ export class EvolutionEvidenceProjector {
3615
3629
  sanitized,
3616
3630
  ruleset === AGENT_MODEL_RULESET
3617
3631
  ? EVOLUTION_AGENT_MODEL_PROJECTION_RULESET_DIGEST
3618
- : RULESET_DIGEST,
3632
+ : RAW_RULESET_V3_DIGEST,
3619
3633
  );
3620
3634
  const trustedSanitized = source.compilable
3621
- ? sanitizePayload(source.trustedPayload, RULESET, valuePatterns(ruleset))
3635
+ ? sanitizePayload(
3636
+ source.trustedPayload,
3637
+ ruleset === RAW_RULESET_V3 ? RAW_RULESET_V3 : RULESET,
3638
+ valuePatterns(ruleset),
3639
+ )
3622
3640
  : null;
3623
3641
  const trustedInputStructured =
3624
3642
  source.compilable && isStructuredTrustedPayload(source.trustedPayload);
@@ -4077,4 +4095,5 @@ Object.freeze(EvolutionEvidenceProjector.prototype);
4077
4095
  Object.freeze(EvolutionEvidenceBundleVerifier.prototype);
4078
4096
  Object.freeze(EvolutionEvidenceReader.prototype);
4079
4097
 
4080
- export const EVOLUTION_PROJECTION_RULESET_DIGEST = RULESET_DIGEST;
4098
+ export const EVOLUTION_PROJECTION_RULESET_V2_DIGEST = RULESET_DIGEST;
4099
+ export const EVOLUTION_PROJECTION_RULESET_DIGEST = RAW_RULESET_V3_DIGEST;
@@ -1,5 +1,15 @@
1
1
  import { isAbortError } from "./abort-utils.js";
2
2
 
3
+ export function isEvolutionIngressFailure(error) {
4
+ const visited = new Set();
5
+ for (let current = error; current; current = current.cause) {
6
+ if (visited.has(current) || visited.size >= 32) return true;
7
+ visited.add(current);
8
+ if (current.code === "CC_AGENT_EVOLUTION_INGRESS_FAILED") return true;
9
+ }
10
+ return false;
11
+ }
12
+
3
13
  // Admission failures are not provider outages, even when their causes contain
4
14
  // HTTP status codes or retryable/authentication words.
5
15
  export function isTerminalModelFailure(error) {