chainlesschain 0.166.16 → 0.166.18

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 (223) hide show
  1. package/README.md +17 -10
  2. package/completions/_cc +1 -1
  3. package/completions/cc.bash +1 -1
  4. package/completions/cc.fish +1 -1
  5. package/completions/cc.ps1 +1 -1
  6. package/package.json +2 -2
  7. package/src/assets/web-panel/assets/{AIOps-CTxa2Wbq.js → AIOps-CQSBl3hY.js} +1 -1
  8. package/src/assets/web-panel/assets/{ActionButton-DHrQyYhy.js → ActionButton-IQt-vRLt.js} +1 -1
  9. package/src/assets/web-panel/assets/{Analytics-DQiUqcNl.js → Analytics-DkHC8O7k.js} +3 -3
  10. package/src/assets/web-panel/assets/{AppLayout-_Iz4r6wt.js → AppLayout-CSti2P2T.js} +5 -5
  11. package/src/assets/web-panel/assets/{Artifacts-BNs63YHo.js → Artifacts-C57hxn3v.js} +1 -1
  12. package/src/assets/web-panel/assets/{Audit-BgHIqRLn.js → Audit-DByLntcf.js} +1 -1
  13. package/src/assets/web-panel/assets/{BackgroundAgents-DUQ5axBB.js → BackgroundAgents-D1Bd2EOa.js} +1 -1
  14. package/src/assets/web-panel/assets/{Backup-CJ51E9Vw.js → Backup-VstHzHng.js} +1 -1
  15. package/src/assets/web-panel/assets/{BaseInput-o-5toA_R.js → BaseInput-CLhdexIf.js} +1 -1
  16. package/src/assets/web-panel/assets/{Chat-Cu7a-x1L.js → Chat-BefC_JZS.js} +6 -6
  17. package/src/assets/web-panel/assets/{ChatBubbleRenderer-BUyYkAXr.js → ChatBubbleRenderer-DbXMvgmn.js} +1 -1
  18. package/src/assets/web-panel/assets/{Checkbox-DwdmZ71L.js → Checkbox-CEY982vx.js} +1 -1
  19. package/src/assets/web-panel/assets/{Codegen-BrH2eYiP.js → Codegen-Dcm_DTvJ.js} +1 -1
  20. package/src/assets/web-panel/assets/{Col-BVJQEP2j.js → Col-C8SSu4KA.js} +1 -1
  21. package/src/assets/web-panel/assets/{Community-FGO3vZPq.js → Community-BVV9vwRR.js} +1 -1
  22. package/src/assets/web-panel/assets/{Compact-DYGAFVnT.js → Compact-B7c5Vo18.js} +1 -1
  23. package/src/assets/web-panel/assets/{Compliance-CRvc8Bdt.js → Compliance-Tq9jSZ5a.js} +1 -1
  24. package/src/assets/web-panel/assets/{Cowork-D6Ah2m7A.js → Cowork-BJUjT09Q.js} +3 -3
  25. package/src/assets/web-panel/assets/{Cron-AXbU2ifR.js → Cron-CjV9PEaS.js} +2 -2
  26. package/src/assets/web-panel/assets/{Crosschain-C5DXgEFd.js → Crosschain-Dl7ReL8F.js} +1 -1
  27. package/src/assets/web-panel/assets/{DID-Bxh9QV9v.js → DID-CG8PjWmM.js} +2 -2
  28. package/src/assets/web-panel/assets/{Dashboard-B-ZHEta-.js → Dashboard-CDBM6wmF.js} +2 -2
  29. package/src/assets/web-panel/assets/{Dropdown-66Ik1jqa.js → Dropdown-8_55bXTD.js} +1 -1
  30. package/src/assets/web-panel/assets/{EmailListRenderer-CCWk1BIM.js → EmailListRenderer-D3qOU1Cm.js} +1 -1
  31. package/src/assets/web-panel/assets/{FamilyGuardDashboard--9faIULK.js → FamilyGuardDashboard-Bv5oWMZF.js} +1 -1
  32. package/src/assets/web-panel/assets/{Federation-CejW9CgX.js → Federation-hpZ1xkKd.js} +1 -1
  33. package/src/assets/web-panel/assets/{FormItemContext-acHgcXki.js → FormItemContext-BN7GT191.js} +1 -1
  34. package/src/assets/web-panel/assets/{GenericCardRenderer-D2ghd_K4.js → GenericCardRenderer-PCRhfA7M.js} +1 -1
  35. package/src/assets/web-panel/assets/{Git-BOe1YJrV.js → Git-CIlP2vy7.js} +2 -2
  36. package/src/assets/web-panel/assets/{Governance-BjgzJsof.js → Governance-81lgm7YL.js} +1 -1
  37. package/src/assets/web-panel/assets/{Inference-CXCD5rnP.js → Inference-Cs24xMOV.js} +1 -1
  38. package/src/assets/web-panel/assets/{KnowledgeGraph-CHA8QgJT.js → KnowledgeGraph-CrJLVCZo.js} +1 -1
  39. package/src/assets/web-panel/assets/{Logs-DORPMcL6.js → Logs-DLyO8RKT.js} +2 -2
  40. package/src/assets/web-panel/assets/{MarkdownRenderer-CPPHz01z.js → MarkdownRenderer-DBOqijrP.js} +1 -1
  41. package/src/assets/web-panel/assets/{Marketplace-BCFlo1Yx.js → Marketplace-Dz7AbQZc.js} +1 -1
  42. package/src/assets/web-panel/assets/{McpTools-Dl_uZAKh.js → McpTools-BM0aFiWv.js} +3 -3
  43. package/src/assets/web-panel/assets/{Memory-DupHamwz.js → Memory-C9SJzENX.js} +2 -2
  44. package/src/assets/web-panel/assets/{MobileBridge-BRSMPJxW.js → MobileBridge-BO2HnNRk.js} +1 -1
  45. package/src/assets/web-panel/assets/{MobileProjects-BHpuzsDl.js → MobileProjects-CK_jMz0l.js} +1 -1
  46. package/src/assets/web-panel/assets/{Mtc-Ch0jOQfZ.js → Mtc-CfhrJsdO.js} +2 -2
  47. package/src/assets/web-panel/assets/{MtcAudit-qzwQrDi7.js → MtcAudit-BE2ELxgI.js} +4 -4
  48. package/src/assets/web-panel/assets/{Multisig-B5wHzUcm.js → Multisig-CgR_E3Jd.js} +3 -3
  49. package/src/assets/web-panel/assets/{NLProgramming-Hy9uAiA0.js → NLProgramming-Cw9445_K.js} +1 -1
  50. package/src/assets/web-panel/assets/{Notes-DkuchMC7.js → Notes-DZimkTrb.js} +3 -3
  51. package/src/assets/web-panel/assets/{NotificationSettings-CYZhD7Pi.js → NotificationSettings-DxHVh4uT.js} +1 -1
  52. package/src/assets/web-panel/assets/{OrderTableRenderer-DKOoqajt.js → OrderTableRenderer-Iy-pnX56.js} +1 -1
  53. package/src/assets/web-panel/assets/{Organization-D9AXn6j8.js → Organization-pPXJtWo4.js} +4 -4
  54. package/src/assets/web-panel/assets/{Overflow-Bg15J6hX.js → Overflow-YamdTJwA.js} +1 -1
  55. package/src/assets/web-panel/assets/{P2P--B54HoQn.js → P2P-BvqP53x7.js} +2 -2
  56. package/src/assets/web-panel/assets/{PdhVaultBrowser-Cz9Kk2Nb.js → PdhVaultBrowser-Blz1Xn2n.js} +3 -3
  57. package/src/assets/web-panel/assets/{Permissions-DHx38eS1.js → Permissions-CgFRQqFJ.js} +4 -4
  58. package/src/assets/web-panel/assets/{PersonalDataHub-Dw8i2hAs.js → PersonalDataHub-CFeo3-6O.js} +4 -4
  59. package/src/assets/web-panel/assets/{Pipeline-B2o6Ur2G.js → Pipeline-BkaRojEK.js} +1 -1
  60. package/src/assets/web-panel/assets/{Privacy-8g-h2fnu.js → Privacy-BNZEx2Qp.js} +1 -1
  61. package/src/assets/web-panel/assets/{ProjectInit-DuVTcINx.js → ProjectInit-HUBOgEEK.js} +2 -2
  62. package/src/assets/web-panel/assets/{ProjectSettings-C8njvdZX.js → ProjectSettings-CFMmhROS.js} +2 -2
  63. package/src/assets/web-panel/assets/Projects-Dc517BXp.js +1 -0
  64. package/src/assets/web-panel/assets/{Providers-wFqgod_W.js → Providers-DTLf8bgj.js} +1 -1
  65. package/src/assets/web-panel/assets/{QrScannerModal-9NCXrpmA.js → QrScannerModal-BBNjPszk.js} +1 -1
  66. package/src/assets/web-panel/assets/{QuickAsk-WUTNvFkY.js → QuickAsk-DCsHvk3G.js} +1 -1
  67. package/src/assets/web-panel/assets/{Recommend-xT4nYmju.js → Recommend-Dpr5YSop.js} +1 -1
  68. package/src/assets/web-panel/assets/{RemoteSession-fak1PBGC.js → RemoteSession-DmKnvqGg.js} +2 -2
  69. package/src/assets/web-panel/assets/{Reputation-D1AkQvD-.js → Reputation-CSRfuurX.js} +1 -1
  70. package/src/assets/web-panel/assets/{Row-DVfm6xGt.js → Row-CDj3pQ_w.js} +1 -1
  71. package/src/assets/web-panel/assets/{RssFeed-BDunoLSE.js → RssFeed-DI0a_kNq.js} +2 -2
  72. package/src/assets/web-panel/assets/{Search-OPycRoU3.js → Search-jAy7B2nU.js} +1 -1
  73. package/src/assets/web-panel/assets/{Security-C8-Fm3Dt.js → Security-CkHTqYhc.js} +4 -4
  74. package/src/assets/web-panel/assets/{Services-qM_sMpMl.js → Services-CP-0Nzga.js} +2 -2
  75. package/src/assets/web-panel/assets/{Skeleton-D3HBJjVF.js → Skeleton-BkF5-p3n.js} +1 -1
  76. package/src/assets/web-panel/assets/{Skills-jr67X-tP.js → Skills-BDu-utDE.js} +1 -1
  77. package/src/assets/web-panel/assets/{Sla-CS3ggyCg.js → Sla-CQvq_2Qb.js} +1 -1
  78. package/src/assets/web-panel/assets/{SpeechSettings-CTOCYxOi.js → SpeechSettings-T7Ap512g.js} +1 -1
  79. package/src/assets/web-panel/assets/{SyncSettings-D3s3cLT5.js → SyncSettings-Bt-PLvot.js} +2 -2
  80. package/src/assets/web-panel/assets/{Tasks-CdfoJ25m.js → Tasks-yLEcCogg.js} +1 -1
  81. package/src/assets/web-panel/assets/{Templates-Drb4AI8X.js → Templates-ByN3fmbr.js} +1 -1
  82. package/src/assets/web-panel/assets/{Tenant-DzwR3Qkz.js → Tenant-DBI7hITH.js} +1 -1
  83. package/src/assets/web-panel/assets/{Terminal-D-ESq7xp.js → Terminal-B77_DlGX.js} +2 -2
  84. package/src/assets/web-panel/assets/{TimelineRenderer-BK-AUuws.js → TimelineRenderer-CsLTB_QO.js} +1 -1
  85. package/src/assets/web-panel/assets/{Tokens-xGTouuNp.js → Tokens-BV2N6cR8.js} +1 -1
  86. package/src/assets/web-panel/assets/{Trigger-BvZj-v2H.js → Trigger-CjXWGH3p.js} +1 -1
  87. package/src/assets/web-panel/assets/{Trust-BLC9CGmc.js → Trust-uqXIq3WC.js} +1 -1
  88. package/src/assets/web-panel/assets/{UkeySign-BSuCXpmE.js → UkeySign-D-6qu4vY.js} +1 -1
  89. package/src/assets/web-panel/assets/{VideoEditing-DT3A-_Ql.js → VideoEditing-CxGmx_2e.js} +1 -1
  90. package/src/assets/web-panel/assets/{Wallet-c1OXao85.js → Wallet-DSq7WlAg.js} +4 -4
  91. package/src/assets/web-panel/assets/{WebAuthn-CuA-F7KJ.js → WebAuthn-CDBiD57O.js} +2 -2
  92. package/src/assets/web-panel/assets/{WorkflowEditor-MANZrf82.js → WorkflowEditor-Z8f63TSb.js} +1 -1
  93. package/src/assets/web-panel/assets/{chat-D4Y4Ey0O.js → chat-B-UZFBjy.js} +1 -1
  94. package/src/assets/web-panel/assets/{colors-DDH06hKO.js → colors-CFk7K-7Q.js} +1 -1
  95. package/src/assets/web-panel/assets/{compact-item-Cym756Xj.js → compact-item-X0IVMvgi.js} +1 -1
  96. package/src/assets/web-panel/assets/{createContext-By4Nb1k-.js → createContext-DWg4j2n6.js} +1 -1
  97. package/src/assets/web-panel/assets/devWarning-B2IW1J_J.js +1 -0
  98. package/src/assets/web-panel/assets/{hasIn-Ch7OY258.js → hasIn-CkVCwNNF.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-D9le0-dc.js → index-5OcZHdzc.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CykROEJA.js → index-B273IY-E.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DjwgJ5Jd.js → index-B3-B3FWD.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CjNUTBwe.js → index-BB4KHHcv.js} +1 -1
  103. package/src/assets/web-panel/assets/index-BCp2ir-1.js +1 -0
  104. package/src/assets/web-panel/assets/{index-BFydNU6a.js → index-BG-GaZri.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-mL3nOcH6.js → index-BPBia4b-.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-XGeQMvWK.js → index-BipwEbTA.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-D5sADPGY.js → index-BoskgPt9.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-CV8qXTvb.js → index-Btqk6zWb.js} +1 -1
  109. package/src/assets/web-panel/assets/index-Bw4iuzRD.js +1 -0
  110. package/src/assets/web-panel/assets/{index-CJPks33Y.js → index-BzXjYUmd.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-BBBUn5v7.js → index-C1ZAOJRW.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-DiewptTL.js → index-CCLwoATF.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-OU8DZ9BL.js → index-CDfSD07S.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-DvnywwUj.js → index-CLlP1E4X.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-CT-3FYwd.js → index-CMCEXBRh.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-tZ5BUdad.js → index-CN8HZlLH.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-DNlxihs8.js → index-CNKFsBlz.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CF3Lhyns.js → index-CUBkvFPH.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-CV1UC4zo.js → index-Ca0mij1n.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-DAkk1M7x.js → index-CbIAWbma.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-DNEJzc0r.js → index-CbihMThv.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-q-s04OKn.js → index-CvOa-IFV.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-BZB9q-Lp.js → index-Cvwu_rA_.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-oBsfUbyH.js → index-D-EJNxgR.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-ZY2Qs_Sn.js → index-D8uEL8Uw.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-DtGValNi.js → index-D92g4l3n.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CpudmDhf.js → index-DCqpl_E_.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-Bo20BfdS.js → index-DLSBks8h.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-CUSUzaB8.js → index-Db_5xhrU.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-CZn6dmZe.js → index-DcDggpWR.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-CGsvEbbq.js → index-DeWKPQGs.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-jx7kr6mB.js → index-DhVHoqGL.js} +3 -3
  133. package/src/assets/web-panel/assets/{index-BIrRX-ra.js → index-DyWlOuak.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-6CpOV3Pn.js → index-LU54bChK.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-6-2eYBXr.js → index-OjnAwUJo.js} +1 -1
  136. package/src/assets/web-panel/assets/{index-B51otVoZ.js → index-P83LDnCz.js} +1 -1
  137. package/src/assets/web-panel/assets/{index-ArMrnx0v.js → index-_-9k3Tna.js} +1 -1
  138. package/src/assets/web-panel/assets/{initDefaultProps-DGcX9iPP.js → initDefaultProps-CFNgY8lJ.js} +1 -1
  139. package/src/assets/web-panel/assets/{motion-2SeL1D8A.js → motion-D-5RrDzn.js} +1 -1
  140. package/src/assets/web-panel/assets/{move-3cYbQCpS.js → move-DN-L0Bd-.js} +1 -1
  141. package/src/assets/web-panel/assets/{mtc-parser-IDdxfw0z.js → mtc-parser-6mgLSeCK.js} +1 -1
  142. package/src/assets/web-panel/assets/{omit-BNswdKO6.js → omit-ClWW8eTP.js} +1 -1
  143. package/src/assets/web-panel/assets/{pickAttrs-BwCnem2I.js → pickAttrs-Vystq3R8.js} +1 -1
  144. package/src/assets/web-panel/assets/{placementArrow-B9PtZ5rq.js → placementArrow-D0H9hK4W.js} +1 -1
  145. package/src/assets/web-panel/assets/{responsiveObserve-CPB6iSzV.js → responsiveObserve-B3iNRU-a.js} +1 -1
  146. package/src/assets/web-panel/assets/{slide-DZgyblZa.js → slide-CiMXe6am.js} +1 -1
  147. package/src/assets/web-panel/assets/{statusUtils-D82IBdsx.js → statusUtils-CGDZJ1uT.js} +1 -1
  148. package/src/assets/web-panel/assets/{styleChecker-qSHtosM-.js → styleChecker-D2zA6NkY.js} +1 -1
  149. package/src/assets/web-panel/assets/{useFlexGapSupport-CmWO7h0I.js → useFlexGapSupport-C1sYU6QE.js} +1 -1
  150. package/src/assets/web-panel/assets/{useFs-yLrs_ub4.js → useFs-BzUHSjg2.js} +1 -1
  151. package/src/assets/web-panel/assets/{usePersonalDataHub-CJ1VW6rh.js → usePersonalDataHub-CxB5yZCq.js} +1 -1
  152. package/src/assets/web-panel/assets/{vnode-CzY_moQ4.js → vnode-BfUfMwtc.js} +1 -1
  153. package/src/assets/web-panel/assets/{zoom-DAa7rEY5.js → zoom-CFYmj1TO.js} +1 -1
  154. package/src/assets/web-panel/index.html +1 -1
  155. package/src/command-help-index.json +2 -2
  156. package/src/command-manifest.json +2 -2
  157. package/src/commands/agent.js +80 -2
  158. package/src/commands/evolution.js +61 -42
  159. package/src/commands/learning.js +24 -8
  160. package/src/commands/serve.js +11 -2
  161. package/src/data/changelog.json +13 -0
  162. package/src/gateways/ws/session-protocol.js +1 -0
  163. package/src/gateways/ws/ws-agent-handler.js +70 -2
  164. package/src/gateways/ws/ws-server.js +8 -0
  165. package/src/lib/app-server/cli-agent-kernel-adapter.js +4 -0
  166. package/src/lib/app-server/graph-runtime.js +115 -8
  167. package/src/lib/app-server/server.js +21 -2
  168. package/src/lib/app-server/websocket-transport.js +2 -0
  169. package/src/lib/evolution/agent-evolution-ingress.js +300 -0
  170. package/src/lib/evolution/agent-evolution-runtime-composition-brand.js +22 -0
  171. package/src/lib/evolution/agent-evolution-runtime-composition.js +369 -0
  172. package/src/lib/evolution/bounded-skill-improvement-pilot.js +498 -0
  173. package/src/lib/evolution/evidence-backed-wiki-maintainer.js +752 -0
  174. package/src/lib/evolution/evolution-artifact-ports.js +48 -0
  175. package/src/lib/evolution/evolution-eval-gate.js +11 -4
  176. package/src/lib/evolution/evolution-evidence-artifact-adapter.js +499 -0
  177. package/src/lib/evolution/evolution-evidence-projector.js +61 -1
  178. package/src/lib/evolution/evolution-file-witness.js +601 -0
  179. package/src/lib/evolution/evolution-ledger-file-backend.js +176 -0
  180. package/src/lib/evolution/evolution-ledger-ports.js +353 -16
  181. package/src/lib/evolution/evolution-ledger.js +1355 -54
  182. package/src/lib/evolution/evolution-run-ledger-adapter.js +409 -0
  183. package/src/lib/evolution/evolution-run-runtime-adapter.js +5 -0
  184. package/src/lib/evolution/evolution-run-wiki-maintenance-source.js +300 -0
  185. package/src/lib/evolution/scheduled-batch-wiki-maintenance-source.js +368 -0
  186. package/src/lib/evolution/skill-candidate-registry.js +649 -0
  187. package/src/lib/evolution/skill-evaluated-promotion-durability.js +899 -0
  188. package/src/lib/evolution/skill-evaluated-promotion.js +481 -0
  189. package/src/lib/evolution/skill-promotion-controller.js +220 -37
  190. package/src/lib/evolution/skill-promotion-review-ledger-adapter.js +451 -0
  191. package/src/lib/evolution/skill-promotion-review.js +793 -0
  192. package/src/lib/evolution/skill-registry-transition-capability.js +55 -0
  193. package/src/lib/evolution/skill-registry-transition-ledger-adapter.js +1280 -0
  194. package/src/lib/evolution/skill-registry-transition-source.js +372 -0
  195. package/src/lib/evolution/skill-release-registry.js +2191 -11
  196. package/src/lib/evolution/skill-target-matrix-eval.js +133 -10
  197. package/src/lib/evolution/structured-memory-agent-control-plane.js +222 -0
  198. package/src/lib/evolution/structured-memory-authority-ledger-adapter.js +351 -0
  199. package/src/lib/evolution/structured-memory-ledger-adapter.js +220 -0
  200. package/src/lib/evolution/structured-memory-policy-receipt-writer.js +164 -0
  201. package/src/lib/evolution/structured-memory-post-compact-hook.js +87 -0
  202. package/src/lib/evolution/structured-memory-promotion-receipt-writer.js +221 -0
  203. package/src/lib/evolution/structured-memory-semantic-review-pipeline.js +313 -0
  204. package/src/lib/evolution/wiki-informed-skill-proposer.js +343 -0
  205. package/src/lib/evolution/wiki-maintainer-ledger-adapter.js +200 -0
  206. package/src/lib/evolution/wiki-maintenance-trigger-ledger-adapter.js +687 -0
  207. package/src/lib/evolution-system.js +65 -30
  208. package/src/lib/graph-kernel/evolution-run-runtime-adapter.js +5 -0
  209. package/src/lib/hooks-v2-runtime.js +20 -0
  210. package/src/lib/mcp-lifecycle-authority.js +21 -2
  211. package/src/lib/remote-approval-bridge.js +24 -0
  212. package/src/lib/scheduler-kernel/store.js +62 -14
  213. package/src/repl/agent-repl.js +45 -0
  214. package/src/runtime/agent-core.js +68 -0
  215. package/src/runtime/agent-runtime.js +114 -1
  216. package/src/runtime/headless-runner.js +19 -0
  217. package/src/runtime/headless-stream.js +43 -0
  218. package/src/runtime/runtime-factory.js +19 -1
  219. package/src/assets/web-panel/assets/Projects-Ca9BAfu7.js +0 -1
  220. package/src/assets/web-panel/assets/devWarning-KO3pAGeO.js +0 -1
  221. package/src/assets/web-panel/assets/index-Bh4Rgkg2.js +0 -1
  222. package/src/assets/web-panel/assets/index-Dox_coTY.js +0 -1
  223. package/src/lib/learning/learning-hooks.js +0 -123
