chainlesschain 0.166.18 → 0.166.21

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 (214) hide show
  1. package/package.json +2 -2
  2. package/src/assets/web-panel/assets/{AIOps-CQSBl3hY.js → AIOps-BjMnsUci.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-IQt-vRLt.js → ActionButton-DdYFP03A.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-DkHC8O7k.js → Analytics-Bb8TuuK_.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-CSti2P2T.js → AppLayout-Kn3TIOtk.js} +5 -5
  6. package/src/assets/web-panel/assets/{Artifacts-C57hxn3v.js → Artifacts-4IxpqI_b.js} +1 -1
  7. package/src/assets/web-panel/assets/{Audit-DByLntcf.js → Audit-BOV2caqU.js} +1 -1
  8. package/src/assets/web-panel/assets/{BackgroundAgents-D1Bd2EOa.js → BackgroundAgents-B86k-ay4.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-VstHzHng.js → Backup-C5_ie1e3.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-CLhdexIf.js → BaseInput-xpwg6QCW.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-BefC_JZS.js → Chat-CVZOcZau.js} +6 -6
  12. package/src/assets/web-panel/assets/{ChatBubbleRenderer-DbXMvgmn.js → ChatBubbleRenderer-D8fPYhUu.js} +1 -1
  13. package/src/assets/web-panel/assets/{Checkbox-CEY982vx.js → Checkbox-MKTq3zdP.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-Dcm_DTvJ.js → Codegen-JUk3wzep.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-C8SSu4KA.js → Col-JPvTA0kC.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-BVV9vwRR.js → Community-Tqgl87NQ.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-B7c5Vo18.js → Compact-BuAFYBmN.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-Tq9jSZ5a.js → Compliance-CXS9WIPZ.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-BJUjT09Q.js → Cowork-Ds2bFHrr.js} +2 -2
  20. package/src/assets/web-panel/assets/{Cron-CjV9PEaS.js → Cron-C_dV_OeW.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-Dl7ReL8F.js → Crosschain-BsO6tIRo.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-CG8PjWmM.js → DID-rNOFqBac.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-CDBM6wmF.js → Dashboard-C2fcKKVY.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-8_55bXTD.js → Dropdown-Y7Ndr0X_.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-D3qOU1Cm.js → EmailListRenderer-DcP_uPmL.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-Bv5oWMZF.js → FamilyGuardDashboard-Cwn3gDzk.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-hpZ1xkKd.js → Federation-ClQuOsqb.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-BN7GT191.js → FormItemContext-DfwtmlcK.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-PCRhfA7M.js → GenericCardRenderer-zNZhtbC5.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-CIlP2vy7.js → Git-BZmdW-G5.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-81lgm7YL.js → Governance-CqBk4lEn.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-Cs24xMOV.js → Inference-Dbmt3ZXk.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-CrJLVCZo.js → KnowledgeGraph-hMTH6qf3.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-DLyO8RKT.js → Logs-CkiYgiW2.js} +2 -2
  35. package/src/assets/web-panel/assets/{MarkdownRenderer-DBOqijrP.js → MarkdownRenderer-BL1FElXg.js} +1 -1
  36. package/src/assets/web-panel/assets/{Marketplace-Dz7AbQZc.js → Marketplace-CbB6wfin.js} +1 -1
  37. package/src/assets/web-panel/assets/{McpTools-BM0aFiWv.js → McpTools-BSwiFtte.js} +3 -3
  38. package/src/assets/web-panel/assets/{Memory-C9SJzENX.js → Memory-B03PeHrz.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileBridge-BO2HnNRk.js → MobileBridge-CRGrnd-X.js} +1 -1
  40. package/src/assets/web-panel/assets/{MobileProjects-CK_jMz0l.js → MobileProjects-CE_5v2kO.js} +1 -1
  41. package/src/assets/web-panel/assets/{Mtc-CfhrJsdO.js → Mtc-Dp11QVx1.js} +2 -2
  42. package/src/assets/web-panel/assets/{MtcAudit-BE2ELxgI.js → MtcAudit-CYu-3JBu.js} +5 -5
  43. package/src/assets/web-panel/assets/{Multisig-CgR_E3Jd.js → Multisig-CGyJ0Xl3.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-Cw9445_K.js → NLProgramming-CoWi_ov1.js} +1 -1
  45. package/src/assets/web-panel/assets/Notes-CgU9DDo9.js +7 -0
  46. package/src/assets/web-panel/assets/{NotificationSettings-DxHVh4uT.js → NotificationSettings-DX4I2b4W.js} +1 -1
  47. package/src/assets/web-panel/assets/OrderTableRenderer-CwHc15Zs.js +1 -0
  48. package/src/assets/web-panel/assets/{Organization-pPXJtWo4.js → Organization-oopLO_tk.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-YamdTJwA.js → Overflow-BFVvjMyf.js} +1 -1
  50. package/src/assets/web-panel/assets/{P2P-BvqP53x7.js → P2P-CBy5t-Tk.js} +2 -2
  51. package/src/assets/web-panel/assets/{PdhVaultBrowser-Blz1Xn2n.js → PdhVaultBrowser--YWJNsu6.js} +3 -3
  52. package/src/assets/web-panel/assets/{Permissions-CgFRQqFJ.js → Permissions-C2dZ8scb.js} +4 -4
  53. package/src/assets/web-panel/assets/{PersonalDataHub-CFeo3-6O.js → PersonalDataHub-Bs3l7Hlx.js} +4 -4
  54. package/src/assets/web-panel/assets/{Pipeline-BkaRojEK.js → Pipeline-DEBWbZuD.js} +1 -1
  55. package/src/assets/web-panel/assets/{Privacy-BNZEx2Qp.js → Privacy-CjHBb6NU.js} +1 -1
  56. package/src/assets/web-panel/assets/{ProjectInit-HUBOgEEK.js → ProjectInit-D2WipUz5.js} +2 -2
  57. package/src/assets/web-panel/assets/ProjectSettings-B6WfnrGB.js +2 -0
  58. package/src/assets/web-panel/assets/{Projects-Dc517BXp.js → Projects-FF_thRi6.js} +1 -1
  59. package/src/assets/web-panel/assets/{Providers-DTLf8bgj.js → Providers-CCv5M_Dv.js} +1 -1
  60. package/src/assets/web-panel/assets/{QrScannerModal-BBNjPszk.js → QrScannerModal-CGthxU54.js} +1 -1
  61. package/src/assets/web-panel/assets/{QuickAsk-DCsHvk3G.js → QuickAsk-CnPmXPFb.js} +1 -1
  62. package/src/assets/web-panel/assets/{Recommend-Dpr5YSop.js → Recommend-Df_tGEa9.js} +1 -1
  63. package/src/assets/web-panel/assets/{RemoteSession-DmKnvqGg.js → RemoteSession-Z58N0Loe.js} +2 -2
  64. package/src/assets/web-panel/assets/{Reputation-CSRfuurX.js → Reputation-CZTBQ2Vt.js} +1 -1
  65. package/src/assets/web-panel/assets/{Row-CDj3pQ_w.js → Row-CdK3YpCQ.js} +1 -1
  66. package/src/assets/web-panel/assets/{RssFeed-DI0a_kNq.js → RssFeed-CFMVT5sb.js} +3 -3
  67. package/src/assets/web-panel/assets/{Search-jAy7B2nU.js → Search-DrF8RIvD.js} +1 -1
  68. package/src/assets/web-panel/assets/{Security-CkHTqYhc.js → Security-Ddk2f2DM.js} +4 -4
  69. package/src/assets/web-panel/assets/{Services-CP-0Nzga.js → Services-CCuK-VOo.js} +2 -2
  70. package/src/assets/web-panel/assets/{Skeleton-BkF5-p3n.js → Skeleton-DxCpHzeM.js} +1 -1
  71. package/src/assets/web-panel/assets/{Skills-BDu-utDE.js → Skills-t2oTDgcv.js} +1 -1
  72. package/src/assets/web-panel/assets/{Sla-CQvq_2Qb.js → Sla-Df63M9_R.js} +1 -1
  73. package/src/assets/web-panel/assets/{SpeechSettings-T7Ap512g.js → SpeechSettings-l7ox6KuX.js} +1 -1
  74. package/src/assets/web-panel/assets/{SyncSettings-Bt-PLvot.js → SyncSettings-COd_tgPp.js} +2 -2
  75. package/src/assets/web-panel/assets/{Tasks-yLEcCogg.js → Tasks-CzDCcrik.js} +1 -1
  76. package/src/assets/web-panel/assets/{Templates-ByN3fmbr.js → Templates-D-vfxTGA.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tenant-DBI7hITH.js → Tenant-BlpT_Gxc.js} +1 -1
  78. package/src/assets/web-panel/assets/{Terminal-B77_DlGX.js → Terminal-D5rq52Hg.js} +2 -2
  79. package/src/assets/web-panel/assets/TimelineRenderer-DdoMndkK.js +1 -0
  80. package/src/assets/web-panel/assets/{Tokens-BV2N6cR8.js → Tokens-BhgBsI6g.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trigger-CjXWGH3p.js → Trigger-DwwzoikZ.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trust-uqXIq3WC.js → Trust-HkTpzXFb.js} +1 -1
  83. package/src/assets/web-panel/assets/{UkeySign-D-6qu4vY.js → UkeySign-D9nk6Ehe.js} +1 -1
  84. package/src/assets/web-panel/assets/{VideoEditing-CxGmx_2e.js → VideoEditing-BKk0rfoy.js} +1 -1
  85. package/src/assets/web-panel/assets/{Wallet-DSq7WlAg.js → Wallet-IVWIU_Lq.js} +4 -4
  86. package/src/assets/web-panel/assets/{WebAuthn-CDBiD57O.js → WebAuthn-CFTCpfsG.js} +4 -4
  87. package/src/assets/web-panel/assets/{WorkflowEditor-Z8f63TSb.js → WorkflowEditor-Dnf4Obif.js} +1 -1
  88. package/src/assets/web-panel/assets/{chat-B-UZFBjy.js → chat-D2snERdj.js} +1 -1
  89. package/src/assets/web-panel/assets/{colors-CFk7K-7Q.js → colors-DKEjK1N1.js} +1 -1
  90. package/src/assets/web-panel/assets/{compact-item-X0IVMvgi.js → compact-item-BEDLwQdt.js} +1 -1
  91. package/src/assets/web-panel/assets/{createContext-DWg4j2n6.js → createContext-DA9iW1a0.js} +1 -1
  92. package/src/assets/web-panel/assets/devWarning-DyhgpXPf.js +1 -0
  93. package/src/assets/web-panel/assets/{hasIn-CkVCwNNF.js → hasIn-5l2xEcY9.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-BipwEbTA.js → index-5pW4t1iD.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-5OcZHdzc.js → index-7P1b8HZo.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-Cvwu_rA_.js → index-B00GeekA.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-CbIAWbma.js → index-B4QYBliR.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-CNKFsBlz.js → index-B7_W_rYd.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BoskgPt9.js → index-BO9dQjpt.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CvOa-IFV.js → index-BZ5lY2zx.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-_-9k3Tna.js → index-B_eCoZgW.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CbihMThv.js → index-BgfImyZI.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DLSBks8h.js → index-Bq5P3piS.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-LU54bChK.js → index-Bqc8tdIF.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-Btqk6zWb.js → index-C7sKbM5s.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-D8uEL8Uw.js → index-CGlotREA.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-CLlP1E4X.js → index-CRPrHE7h.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DeWKPQGs.js → index-CX1x4AFn.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Db_5xhrU.js → index-CbTPvp2_.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-CDfSD07S.js → index-CjWltbi_.js} +1 -1
  111. package/src/assets/web-panel/assets/index-Ck1jhFE0.js +1 -0
  112. package/src/assets/web-panel/assets/{index-BPBia4b-.js → index-CkMKuqUs.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-C1ZAOJRW.js → index-CmruhzFi.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-P83LDnCz.js → index-Csfb-7hw.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-DcDggpWR.js → index-CxEtQYdi.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-OjnAwUJo.js → index-D7z4zB_a.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-D-EJNxgR.js → index-DLoalqRX.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-B3-B3FWD.js → index-DU2TXJu-.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-D92g4l3n.js → index-DXet1xol.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-Ca0mij1n.js → index-Dbd7eEex.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-DCqpl_E_.js → index-Dbkghqn_.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DyWlOuak.js → index-Dg2a9owQ.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-CUBkvFPH.js → index-DpqtbXdE.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-DhVHoqGL.js → index-DqwPFbOb.js} +3 -3
  125. package/src/assets/web-panel/assets/{index-BG-GaZri.js → index-DvV03Ayk.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CMCEXBRh.js → index-NJieh3T1.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-B273IY-E.js → index-Td8ZwyoC.js} +1 -1
  128. package/src/assets/web-panel/assets/index-c8jJEHVs.js +1 -0
  129. package/src/assets/web-panel/assets/{index-BzXjYUmd.js → index-e-e40id6.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-CCLwoATF.js → index-fccZmC_h.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-CN8HZlLH.js → index-fgYk0QXO.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-BB4KHHcv.js → index-yYEQXYaU.js} +1 -1
  133. package/src/assets/web-panel/assets/{initDefaultProps-CFNgY8lJ.js → initDefaultProps-CPrcB1TC.js} +1 -1
  134. package/src/assets/web-panel/assets/{motion-D-5RrDzn.js → motion-BQ7mWRh_.js} +1 -1
  135. package/src/assets/web-panel/assets/{move-DN-L0Bd-.js → move-CzOEq99p.js} +1 -1
  136. package/src/assets/web-panel/assets/{mtc-parser-6mgLSeCK.js → mtc-parser-BlQI5jrw.js} +1 -1
  137. package/src/assets/web-panel/assets/{omit-ClWW8eTP.js → omit-DlW4gxmv.js} +1 -1
  138. package/src/assets/web-panel/assets/{pickAttrs-Vystq3R8.js → pickAttrs-BBYms5nP.js} +1 -1
  139. package/src/assets/web-panel/assets/{placementArrow-D0H9hK4W.js → placementArrow-az2MPJ_7.js} +1 -1
  140. package/src/assets/web-panel/assets/{responsiveObserve-B3iNRU-a.js → responsiveObserve-D1-ibEol.js} +1 -1
  141. package/src/assets/web-panel/assets/{slide-CiMXe6am.js → slide-DHGqa4GA.js} +1 -1
  142. package/src/assets/web-panel/assets/{statusUtils-CGDZJ1uT.js → statusUtils-CYGDo6lD.js} +1 -1
  143. package/src/assets/web-panel/assets/{styleChecker-D2zA6NkY.js → styleChecker-Cl2EM9K6.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFlexGapSupport-C1sYU6QE.js → useFlexGapSupport-DdYhzuv1.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFs-BzUHSjg2.js → useFs-DWumPuBW.js} +1 -1
  146. package/src/assets/web-panel/assets/{usePersonalDataHub-CxB5yZCq.js → usePersonalDataHub-DxAO-Aqi.js} +1 -1
  147. package/src/assets/web-panel/assets/{vnode-BfUfMwtc.js → vnode-CplsQf_N.js} +1 -1
  148. package/src/assets/web-panel/assets/{zoom-CFYmj1TO.js → zoom-Cw5HXNSG.js} +1 -1
  149. package/src/assets/web-panel/index.html +1 -1
  150. package/src/command-help-index.json +2 -2
  151. package/src/commands/agent.js +19 -1
  152. package/src/commands/evolution-knowledge.js +54 -0
  153. package/src/commands/evolution-workbench.js +83 -0
  154. package/src/commands/evolution.js +6 -1
  155. package/src/commands/serve.js +16 -0
  156. package/src/commands/skill.js +158 -16
  157. package/src/data/changelog.json +26 -0
  158. package/src/gateways/ws/session-protocol.js +2 -0
  159. package/src/gateways/ws/ws-agent-handler.js +124 -69
  160. package/src/gateways/ws/ws-server.js +19 -0
  161. package/src/generated/cc-agent-protocol.schema.json +7 -1
  162. package/src/harness/jsonl-session-store.js +25 -1
  163. package/src/index.js +1 -1
  164. package/src/lib/app-server/cli-agent-kernel-adapter.js +8 -0
  165. package/src/lib/app-server/graph-runtime.js +40 -1
  166. package/src/lib/app-server/server.js +181 -3
  167. package/src/lib/app-server/websocket-transport.js +2 -0
  168. package/src/lib/evolution/agent-evolution-runtime-composition-brand.js +17 -0
  169. package/src/lib/evolution/agent-evolution-runtime-composition.js +165 -1
  170. package/src/lib/evolution/controlled-skill-production-pilot.js +912 -0
  171. package/src/lib/evolution/evolution-artifact-ports.js +21 -0
  172. package/src/lib/evolution/evolution-raw-crypto-shred.js +185 -0
  173. package/src/lib/evolution/evolution-workbench-batch-executor.js +195 -0
  174. package/src/lib/evolution/evolution-workbench-cli-host.js +169 -0
  175. package/src/lib/evolution/evolution-workbench-metrics-ledger-adapter.js +648 -0
  176. package/src/lib/evolution/evolution-workbench-metrics.js +943 -0
  177. package/src/lib/evolution/evolution-workbench-projection.js +734 -0
  178. package/src/lib/evolution/evolution-workbench-version-control.js +272 -0
  179. package/src/lib/evolution/governed-knowledge-conflict-merge.js +352 -0
  180. package/src/lib/evolution/governed-knowledge-dependency-authority.js +273 -0
  181. package/src/lib/evolution/governed-knowledge-dependency-ledger-executor.js +646 -0
  182. package/src/lib/evolution/governed-knowledge-merge-ledger-executor.js +644 -0
  183. package/src/lib/evolution/governed-knowledge-merge-publisher-authority.js +282 -0
  184. package/src/lib/evolution/governed-knowledge-node-crypto-authority.js +348 -0
  185. package/src/lib/evolution/governed-knowledge-rbac-approval-authority.js +621 -0
  186. package/src/lib/evolution/governed-knowledge-review-host.js +249 -0
  187. package/src/lib/evolution/governed-knowledge-sync-ledger-adapter.js +643 -0
  188. package/src/lib/evolution/governed-knowledge-sync-merge-publisher.js +259 -0
  189. package/src/lib/evolution/governed-knowledge-sync.js +485 -0
  190. package/src/lib/evolution/governed-knowledge-trust-ledger.js +707 -0
  191. package/src/lib/evolution/governed-skill-marketplace.js +430 -0
  192. package/src/lib/evolution/governed-wiki-pruning.js +435 -0
  193. package/src/lib/evolution/skill-outcome-index-authority.js +268 -0
  194. package/src/lib/evolution/skill-outcome-source-catalog-authority.js +237 -0
  195. package/src/lib/public-ide-capability-manifest.js +4 -0
  196. package/src/lib/skill-outcome-authority.js +43 -0
  197. package/src/lib/skill-outcome-transcript-authority.js +252 -0
  198. package/src/lib/skill-retrieval-router-benchmark.js +135 -0
  199. package/src/lib/skill-retrieval-router.js +235 -0
  200. package/src/lib/skill-vector-authority.js +325 -0
  201. package/src/lib/skill-vector-process-authority.js +386 -0
  202. package/src/repl/agent-repl.js +7 -1
  203. package/src/runtime/agent-core.js +72 -6
  204. package/src/runtime/agent-runtime.js +42 -0
  205. package/src/runtime/headless-runner.js +32 -0
  206. package/src/runtime/headless-stream.js +36 -1
  207. package/src/runtime/runtime-factory.js +62 -4
  208. package/src/assets/web-panel/assets/Notes-DZimkTrb.js +0 -7
  209. package/src/assets/web-panel/assets/OrderTableRenderer-Iy-pnX56.js +0 -1
  210. package/src/assets/web-panel/assets/ProjectSettings-CFMmhROS.js +0 -2
  211. package/src/assets/web-panel/assets/TimelineRenderer-CsLTB_QO.js +0 -1
  212. package/src/assets/web-panel/assets/devWarning-B2IW1J_J.js +0 -1
  213. package/src/assets/web-panel/assets/index-BCp2ir-1.js +0 -1
  214. package/src/assets/web-panel/assets/index-Bw4iuzRD.js +0 -1