@@ -9,12 +9,21 @@ import {
9
9
  verifySkillRuntimeManifest,
10
10
  verifySkillTargetMatrix,
11
11
  } from "./skill-execution-manifest.js";
12
+ import { assertEvolutionContentContainsNoKnownSecrets } from "./evolution-evidence-projector.js";
12
13
 
13
14
  export const SKILL_CANDIDATE_SCHEMA = "chainlesschain.skill-candidate/v2";
14
15
  export const SKILL_CANDIDATE_TENANT_MARKER_SCHEMA =
15
16
  "chainlesschain.skill-candidate-tenant-marker/v1";
16
17
  export const SKILL_CANDIDATE_MIGRATION_REQUIRED_CODE =
17
18
  "SKILL_CANDIDATE_MIGRATION_REQUIRED";
19
+ export const SKILL_CANDIDATE_MIGRATION_RECORD_SCHEMA =
20
+ "chainlesschain.skill-candidate-migration/v1";
21
+ export const SKILL_CANDIDATE_MIGRATION_AUTHORITY_SCHEMA =
22
+ "chainlesschain.skill-candidate-migration-authority/v1";
23
+ export const SKILL_CANDIDATE_MIGRATION_RECEIPT_SCHEMA =
24
+ "chainlesschain.skill-candidate-migration-receipt/v1";
25
+ export const SKILL_CANDIDATE_STORE_MIGRATION_SCHEMA =
26
+ "chainlesschain.skill-candidate-store-migration/v1";
18
27
  export const SKILL_CANDIDATE_STORE_LIMIT_CODE = "SKILL_CANDIDATE_STORE_LIMIT";
19
28
  export const SKILL_CANDIDATE_STATUS = "draft";
20
29
  export const SKILL_CANDIDATE_CONTENT_TYPE =
@@ -46,7 +55,9 @@ const NAMESPACED_ID_PATTERN = /^[a-z][a-z0-9]*(?:[._:-][a-z0-9]+)*$/u;
46
55
  const TENANT_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}$/u;
47
56
  const EVIDENCE_REF_PATTERN = /^[a-z][a-z0-9+.-]{1,31}:[^\s\\]+$/u;
48
57
  const LEGACY_SKILL_CANDIDATE_SCHEMA = "chainlesschain.skill-candidate/v1";
58
+ const LEGACY_CANDIDATE_DIGEST_DOMAIN = LEGACY_SKILL_CANDIDATE_SCHEMA;
49
59
  const CANDIDATE_DIGEST_DOMAIN = "chainlesschain.skill-candidate/v2";
60
+ const CANDIDATE_MIGRATION_DOMAIN = SKILL_CANDIDATE_MIGRATION_RECORD_SCHEMA;
50
61
  const TENANT_KEY_DOMAIN = "chainlesschain.skill-candidate-tenant-key/v1";
51
62
  const TENANT_MARKER_DIGEST_DOMAIN =
52
63
  "chainlesschain.skill-candidate-tenant-marker/v1";