@@ -0,0 +1,734 @@
1
+ import { createHash } from "node:crypto";
2
+ import { types as utilTypes } from "node:util";
3
+
4
+ import evolutionRun from "@chainlesschain/session-core/evolution-run";
5
+ import skillInvocationReceipt from "@chainlesschain/session-core/skill-invocation-receipt";
6
+
7
+ import {
8
+ verifySkillPromotionReviewDecision,
9
+ verifySkillPromotionReviewPacketArtifact,
10
+ } from "./skill-promotion-review.js";
11
+
12
+ const { projectEvolutionRun } = evolutionRun;
13
+ const { verifySkillInvocationReceipt } = skillInvocationReceipt;
14
+
15
+ export const EVOLUTION_WORKBENCH_PROJECTION_SCHEMA =
16
+ "chainlesschain.evolution-workbench-projection/v1";
17
+ export const EVOLUTION_WORKBENCH_BATCH_PLAN_SCHEMA =
18
+ "chainlesschain.evolution-workbench-batch-plan/v1";
19
+ export const EVOLUTION_WORKBENCH_MAX_ITEMS = 10_000;
20
+ export const EVOLUTION_WORKBENCH_MAX_BATCH = 50;
21
+
22
+ const DIGEST = /^sha256:[a-f0-9]{64}$/u;
23
+ const SAFE_ID = /^[A-Za-z0-9][A-Za-z0-9._:@/-]{0,255}$/u;
24
+ const DATA_SOURCES = new WeakSet();
25
+
26
+ function canonical(value) {
27
+ if (value === null || typeof value !== "object") return JSON.stringify(value);
28
+ if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
29
+ return `{${Object.keys(value)
30
+ .sort()
31
+ .map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`)
32
+ .join(",")}}`;
33
+ }
34
+
35
+ function hash(domain, value) {
36
+ return `sha256:${createHash("sha256")
37
+ .update(`${domain}\0${canonical(value)}`)
38
+ .digest("hex")}`;
39
+ }
40
+
41
+ function clone(value) {
42
+ return value == null ? value : JSON.parse(JSON.stringify(value));
43
+ }
44
+
45
+ function deepFreeze(value, seen = new WeakSet()) {
46
+ if (!value || typeof value !== "object" || seen.has(value)) return value;
47
+ seen.add(value);
48
+ Object.freeze(value);
49
+ for (const child of Object.values(value)) deepFreeze(child, seen);
50
+ return value;
51
+ }
52
+
53
+ function record(value, label) {
54
+ if (
55
+ !value ||
56
+ typeof value !== "object" ||
57
+ Array.isArray(value) ||
58
+ utilTypes.isProxy(value) ||
59
+ ![Object.prototype, null].includes(Object.getPrototypeOf(value))
60
+ ) {
61
+ throw new TypeError(`${label} must be a plain object`);
62
+ }
63
+ return value;
64
+ }
65
+
66
+ function identifier(value, label) {
67
+ if (typeof value !== "string" || !SAFE_ID.test(value)) {
68
+ throw new TypeError(`${label} is invalid`);
69
+ }
70
+ return value;
71
+ }
72
+
73
+ function digest(value, label) {
74
+ if (typeof value !== "string" || !DIGEST.test(value)) {
75
+ throw new TypeError(`${label} must be sha256-bound`);
76
+ }
77
+ return value;
78
+ }
79
+
80
+ function capture(owner, method, label) {
81
+ if (
82
+ !owner ||
83
+ typeof owner !== "object" ||
84
+ utilTypes.isProxy(owner) ||
85
+ typeof owner[method] !== "function"
86
+ ) {
87
+ throw new TypeError(`${label}.${method}() is required`);
88
+ }
89
+ return (...args) => Reflect.apply(owner[method], owner, args);
90
+ }
91
+
92
+ function boundedArray(value, label) {
93
+ if (!Array.isArray(value) || value.length > EVOLUTION_WORKBENCH_MAX_ITEMS) {
94
+ throw new TypeError(`${label} must be a bounded array`);
95
+ }
96
+ return value;
97
+ }
98
+
99
+ function same(left, right) {
100
+ return canonical(left) === canonical(right);
101
+ }
102
+
103
+ function normalizeTime(value, label) {
104
+ if (typeof value !== "string" || !Number.isFinite(Date.parse(value))) {
105
+ throw new TypeError(`${label} is invalid`);
106
+ }
107
+ return value;
108
+ }
109
+
110
+ function normalizeRun(value, descriptor) {
111
+ record(value, "EvolutionRun source result");
112
+ const events = boundedArray(value.events, "EvolutionRun events");
113
+ const projection = projectEvolutionRun(events, {
114
+ tenantId: descriptor.tenantId,
115
+ runId: descriptor.runId,
116
+ });
117
+ if (!same(projection, value.projection)) {
118
+ throw new Error("EvolutionRun source projection differs from its events");
119
+ }
120
+ return { events: clone(events), projection: clone(projection) };
121
+ }
122
+
123
+ function normalizeReviews(value, descriptor) {
124
+ return boundedArray(value, "review source result").map((entry, index) => {
125
+ record(entry, `reviews[${index}]`);
126
+ const packet = verifySkillPromotionReviewPacketArtifact(entry.packet);
127
+ if (
128
+ packet.tenantId !== descriptor.tenantId ||
129
+ packet.skillName !== descriptor.skillName
130
+ ) {
131
+ throw new Error("review source crossed its tenant or Skill boundary");
132
+ }
133
+ let decision = null;
134
+ if (entry.decision !== null) {
135
+ decision = verifySkillPromotionReviewDecision(
136
+ entry.decision,
137
+ packet,
138
+ Date.parse(entry.decision.decidedAt),
139
+ );
140
+ }
141
+ const expectedStatus = decision?.decision || "pending";
142
+ if (
143
+ !["pending", "approved", "rejected", "expired"].includes(entry.status) ||
144
+ (entry.status === "expired" && decision === null) ||
145
+ (entry.status !== "expired" && entry.status !== expectedStatus)
146
+ ) {
147
+ throw new Error("review source status differs from its decision");
148
+ }
149
+ return {
150
+ packet: clone(packet),
151
+ decision: clone(decision),
152
+ status: entry.status,
153
+ };
154
+ });
155
+ }
156
+
157
+ function normalizeTransitions(value, descriptor) {
158
+ return boundedArray(value, "transition source result").map((entry, index) => {
159
+ record(entry, `transitions[${index}]`);
160
+ record(entry.request, `transitions[${index}].request`);
161
+ digest(entry.request.requestDigest, "transition request digest");
162
+ if (
163
+ entry.request.tenantId !== descriptor.tenantId ||
164
+ entry.request.skillName !== descriptor.skillName ||
165
+ !["pending", "committed"].includes(entry.status) ||
166
+ !Array.isArray(entry.attempts) ||
167
+ entry.attempts.length > 64 ||
168
+ (entry.status === "committed") !== (entry.settlement !== null)
169
+ ) {
170
+ throw new Error("transition source crossed or contradicted its boundary");
171
+ }
172
+ for (const attempt of entry.attempts) {
173
+ digest(attempt.attemptDigest, "transition attempt digest");
174
+ if (
175
+ attempt.tenantId !== descriptor.tenantId ||
176
+ attempt.skillName !== descriptor.skillName ||
177
+ attempt.requestDigest !== entry.request.requestDigest
178
+ ) {
179
+ throw new Error("transition attempt is not bound to its request");
180
+ }
181
+ }
182
+ if (entry.settlement) {
183
+ digest(entry.settlement.settlementDigest, "transition settlement digest");
184
+ if (
185
+ entry.settlement.tenantId !== descriptor.tenantId ||
186
+ entry.settlement.skillName !== descriptor.skillName ||
187
+ entry.settlement.requestDigest !== entry.request.requestDigest
188
+ ) {
189
+ throw new Error("transition settlement is not bound to its request");
190
+ }
191
+ }
192
+ return clone(entry);
193
+ });
194
+ }
195
+
196
+ function normalizeInvocations(value, descriptor) {
197
+ return boundedArray(value, "invocation receipt source result")
198
+ .map((receipt) => verifySkillInvocationReceipt(receipt))
199
+ .filter((receipt) => receipt.evolutionRunId === descriptor.runId)
200
+ .map(clone);
201
+ }
202
+
203
+ function normalizePilot(value, descriptor) {
204
+ if (value === null) return null;
205
+ record(value, "pilot source result");
206
+ digest(value.descriptorDigest, "pilot descriptor digest");
207
+ digest(value.candidateDigest, "pilot candidate digest");
208
+ if (
209
+ !["candidate", "shadow", "canary", "active", "rolled-back"].includes(
210
+ value.stage,
211
+ ) ||
212
+ !Number.isSafeInteger(value.revision) ||
213
+ value.revision < 0 ||
214
+ typeof value.reconciliationRequired !== "boolean" ||
215
+ value.cohort?.id == null
216
+ ) {
217
+ throw new Error("pilot source result is invalid");
218
+ }
219
+ const review = descriptor.reviewPacketDigests;
220
+ if (review.size > 0 && !review.has(value.reviewPacketDigest)) {
221
+ throw new Error("pilot is not bound to a Workbench review packet");
222
+ }
223
+ return clone(value);
224
+ }
225
+
226
+ export function createEvolutionWorkbenchDataSource({
227
+ tenantId: tenantIdInput,
228
+ runId: runIdInput,
229
+ skillName: skillNameInput,
230
+ runAdapter,
231
+ reviewAdapter,
232
+ transitionAdapter,
233
+ invocationReceiptSource = null,
234
+ pilotSource = null,
235
+ } = {}) {
236
+ const tenantId = identifier(tenantIdInput, "tenantId");
237
+ const runId = identifier(runIdInput, "runId");
238
+ const skillName = identifier(skillNameInput, "skillName");
239
+ const loadRun = capture(runAdapter, "load", "runAdapter");
240
+ const listReviews = capture(reviewAdapter, "listReviews", "reviewAdapter");
241
+ const listTransitions = capture(
242
+ transitionAdapter,
243
+ "list",
244
+ "transitionAdapter",
245
+ );
246
+ const listInvocations =
247
+ invocationReceiptSource === null
248
+ ? () => []
249
+ : capture(invocationReceiptSource, "list", "invocationReceiptSource");
250
+ const readPilot =
251
+ pilotSource === null
252
+ ? () => null
253
+ : capture(pilotSource, "view", "pilotSource");
254
+ const source = Object.freeze({
255
+ tenantId,
256
+ runId,
257
+ skillName,
258
+ async load() {
259
+ const run = normalizeRun(await loadRun(), { tenantId, runId });
260
+ const reviews = normalizeReviews(await listReviews(), {
261
+ tenantId,
262
+ skillName,
263
+ });
264
+ for (const { packet } of reviews) {
265
+ const recorded = run.projection.registry.candidates[packet.candidateId];
266
+ if (
267
+ recorded?.digest !== packet.candidateContentDigest ||
268
+ typeof recorded.artifactRef !== "string"
269
+ ) {
270
+ throw new Error(
271
+ "review packet candidate is absent from the authenticated EvolutionRun",
272
+ );
273
+ }
274
+ }
275
+ const reviewPacketDigests = new Set(
276
+ reviews.map(({ packet }) => packet.packetDigest),
277
+ );
278
+ const transitions = normalizeTransitions(await listTransitions(), {
279
+ tenantId,
280
+ skillName,
281
+ });
282
+ for (const { request } of transitions) {
283
+ if (!run.projection.registry.candidates[request.candidateId]) {
284
+ throw new Error(
285
+ "registry transition candidate is absent from the authenticated EvolutionRun",
286
+ );
287
+ }
288
+ }
289
+ return deepFreeze({
290
+ run,
291
+ reviews,
292
+ transitions,
293
+ invocations: normalizeInvocations(await listInvocations(), { runId }),
294
+ pilot: normalizePilot(await readPilot(), { reviewPacketDigests }),
295
+ });
296
+ },
297
+ });
298
+ DATA_SOURCES.add(source);
299
+ return source;
300
+ }
301
+
302
+ export function isEvolutionWorkbenchDataSource(value) {
303
+ return DATA_SOURCES.has(value);
304
+ }
305
+
306
+ function runTimeline(events) {
307
+ return events.map((event) => ({
308
+ id: `run:${event.eventId}`,
309
+ sequence: event.sequence,
310
+ phase: event.type,
311
+ status: "committed",
312
+ subjectId: event.subjectId,
313
+ digest: event.payloadDigest,
314
+ artifactRef: event.artifactRef,
315
+ occurredAt: null,
316
+ source: "evolution-run",
317
+ detail: clone(event.data),
318
+ }));
319
+ }
320
+
321
+ function reviewTimeline(reviews) {
322
+ const rows = [];
323
+ for (const { packet, decision, status } of reviews) {
324
+ rows.push({
325
+ id: `review:${packet.packetDigest}`,
326
+ sequence: null,
327
+ phase: "approval-requested",
328
+ status,
329
+ subjectId: packet.candidateId,
330
+ digest: packet.packetDigest,
331
+ artifactRef: null,
332
+ occurredAt: null,
333
+ source: "promotion-review",
334
+ detail: {
335
+ requiredHumanQuorum: packet.requiredHumanQuorum,
336
+ contentRiskDigest: packet.contentRisk.contentRiskDigest,
337
+ },
338
+ });
339
+ if (decision) {
340
+ rows.push({
341
+ id: `decision:${decision.receiptDigest}`,
342
+ sequence: null,
343
+ phase: decision.decision,
344
+ status: decision.decision,
345
+ subjectId: packet.candidateId,
346
+ digest: decision.receiptDigest,
347
+ artifactRef: null,
348
+ occurredAt: decision.decidedAt,
349
+ source: "promotion-review",
350
+ detail: {
351
+ packetDigest: packet.packetDigest,
352
+ reason: decision.reason,
353
+ reviewerIds: [...decision.reviewerIds],
354
+ },
355
+ });
356
+ }
357
+ }
358
+ return rows;
359
+ }
360
+
361
+ function transitionTimeline(transitions) {
362
+ const rows = [];
363
+ for (const entry of transitions) {
364
+ rows.push({
365
+ id: `transition:${entry.request.requestDigest}`,
366
+ sequence: entry.requestEventSequence,
367
+ phase: "promotion-requested",
368
+ status: entry.status,
369
+ subjectId: entry.request.candidateId,
370
+ digest: entry.request.requestDigest,
371
+ artifactRef: null,
372
+ occurredAt: entry.request.effectiveAt,
373
+ source: "registry-transition",
374
+ detail: { requestId: entry.request.requestId },
375
+ });
376
+ for (const attempt of entry.attempts) {
377
+ rows.push({
378
+ id: `attempt:${attempt.attemptDigest}`,
379
+ sequence: entry.requestEventSequence,
380
+ phase: "promotion-attempted",
381
+ status: entry.status,
382
+ subjectId: attempt.candidateId,
383
+ digest: attempt.attemptDigest,
384
+ artifactRef: null,
385
+ occurredAt: attempt.createdAt,
386
+ source: "registry-transition",
387
+ detail: {
388
+ ordinal: attempt.ordinal,
389
+ requestDigest: attempt.requestDigest,
390
+ },
391
+ });
392
+ }
393
+ if (entry.settlement) {
394
+ rows.push({
395
+ id: `settlement:${entry.settlement.settlementDigest}`,
396
+ sequence: entry.requestEventSequence,
397
+ phase: entry.settlement.outcome || "promotion-settled",
398
+ status: "committed",
399
+ subjectId: entry.settlement.candidateId,
400
+ digest: entry.settlement.settlementDigest,
401
+ artifactRef: null,
402
+ occurredAt: entry.settlement.settledAt,
403
+ source: "registry-transition",
404
+ detail: {
405
+ requestDigest: entry.settlement.requestDigest,
406
+ activeReleaseDigest: entry.settlement.activeReleaseDigest,
407
+ },
408
+ });
409
+ }
410
+ }
411
+ return rows;
412
+ }
413
+
414
+ function timelineOrder(left, right) {
415
+ const leftTime = left.occurredAt ? Date.parse(left.occurredAt) : NaN;
416
+ const rightTime = right.occurredAt ? Date.parse(right.occurredAt) : NaN;
417
+ if (
418
+ Number.isFinite(leftTime) &&
419
+ Number.isFinite(rightTime) &&
420
+ leftTime !== rightTime
421
+ ) {
422
+ return leftTime - rightTime;
423
+ }
424
+ if (
425
+ left.sequence !== null &&
426
+ right.sequence !== null &&
427
+ left.sequence !== right.sequence
428
+ ) {
429
+ return left.sequence - right.sequence;
430
+ }
431
+ if (Number.isFinite(leftTime) !== Number.isFinite(rightTime)) {
432
+ return Number.isFinite(leftTime) ? 1 : -1;
433
+ }
434
+ return left.id.localeCompare(right.id);
435
+ }
436
+
437
+ function candidateView(review, invocations, activeCandidateIds) {
438
+ const { packet, decision, status } = review;
439
+ const receipts = invocations.filter((receipt) =>
440
+ receipt.selectedSkillDigests.includes(packet.candidateContentDigest),
441
+ );
442
+ const completed = receipts.filter(
443
+ ({ executionStatus }) => executionStatus === "completed",
444
+ ).length;
445
+ const totalCostUsd = receipts.reduce(
446
+ (sum, receipt) => sum + receipt.tokenCostLatency.costUsd,
447
+ 0,
448
+ );
449
+ return {
450
+ candidateId: packet.candidateId,
451
+ candidateContentDigest: packet.candidateContentDigest,
452
+ packetDigest: packet.packetDigest,
453
+ status,
454
+ decision: decision
455
+ ? {
456
+ receiptDigest: decision.receiptDigest,
457
+ decision: decision.decision,
458
+ reason: decision.reason,
459
+ reviewerIds: [...decision.reviewerIds],
460
+ decidedAt: decision.decidedAt,
461
+ }
462
+ : null,
463
+ why: {
464
+ evidence: clone(packet.evidenceSummary),
465
+ parentContentDigest: packet.parentContentDigest,
466
+ baselineReleaseDigest: packet.baselineReleaseDigest,
467
+ },
468
+ changes: {
469
+ unifiedDiff: packet.candidateDiff,
470
+ candidateDiffDigest: packet.candidateDiffDigest,
471
+ capabilities: clone(packet.capabilityDiff),
472
+ contentRisk: clone(packet.contentRisk),
473
+ },
474
+ validation: {
475
+ matrixEvalId: packet.evaluation.matrixEvalId,
476
+ matrixReceiptDigest: packet.evaluation.matrixReceiptDigest,
477
+ decisionCommitmentDigest: packet.evaluation.decisionCommitmentDigest,
478
+ targetRuntimes: [...packet.targetRuntimes],
479
+ },
480
+ actualUsage: {
481
+ active: activeCandidateIds.has(packet.candidateId),
482
+ receiptCount: receipts.length,
483
+ completed,
484
+ failedOrBlocked: receipts.length - completed,
485
+ totalCostUsd,
486
+ sessionPins: receipts.map((receipt) => ({
487
+ receiptId: receipt.receiptId,
488
+ receiptDigest: receipt.receiptDigest,
489
+ traceId: receipt.traceId,
490
+ trajectorySegmentId: receipt.trajectorySegmentId,
491
+ selectedSkillDigests: [...receipt.selectedSkillDigests],
492
+ providerModelVersion: receipt.providerModelVersion,
493
+ toolSetDigest: receipt.toolSetDigest,
494
+ osSandboxPermissionPolicyDigest:
495
+ receipt.osSandboxPermissionPolicyDigest,
496
+ executionStatus: receipt.executionStatus,
497
+ })),
498
+ },
499
+ };
500
+ }
501
+
502
+ function conflictsFor(candidates, transitions, pilot) {
503
+ const conflicts = [];
504
+ for (const candidate of candidates) {
505
+ for (const findingId of candidate.changes.contentRisk.findingIds) {
506
+ conflicts.push({
507
+ type: "content-risk",
508
+ candidateId: candidate.candidateId,
509
+ packetDigest: candidate.packetDigest,
510
+ reason: findingId,
511
+ });
512
+ }
513
+ for (const capability of candidate.changes.capabilities.highRiskAdded) {
514
+ conflicts.push({
515
+ type: "high-risk-capability",
516
+ candidateId: candidate.candidateId,
517
+ packetDigest: candidate.packetDigest,
518
+ reason: capability,
519
+ });
520
+ }
521
+ if (candidate.status === "expired") {
522
+ conflicts.push({
523
+ type: "expired-review",
524
+ candidateId: candidate.candidateId,
525
+ packetDigest: candidate.packetDigest,
526
+ reason: "human review expired before consumption",
527
+ });
528
+ }
529
+ }
530
+ for (const transition of transitions.filter(
531
+ ({ status }) => status === "pending",
532
+ )) {
533
+ conflicts.push({
534
+ type: "pending-transition",
535
+ candidateId: transition.request.candidateId,
536
+ packetDigest: transition.request.receipts?.reviewReceiptDigest || null,
537
+ reason: "registry transition has not reached a durable settlement",
538
+ });
539
+ }
540
+ if (pilot?.reconciliationRequired) {
541
+ conflicts.push({
542
+ type: "pilot-reconciliation",
543
+ candidateId: pilot.candidateDigest,
544
+ packetDigest: pilot.reviewPacketDigest,
545
+ reason: "pilot rollout authority reconciliation is required",
546
+ });
547
+ }
548
+ return conflicts;
549
+ }
550
+
551
+ export async function buildEvolutionWorkbenchProjection(
552
+ source,
553
+ { observedAt = new Date().toISOString() } = {},
554
+ ) {
555
+ if (!DATA_SOURCES.has(source)) {
556
+ throw new TypeError(
557
+ "a branded Evolution Workbench data source is required",
558
+ );
559
+ }
560
+ normalizeTime(observedAt, "observedAt");
561
+ const data = await source.load();
562
+ const activeReleaseId = data.run.projection.registry.activeReleaseId;
563
+ const activeCandidateIds = new Set(
564
+ data.transitions
565
+ .filter(
566
+ ({ status, settlement }) =>
567
+ status === "committed" &&
568
+ settlement?.activeReleaseDigest === activeReleaseId,
569
+ )
570
+ .map(({ settlement }) => settlement.candidateId),
571
+ );
572
+ const candidates = data.reviews.map((review) =>
573
+ candidateView(review, data.invocations, activeCandidateIds),
574
+ );
575
+ const timeline = [
576
+ ...runTimeline(data.run.events),
577
+ ...reviewTimeline(data.reviews),
578
+ ...transitionTimeline(data.transitions),
579
+ ].sort(timelineOrder);
580
+ const conflicts = conflictsFor(candidates, data.transitions, data.pilot);
581
+ const core = {
582
+ schema: EVOLUTION_WORKBENCH_PROJECTION_SCHEMA,
583
+ tenantId: source.tenantId,
584
+ runId: source.runId,
585
+ skillName: source.skillName,
586
+ observedAt,
587
+ run: {
588
+ status: data.run.projection.status,
589
+ projectionDigest: data.run.projection.projectionDigest,
590
+ eventRoot: data.run.projection.eventRoot,
591
+ eventCount: data.run.projection.eventCount,
592
+ wikiRevision: data.run.projection.wiki.revision,
593
+ wikiRevisionDigest: data.run.projection.wiki.revisionDigest,
594
+ activeReleaseId,
595
+ lastKnownGoodReleaseId:
596
+ data.run.projection.registry.lastKnownGoodReleaseId,
597
+ },
598
+ summary: {
599
+ candidateCount: candidates.length,
600
+ pendingReviewCount: candidates.filter(
601
+ ({ status }) => status === "pending",
602
+ ).length,
603
+ approvedCount: candidates.filter(({ status }) => status === "approved")
604
+ .length,
605
+ rejectedCount: candidates.filter(({ status }) => status === "rejected")
606
+ .length,
607
+ transitionCount: data.transitions.length,
608
+ invocationCount: data.invocations.length,
609
+ conflictCount: conflicts.length,
610
+ },
611
+ candidates,
612
+ timeline,
613
+ conflicts,
614
+ pilot: data.pilot,
615
+ };
616
+ return deepFreeze({
617
+ ...core,
618
+ projectionDigest: hash(EVOLUTION_WORKBENCH_PROJECTION_SCHEMA, core),
619
+ });
620
+ }
621
+
622
+ export function filterEvolutionWorkbenchProjection(
623
+ projection,
624
+ { query = "", status = null, offset = 0, limit = 100 } = {},
625
+ ) {
626
+ if (
627
+ projection?.schema !== EVOLUTION_WORKBENCH_PROJECTION_SCHEMA ||
628
+ projection.projectionDigest !==
629
+ hash(
630
+ EVOLUTION_WORKBENCH_PROJECTION_SCHEMA,
631
+ Object.fromEntries(
632
+ Object.entries(projection).filter(
633
+ ([key]) => key !== "projectionDigest",
634
+ ),
635
+ ),
636
+ )
637
+ ) {
638
+ throw new TypeError(
639
+ "a verified Evolution Workbench projection is required",
640
+ );
641
+ }
642
+ if (
643
+ !Number.isSafeInteger(offset) ||
644
+ offset < 0 ||
645
+ !Number.isSafeInteger(limit) ||
646
+ limit < 1 ||
647
+ limit > 500
648
+ ) {
649
+ throw new TypeError("Workbench pagination is out of range");
650
+ }
651
+ const needle = String(query).trim().toLowerCase();
652
+ const allowedStatus = new Set(["pending", "approved", "rejected", "expired"]);
653
+ if (status !== null && !allowedStatus.has(status)) {
654
+ throw new TypeError("Workbench status filter is invalid");
655
+ }
656
+ const matches = projection.candidates.filter((candidate) => {
657
+ if (status !== null && candidate.status !== status) return false;
658
+ if (!needle) return true;
659
+ const searchable = [
660
+ candidate.candidateId,
661
+ candidate.candidateContentDigest,
662
+ candidate.packetDigest,
663
+ candidate.decision?.reason,
664
+ ...candidate.validation.targetRuntimes,
665
+ ...candidate.changes.capabilities.added,
666
+ ...candidate.changes.capabilities.removed,
667
+ ...candidate.why.evidence.flatMap(({ ref, digest: value }) => [
668
+ ref,
669
+ value,
670
+ ]),
671
+ ]
672
+ .filter(Boolean)
673
+ .join("\n")
674
+ .toLowerCase();
675
+ return searchable.includes(needle);
676
+ });
677
+ return deepFreeze({
678
+ projectionDigest: projection.projectionDigest,
679
+ total: matches.length,
680
+ offset,
681
+ limit,
682
+ hasMore: offset + limit < matches.length,
683
+ candidates: clone(matches.slice(offset, offset + limit)),
684
+ });
685
+ }
686
+
687
+ export function buildEvolutionWorkbenchBatchPlan(
688
+ projection,
689
+ { packetDigests, decision, reason, requestedBy } = {},
690
+ ) {
691
+ filterEvolutionWorkbenchProjection(projection, { limit: 1 });
692
+ if (
693
+ !Array.isArray(packetDigests) ||
694
+ packetDigests.length < 1 ||
695
+ packetDigests.length > EVOLUTION_WORKBENCH_MAX_BATCH ||
696
+ new Set(packetDigests).size !== packetDigests.length ||
697
+ !["approve", "reject"].includes(decision) ||
698
+ typeof reason !== "string" ||
699
+ reason.trim() !== reason ||
700
+ reason.length < 1 ||
701
+ reason.length > 2048
702
+ ) {
703
+ throw new TypeError("Workbench batch governance request is invalid");
704
+ }
705
+ identifier(requestedBy, "requestedBy");
706
+ const pending = new Map(
707
+ projection.candidates
708
+ .filter(({ status }) => status === "pending")
709
+ .map((candidate) => [candidate.packetDigest, candidate]),
710
+ );
711
+ for (const value of packetDigests) {
712
+ digest(value, "packet digest");
713
+ if (!pending.has(value)) {
714
+ throw new Error(
715
+ "batch governance can target only pending review packets",
716
+ );
717
+ }
718
+ }
719
+ const core = {
720
+ schema: EVOLUTION_WORKBENCH_BATCH_PLAN_SCHEMA,
721
+ tenantId: projection.tenantId,
722
+ runId: projection.runId,
723
+ skillName: projection.skillName,
724
+ sourceProjectionDigest: projection.projectionDigest,
725
+ packetDigests: [...packetDigests].sort(),
726
+ decision,
727
+ reason,
728
+ requestedBy,
729
+ };
730
+ return deepFreeze({
731
+ ...core,
732
+ planDigest: hash(EVOLUTION_WORKBENCH_BATCH_PLAN_SCHEMA, core),
733
+ });
734
+ }