@@ -77,6 +88,23 @@ const CANDIDATE_KEYS = new Set([
77
88
  "tenantId",
78
89
  "wikiRevision",
79
90
  ]);
91
+ const LEGACY_CANDIDATE_KEYS = new Set([
92
+ "candidateId",
93
+ "content",
94
+ "contentDigest",
95
+ "contentType",
96
+ "derivationMode",
97
+ "evalRunId",
98
+ "parentDigest",
99
+ "proposerModel",
100
+ "requestedCapabilities",
101
+ "schema",
102
+ "skillName",
103
+ "sourceEvidenceRefs",
104
+ "status",
105
+ "targetRuntimes",
106
+ "wikiRevision",
107
+ ]);
80
108
 
81
109
  const CREATE_INPUT_KEYS = new Set([
82
110
  "content",
@@ -146,6 +174,28 @@ const REGISTRY_OPTION_KEYS = new Set([
146
174
  "targetMatrixAdmissionAuthority",
147
175
  ]);
148
176
  const LIST_OPTION_KEYS = new Set(["limit"]);
177
+ const MIGRATION_EXECUTION_KEYS = new Set([
178
+ "dependencyLock",
179
+ "runtimeManifest",
180
+ "targetMatrix",
181
+ ]);
182
+ const MIGRATION_AUTHORITY_KEYS = new Set([
183
+ "audit",
184
+ "authorityId",
185
+ "handlerArtifactDigest",
186
+ "schema",
187
+ "trust",
188
+ ]);
189
+ const MIGRATION_RECEIPT_KEYS = new Set([
190
+ "authenticated",
191
+ "authorityId",
192
+ "durable",
193
+ "handlerArtifactDigest",
194
+ "migrationDigest",
195
+ "receiptDigest",
196
+ "schema",
197
+ "trust",
198
+ ]);
149
199
  const PROPOSER_MODEL_KEYS = new Set(["model", "provider", "version"]);
150
200
  const SOURCE_EVIDENCE_KEYS = new Set(["digest", "ref"]);
151
201
  const DERIVATION_MODES = new Set(["wiki", "record-replay", "manual-import"]);
@@ -405,9 +455,22 @@ function normalizeContent(value) {
405
455
  `content exceeds ${SKILL_CANDIDATE_MAX_CONTENT_BYTES} bytes`,
406
456
  );
407
457
  }
458
+ assertCandidatePlaintextSafe(value, "content");
408
459
  return value;
409
460
  }
410
461
 
462
+ function assertCandidatePlaintextSafe(value, label) {
463
+ try {
464
+ assertEvolutionContentContainsNoKnownSecrets(value);
465
+ } catch (cause) {
466
+ throw registryError(
467
+ "SKILL_CANDIDATE_SECRET_LEAK",
468
+ `candidate ${label} contains secret or PII plaintext`,
469
+ { cause },
470
+ );
471
+ }
472
+ }
473
+
411
474
  function normalizeNamespacedId(value, label) {
412
475
  const normalized = normalizeBoundedString(value, label, 128);
413
476
  if (!NAMESPACED_ID_PATTERN.test(normalized)) {
@@ -496,6 +559,7 @@ function normalizeSourceEvidenceRefs(value) {
496
559
  `sourceEvidenceRefs[${index}].ref must be an absolute opaque URI`,
497
560
  );
498
561
  }
562
+ assertCandidatePlaintextSafe(ref, `sourceEvidenceRefs[${index}].ref`);
499
563
  return {
500
564
  digest: normalizeDigest(
501
565
  ownData(entry, "digest", `sourceEvidenceRefs[${index}]`),
@@ -1002,6 +1066,112 @@ function candidateCore(input, verificationContext) {
1002
1066
  };
1003
1067
  }
1004
1068
 
1069
+ /** Verify the exact historical v1 draft before any tenant-scoped migration. */
1070
+ export function verifyLegacySkillCandidateDraft(candidate) {
1071
+ assertDataRecord(candidate, LEGACY_CANDIDATE_KEYS, "legacy candidate", {
1072
+ exact: true,
1073
+ });
1074
+ if (
1075
+ ownData(candidate, "schema", "legacy candidate") !==
1076
+ LEGACY_SKILL_CANDIDATE_SCHEMA ||
1077
+ ownData(candidate, "status", "legacy candidate") !==
1078
+ SKILL_CANDIDATE_STATUS ||
1079
+ ownData(candidate, "contentType", "legacy candidate") !==
1080
+ SKILL_CANDIDATE_CONTENT_TYPE
1081
+ ) {
1082
+ throw migrationRequired(
1083
+ "legacy candidate schema, status, or content type is invalid",
1084
+ );
1085
+ }
1086
+ const evalRunId = ownData(candidate, "evalRunId", "legacy candidate");
1087
+ if (evalRunId !== null) {
1088
+ throw migrationRequired("legacy draft candidate cannot carry evalRunId");
1089
+ }
1090
+ const content = normalizeContent(
1091
+ ownData(candidate, "content", "legacy candidate"),
1092
+ );
1093
+ const sourceEvidenceRefs = normalizeSourceEvidenceRefs(
1094
+ ownData(candidate, "sourceEvidenceRefs", "legacy candidate"),
1095
+ );
1096
+ const derivationMode = normalizeDerivationMode(
1097
+ ownData(candidate, "derivationMode", "legacy candidate"),
1098
+ );
1099
+ const wikiRevision = normalizeNullableReference(
1100
+ ownData(candidate, "wikiRevision", "legacy candidate"),
1101
+ "wikiRevision",
1102
+ );
1103
+ const proposerModel = normalizeProposerModel(
1104
+ ownData(candidate, "proposerModel", "legacy candidate"),
1105
+ );
1106
+ if (sourceEvidenceRefs.length === 0) {
1107
+ throw migrationRequired("legacy candidate has no source evidence");
1108
+ }
1109
+ if (
1110
+ derivationMode === "wiki" &&
1111
+ (wikiRevision === null || proposerModel === null)
1112
+ ) {
1113
+ throw migrationRequired(
1114
+ "legacy wiki candidate is missing its revision or proposer",
1115
+ );
1116
+ }
1117
+ if (derivationMode !== "wiki" && wikiRevision !== null) {
1118
+ throw migrationRequired("legacy non-wiki candidate claims a wiki revision");
1119
+ }
1120
+ const core = {
1121
+ schema: LEGACY_SKILL_CANDIDATE_SCHEMA,
1122
+ status: SKILL_CANDIDATE_STATUS,
1123
+ skillName: normalizeSkillName(
1124
+ ownData(candidate, "skillName", "legacy candidate"),
1125
+ ),
1126
+ parentDigest: normalizeDigest(
1127
+ ownData(candidate, "parentDigest", "legacy candidate"),
1128
+ "parentDigest",
1129
+ { nullable: true },
1130
+ ),
1131
+ contentDigest: contentDigest(content),
1132
+ sourceEvidenceRefs,
1133
+ derivationMode,
1134
+ wikiRevision,
1135
+ proposerModel,
1136
+ targetRuntimes: normalizeUniqueStringList(
1137
+ ownData(candidate, "targetRuntimes", "legacy candidate"),
1138
+ "targetRuntimes",
1139
+ MAX_TARGET_RUNTIMES,
1140
+ ),
1141
+ requestedCapabilities: normalizeUniqueStringList(
1142
+ ownData(candidate, "requestedCapabilities", "legacy candidate"),
1143
+ "requestedCapabilities",
1144
+ MAX_REQUESTED_CAPABILITIES,
1145
+ ),
1146
+ evalRunId: null,
1147
+ contentType: SKILL_CANDIDATE_CONTENT_TYPE,
1148
+ content,
1149
+ };
1150
+ const normalized = deepFreeze({
1151
+ candidateId: domainDigest(LEGACY_CANDIDATE_DIGEST_DOMAIN, core),
1152
+ ...core,
1153
+ });
1154
+ if (
1155
+ ownData(candidate, "candidateId", "legacy candidate") !==
1156
+ normalized.candidateId ||
1157
+ ownData(candidate, "contentDigest", "legacy candidate") !==
1158
+ normalized.contentDigest ||
1159
+ canonicalJson(candidate) !== canonicalJson(normalized)
1160
+ ) {
1161
+ throw migrationRequired(
1162
+ "legacy candidate bytes or digests are not canonical",
1163
+ {
1164
+ legacyCandidateId: ownData(
1165
+ candidate,
1166
+ "candidateId",
1167
+ "legacy candidate",
1168
+ ),
1169
+ },
1170
+ );
1171
+ }
1172
+ return normalized;
1173
+ }
1174
+
1005
1175
  /** Build the only artifact shape accepted by the candidate registry. */
1006
1176
  export function buildSkillCandidateDraft(input, verificationContext) {
1007
1177
  const core = candidateCore(input, verificationContext);
@@ -1958,6 +2128,485 @@ export class SkillCandidateRegistry {
1958
2128
  );
1959
2129
  }
1960
2130
 
2131
+ migrateLegacy(legacyCandidate, executionArtifacts, migrationAuthority) {
2132
+ if (arguments.length !== 3) {
2133
+ throw migrationRequired(
2134
+ "legacy migration requires candidate, execution artifacts, and a durable audit authority",
2135
+ );
2136
+ }
2137
+ const legacy = verifyLegacySkillCandidateDraft(legacyCandidate);
2138
+ assertDataRecord(
2139
+ executionArtifacts,
2140
+ MIGRATION_EXECUTION_KEYS,
2141
+ "candidate migration execution artifacts",
2142
+ { exact: true },
2143
+ );
2144
+ assertDataRecord(
2145
+ migrationAuthority,
2146
+ MIGRATION_AUTHORITY_KEYS,
2147
+ "candidate migration authority",
2148
+ { exact: true },
2149
+ );
2150
+ if (
2151
+ ownData(migrationAuthority, "schema", "candidate migration authority") !==
2152
+ SKILL_CANDIDATE_MIGRATION_AUTHORITY_SCHEMA ||
2153
+ ownData(migrationAuthority, "trust", "candidate migration authority") !==
2154
+ "trusted"
2155
+ ) {
2156
+ throw migrationRequired(
2157
+ "candidate migration authority is not trusted or has an unsupported schema",
2158
+ );
2159
+ }
2160
+ const authorityId = normalizeNamespacedId(
2161
+ ownData(
2162
+ migrationAuthority,
2163
+ "authorityId",
2164
+ "candidate migration authority",
2165
+ ),
2166
+ "migrationAuthority.authorityId",
2167
+ );
2168
+ const handlerArtifactDigest = normalizeDigest(
2169
+ ownData(
2170
+ migrationAuthority,
2171
+ "handlerArtifactDigest",
2172
+ "candidate migration authority",
2173
+ ),
2174
+ "migrationAuthority.handlerArtifactDigest",
2175
+ );
2176
+ const audit = ownData(
2177
+ migrationAuthority,
2178
+ "audit",
2179
+ "candidate migration authority",
2180
+ );
2181
+ if (typeof audit !== "function") {
2182
+ throw migrationRequired(
2183
+ "candidate migration audit port must be a function",
2184
+ );
2185
+ }
2186
+
2187
+ const dependencyLock = ownData(
2188
+ executionArtifacts,
2189
+ "dependencyLock",
2190
+ "candidate migration execution artifacts",
2191
+ );
2192
+ const runtimeManifest = ownData(
2193
+ executionArtifacts,
2194
+ "runtimeManifest",
2195
+ "candidate migration execution artifacts",
2196
+ );
2197
+ const targetMatrix = ownData(
2198
+ executionArtifacts,
2199
+ "targetMatrix",
2200
+ "candidate migration execution artifacts",
2201
+ );
2202
+ assertPlainObject(targetMatrix, "candidate migration targetMatrix");
2203
+ const targetRuntimes = normalizeUniqueStringList(
2204
+ ownData(
2205
+ targetMatrix,
2206
+ "targetRuntimes",
2207
+ "candidate migration targetMatrix",
2208
+ ),
2209
+ "targetMatrix.targetRuntimes",
2210
+ MAX_TARGET_RUNTIMES,
2211
+ );
2212
+ if (
2213
+ canonicalJson(targetRuntimes) !== canonicalJson(legacy.targetRuntimes)
2214
+ ) {
2215
+ throw migrationRequired(
2216
+ "candidate migration target matrix changes the legacy runtime scope",
2217
+ { legacyCandidateId: legacy.candidateId },
2218
+ );
2219
+ }
2220
+
2221
+ const publication = this.create({
2222
+ tenantId: this.tenantId,
2223
+ skillName: legacy.skillName,
2224
+ parentDigest: legacy.parentDigest,
2225
+ sourceEvidenceRefs: legacy.sourceEvidenceRefs,
2226
+ derivationMode: legacy.derivationMode,
2227
+ wikiRevision: legacy.wikiRevision,
2228
+ proposerModel: legacy.proposerModel,
2229
+ requestedCapabilities: legacy.requestedCapabilities,
2230
+ evalRunId: null,
2231
+ content: legacy.content,
2232
+ dependencyLock,
2233
+ runtimeManifest,
2234
+ targetMatrix,
2235
+ });
2236
+ const candidate = publication.candidate;
2237
+ const migrationCore = deepFreeze({
2238
+ authorityId,
2239
+ candidateId: candidate.candidateId,
2240
+ contentDigest: candidate.contentDigest,
2241
+ dependencyLockDigest: candidate.dependencyLockDigest,
2242
+ handlerArtifactDigest,
2243
+ legacyArtifactDigest: sha256(
2244
+ Buffer.from(`${canonicalJson(legacy)}\n`, "utf8"),
2245
+ ),
2246
+ legacyCandidateId: legacy.candidateId,
2247
+ runtimeManifestDigest: candidate.runtimeManifestDigest,
2248
+ schema: SKILL_CANDIDATE_MIGRATION_RECORD_SCHEMA,
2249
+ targetMatrixRoot: candidate.targetMatrixRoot,
2250
+ tenantId: this.tenantId,
2251
+ trust: "trusted",
2252
+ });
2253
+ const missingBindings = Object.entries(migrationCore)
2254
+ .filter(([, value]) => value === undefined)
2255
+ .map(([key]) => key);
2256
+ if (missingBindings.length > 0) {
2257
+ throw migrationRequired(
2258
+ "candidate migration could not derive a complete audit binding",
2259
+ { legacyCandidateId: legacy.candidateId, missingBindings },
2260
+ );
2261
+ }
2262
+ const migration = deepFreeze({
2263
+ ...migrationCore,
2264
+ migrationDigest: domainDigest(CANDIDATE_MIGRATION_DOMAIN, migrationCore),
2265
+ });
2266
+ let receipt;
2267
+ try {
2268
+ receipt = audit(migration);
2269
+ } catch (cause) {
2270
+ throw registryError(
2271
+ "SKILL_CANDIDATE_MIGRATION_AUDIT_FAILED",
2272
+ "candidate migration audit authority failed after draft publication",
2273
+ {
2274
+ candidateId: candidate.candidateId,
2275
+ cause,
2276
+ commitState: "candidate-only",
2277
+ migrationDigest: migration.migrationDigest,
2278
+ },
2279
+ );
2280
+ }
2281
+ if (utilTypes.isPromise(receipt)) {
2282
+ throw registryError(
2283
+ "SKILL_CANDIDATE_MIGRATION_AUDIT_FAILED",
2284
+ "candidate migration audit authority must be synchronous",
2285
+ {
2286
+ candidateId: candidate.candidateId,
2287
+ commitState: "candidate-only",
2288
+ migrationDigest: migration.migrationDigest,
2289
+ },
2290
+ );
2291
+ }
2292
+ assertDataRecord(
2293
+ receipt,
2294
+ MIGRATION_RECEIPT_KEYS,
2295
+ "candidate migration receipt",
2296
+ { exact: true },
2297
+ );
2298
+ const normalizedReceipt = deepFreeze({
2299
+ authenticated: ownData(
2300
+ receipt,
2301
+ "authenticated",
2302
+ "candidate migration receipt",
2303
+ ),
2304
+ authorityId: normalizeNamespacedId(
2305
+ ownData(receipt, "authorityId", "candidate migration receipt"),
2306
+ "migrationReceipt.authorityId",
2307
+ ),
2308
+ durable: ownData(receipt, "durable", "candidate migration receipt"),
2309
+ handlerArtifactDigest: normalizeDigest(
2310
+ ownData(
2311
+ receipt,
2312
+ "handlerArtifactDigest",
2313
+ "candidate migration receipt",
2314
+ ),
2315
+ "migrationReceipt.handlerArtifactDigest",
2316
+ ),
2317
+ migrationDigest: normalizeDigest(
2318
+ ownData(receipt, "migrationDigest", "candidate migration receipt"),
2319
+ "migrationReceipt.migrationDigest",
2320
+ ),
2321
+ receiptDigest: normalizeDigest(
2322
+ ownData(receipt, "receiptDigest", "candidate migration receipt"),
2323
+ "migrationReceipt.receiptDigest",
2324
+ ),
2325
+ schema: ownData(receipt, "schema", "candidate migration receipt"),
2326
+ trust: ownData(receipt, "trust", "candidate migration receipt"),
2327
+ });
2328
+ if (
2329
+ normalizedReceipt.schema !== SKILL_CANDIDATE_MIGRATION_RECEIPT_SCHEMA ||
2330
+ normalizedReceipt.authenticated !== true ||
2331
+ normalizedReceipt.durable !== true ||
2332
+ normalizedReceipt.trust !== "trusted" ||
2333
+ normalizedReceipt.authorityId !== authorityId ||
2334
+ normalizedReceipt.handlerArtifactDigest !== handlerArtifactDigest ||
2335
+ normalizedReceipt.migrationDigest !== migration.migrationDigest
2336
+ ) {
2337
+ throw registryError(
2338
+ "SKILL_CANDIDATE_MIGRATION_AUDIT_FAILED",
2339
+ "candidate migration receipt is not exactly bound and durable",
2340
+ {
2341
+ candidateId: candidate.candidateId,
2342
+ commitState: "candidate-only",
2343
+ migrationDigest: migration.migrationDigest,
2344
+ },
2345
+ );
2346
+ }
2347
+ return deepFreeze({
2348
+ candidate,
2349
+ created: publication.created,
2350
+ migration,
2351
+ receipt: normalizedReceipt,
2352
+ });
2353
+ }
2354
+
2355
+ migrateLegacyStore(
2356
+ sourceRootDir,
2357
+ resolveExecutionArtifacts,
2358
+ migrationAuthority,
2359
+ ) {
2360
+ if (
2361
+ arguments.length !== 3 ||
2362
+ typeof resolveExecutionArtifacts !== "function"
2363
+ ) {
2364
+ throw migrationRequired(
2365
+ "legacy store migration requires one source root, one execution resolver, and one audit authority",
2366
+ );
2367
+ }
2368
+ assertDataRecord(
2369
+ migrationAuthority,
2370
+ MIGRATION_AUTHORITY_KEYS,
2371
+ "candidate migration authority",
2372
+ { exact: true },
2373
+ );
2374
+ const capturedMigrationAuthority = Object.freeze(
2375
+ Object.fromEntries(
2376
+ [...MIGRATION_AUTHORITY_KEYS].map((key) => [
2377
+ key,
2378
+ ownData(migrationAuthority, key, "candidate migration authority"),
2379
+ ]),
2380
+ ),
2381
+ );
2382
+ const requestedSource = path.resolve(
2383
+ normalizeBoundedString(
2384
+ sourceRootDir,
2385
+ "legacy candidate source root",
2386
+ 32_768,
2387
+ ),
2388
+ );
2389
+ let sourceRoot;
2390
+ let sourceIdentity;
2391
+ try {
2392
+ const stat = this._fs.lstatSync(requestedSource);
2393
+ sourceRoot = realpath(this._fs, requestedSource);
2394
+ const canonicalStat = this._fs.lstatSync(sourceRoot);
2395
+ const canonicalParent = realpath(this._fs, path.dirname(requestedSource));
2396
+ const expectedCanonical = path.join(
2397
+ canonicalParent,
2398
+ path.basename(requestedSource),
2399
+ );
2400
+ if (
2401
+ !stat.isDirectory() ||
2402
+ stat.isSymbolicLink() ||
2403
+ !canonicalStat.isDirectory() ||
2404
+ canonicalStat.isSymbolicLink() ||
2405
+ entryIdentity(canonicalStat) !== entryIdentity(stat) ||
2406
+ !samePath(sourceRoot, expectedCanonical) ||
2407
+ !samePath(realpath(this._fs, sourceRoot), sourceRoot) ||
2408
+ isContained(sourceRoot, this.baseDir) ||
2409
+ isContained(this.baseDir, sourceRoot)
2410
+ ) {
2411
+ throw registryError(
2412
+ "SKILL_CANDIDATE_MIGRATION_SOURCE_UNSAFE",
2413
+ "legacy source must be a canonical directory independent from the tenant registry",
2414
+ );
2415
+ }
2416
+ sourceIdentity = entryIdentity(stat);
2417
+ } catch (cause) {
2418
+ if (cause instanceof SkillCandidateRegistryError) throw cause;
2419
+ throw registryError(
2420
+ "SKILL_CANDIDATE_MIGRATION_SOURCE_UNSAFE",
2421
+ "legacy candidate source root is unavailable or unsafe",
2422
+ { cause },
2423
+ );
2424
+ }
2425
+ const assertSourceBoundary = () => {
2426
+ const stat = this._fs.lstatSync(sourceRoot);
2427
+ if (
2428
+ !stat.isDirectory() ||
2429
+ stat.isSymbolicLink() ||
2430
+ entryIdentity(stat) !== sourceIdentity ||
2431
+ !samePath(realpath(this._fs, sourceRoot), sourceRoot)
2432
+ ) {
2433
+ throw registryError(
2434
+ "SKILL_CANDIDATE_MIGRATION_SOURCE_UNSAFE",
2435
+ "legacy candidate source root changed during migration",
2436
+ );
2437
+ }
2438
+ };
2439
+
2440
+ this._assertBoundary();
2441
+ assertSourceBoundary();
2442
+ const names = this._readDirectoryEntryNamesBounded(
2443
+ sourceRoot,
2444
+ "legacy candidate source",
2445
+ ).sort(compareStrings);
2446
+ const sources = [];
2447
+ let totalBytes = 0;
2448
+ for (const name of names) {
2449
+ assertSourceBoundary();
2450
+ const match = CANDIDATE_FILE_PATTERN.exec(name);
2451
+ if (!match) {
2452
+ throw migrationRequired(
2453
+ "legacy candidate source contains a non-candidate entry",
2454
+ { path: path.join(sourceRoot, name) },
2455
+ );
2456
+ }
2457
+ const sourcePath = path.resolve(sourceRoot, name);
2458
+ if (
2459
+ !isContained(sourceRoot, sourcePath) ||
2460
+ !samePath(path.dirname(sourcePath), sourceRoot)
2461
+ ) {
2462
+ throw registryError(
2463
+ "SKILL_CANDIDATE_MIGRATION_SOURCE_UNSAFE",
2464
+ "legacy candidate source path escaped its root",
2465
+ );
2466
+ }
2467
+ const stored = this._readBoundedRegularFile(
2468
+ sourcePath,
2469
+ SKILL_CANDIDATE_MAX_ARTIFACT_BYTES,
2470
+ "SKILL_CANDIDATE_MIGRATION_SOURCE_UNSAFE",
2471
+ "legacy candidate artifact",
2472
+ );
2473
+ totalBytes += stored.bytes.length;
2474
+ if (totalBytes > SKILL_CANDIDATE_TENANT_SCAN_MAX_BYTES) {
2475
+ throw tenantScanLimit(
2476
+ "legacy candidate migration exceeded its aggregate byte budget",
2477
+ { path: sourcePath },
2478
+ );
2479
+ }
2480
+ let parsed;
2481
+ try {
2482
+ parsed = JSON.parse(
2483
+ new TextDecoder("utf-8", { fatal: true }).decode(stored.bytes),
2484
+ );
2485
+ } catch (cause) {
2486
+ throw registryError(
2487
+ "SKILL_CANDIDATE_MIGRATION_SOURCE_UNSAFE",
2488
+ "legacy candidate is not bounded UTF-8 JSON",
2489
+ { cause, path: sourcePath },
2490
+ );
2491
+ }
2492
+ const legacy = verifyLegacySkillCandidateDraft(parsed);
2493
+ const canonicalBytes = Buffer.from(`${canonicalJson(legacy)}\n`, "utf8");
2494
+ if (
2495
+ legacy.candidateId.slice("sha256:".length) !== match[1] ||
2496
+ !stored.bytes.equals(canonicalBytes)
2497
+ ) {
2498
+ throw registryError(
2499
+ "SKILL_CANDIDATE_MIGRATION_SOURCE_UNSAFE",
2500
+ "legacy candidate filename or bytes are not content-addressed and canonical",
2501
+ { path: sourcePath },
2502
+ );
2503
+ }
2504
+ sources.push(
2505
+ Object.freeze({
2506
+ bytesDigest: sha256(stored.bytes),
2507
+ identity: stored.identity,
2508
+ legacy,
2509
+ name,
2510
+ sourcePath,
2511
+ }),
2512
+ );
2513
+ assertSourceBoundary();
2514
+ }
2515
+
2516
+ const entries = [];
2517
+ let createdCount = 0;
2518
+ for (const source of sources) {
2519
+ assertSourceBoundary();
2520
+ let executionArtifacts;
2521
+ try {
2522
+ executionArtifacts = resolveExecutionArtifacts(
2523
+ deepFreeze({
2524
+ legacyCandidateId: source.legacy.candidateId,
2525
+ schema: SKILL_CANDIDATE_STORE_MIGRATION_SCHEMA,
2526
+ skillName: source.legacy.skillName,
2527
+ targetRuntimes: source.legacy.targetRuntimes,
2528
+ tenantId: this.tenantId,
2529
+ }),
2530
+ );
2531
+ } catch (cause) {
2532
+ throw registryError(
2533
+ "SKILL_CANDIDATE_MIGRATION_EXECUTION_UNAVAILABLE",
2534
+ "legacy candidate execution artifacts could not be resolved",
2535
+ {
2536
+ cause,
2537
+ legacyCandidateId: source.legacy.candidateId,
2538
+ migratedCount: entries.length,
2539
+ },
2540
+ );
2541
+ }
2542
+ if (utilTypes.isPromise(executionArtifacts)) {
2543
+ throw registryError(
2544
+ "SKILL_CANDIDATE_MIGRATION_EXECUTION_UNAVAILABLE",
2545
+ "legacy candidate execution resolver must be synchronous",
2546
+ {
2547
+ legacyCandidateId: source.legacy.candidateId,
2548
+ migratedCount: entries.length,
2549
+ },
2550
+ );
2551
+ }
2552
+ const migrated = this.migrateLegacy(
2553
+ source.legacy,
2554
+ executionArtifacts,
2555
+ capturedMigrationAuthority,
2556
+ );
2557
+ if (migrated.created) createdCount += 1;
2558
+ entries.push(
2559
+ deepFreeze({
2560
+ candidateId: migrated.candidate.candidateId,
2561
+ legacyArtifactDigest: migrated.migration.legacyArtifactDigest,
2562
+ legacyCandidateId: source.legacy.candidateId,
2563
+ migrationDigest: migrated.migration.migrationDigest,
2564
+ receiptDigest: migrated.receipt.receiptDigest,
2565
+ }),
2566
+ );
2567
+ }
2568
+
2569
+ for (const source of sources) {
2570
+ assertSourceBoundary();
2571
+ const current = this._readBoundedRegularFile(
2572
+ source.sourcePath,
2573
+ SKILL_CANDIDATE_MAX_ARTIFACT_BYTES,
2574
+ "SKILL_CANDIDATE_MIGRATION_SOURCE_UNSAFE",
2575
+ "legacy candidate artifact",
2576
+ );
2577
+ if (
2578
+ current.identity !== source.identity ||
2579
+ sha256(current.bytes) !== source.bytesDigest
2580
+ ) {
2581
+ throw registryError(
2582
+ "SKILL_CANDIDATE_MIGRATION_SOURCE_UNSAFE",
2583
+ "legacy candidate source changed before migration completion",
2584
+ {
2585
+ legacyCandidateId: source.legacy.candidateId,
2586
+ migratedCount: entries.length,
2587
+ },
2588
+ );
2589
+ }
2590
+ }
2591
+ this._assertBoundary();
2592
+ assertSourceBoundary();
2593
+ const core = deepFreeze({
2594
+ entries,
2595
+ migratedCount: entries.length,
2596
+ schema: SKILL_CANDIDATE_STORE_MIGRATION_SCHEMA,
2597
+ sourceArtifactCount: sources.length,
2598
+ tenantId: this.tenantId,
2599
+ });
2600
+ return deepFreeze({
2601
+ ...core,
2602
+ createdCount,
2603
+ migrationDigest: domainDigest(
2604
+ SKILL_CANDIDATE_STORE_MIGRATION_SCHEMA,
2605
+ core,
2606
+ ),
2607
+ });
2608
+ }
2609
+
1961
2610
  create(input) {
1962
2611
  if (arguments.length !== 1) {
1963
2612
  throw registryError(