chainlesschain 0.162.148 → 0.162.150

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 (322) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/src/assets/web-panel/.build-hash +1 -1
  4. package/src/assets/web-panel/assets/{AIOps-DwpCCp64.js → AIOps-CBLvrjeG.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-C9pBYocA.js → ActionButton-DYv2GtE0.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-BWAkeXxK.js → Analytics-CL6PZ-Ww.js} +3 -3
  7. package/src/assets/web-panel/assets/{AppLayout-CivFGH6B.js → AppLayout-xuyHt4uA.js} +3 -3
  8. package/src/assets/web-panel/assets/{Audit-Cm8hRpZm.js → Audit-DOvSVycq.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-DXdFMsE8.js → Backup-DMhfTswr.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-uAwSTeql.js → BaseInput-CQxDdm63.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-KU8eeJJE.js → Chat-BEeNhK2a.js} +5 -5
  12. package/src/assets/web-panel/assets/ChatBubbleRenderer-8nul8eTq.js +1 -0
  13. package/src/assets/web-panel/assets/{Checkbox-C6AMDkjd.js → Checkbox-CL04O-ER.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-t2moDxcO.js → Codegen-C50o-n7x.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-DCcsRRhN.js → Col-CH-bDkzs.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-DtB-8SAC.js → Community-DqAIMvSe.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-CZm8THYA.js → Compact-C43fo_my.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-LiQgC7g1.js → Compliance-BERnMrdP.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-CA8SAxht.js → Cowork-Baw3w1gp.js} +4 -4
  20. package/src/assets/web-panel/assets/{Cron-CtRaF1wD.js → Cron-BEqAHF1-.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-6-br6Hub.js → Crosschain-CvnmKwK4.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-Do2EccrL.js → DID-iMPxgVdt.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-wrXcbzGe.js → Dashboard--4SJX3YR.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-p3FsT245.js → Dropdown-BgLV6xgz.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-D95A2L8q.js → EmailListRenderer-Bvb8oUD8.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-cLuJW2zo.js → FamilyGuardDashboard-DpXPjJB5.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-Brgq_cbN.js → Federation-BbFfJ1Xi.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-DWLCkNgh.js → FormItemContext-DeGq1B-q.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-BBqUfQd6.js → GenericCardRenderer-CNW7s9zM.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-8F090w4I.js → Git-L1PjW-lT.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-CCogEbxb.js → Governance-PK-X58to.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-CfLD7v7C.js → Inference-BePWEH-d.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-DDuHJewd.js → KnowledgeGraph-LF_sBvdL.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-CE8KSEVC.js → Logs-BKkfk9hy.js} +2 -2
  35. package/src/assets/web-panel/assets/{Marketplace-DmwpZmhT.js → Marketplace-BNMqUDla.js} +1 -1
  36. package/src/assets/web-panel/assets/{McpTools-Bf7AazU8.js → McpTools-w4WPiyz2.js} +5 -5
  37. package/src/assets/web-panel/assets/{Memory-D0QU_00S.js → Memory-DUKMVGNi.js} +2 -2
  38. package/src/assets/web-panel/assets/{MobileBridge-yXS9xdhx.js → MobileBridge-BWhiEyTJ.js} +1 -1
  39. package/src/assets/web-panel/assets/{MobileProjects-BuDUoGUP.js → MobileProjects-Ocf5JEkX.js} +1 -1
  40. package/src/assets/web-panel/assets/{Mtc-BYyHy28p.js → Mtc-D2B6MMhU.js} +4 -4
  41. package/src/assets/web-panel/assets/{MtcAudit-CK0aqpiZ.js → MtcAudit-DdYjCq1O.js} +4 -4
  42. package/src/assets/web-panel/assets/{Multisig-mNimKYeb.js → Multisig-Cb1hfuUZ.js} +3 -3
  43. package/src/assets/web-panel/assets/{NLProgramming-AioAJ0YA.js → NLProgramming-CTeImGp7.js} +1 -1
  44. package/src/assets/web-panel/assets/{Notes-CVVNCLHE.js → Notes-BjYNc7eQ.js} +4 -4
  45. package/src/assets/web-panel/assets/{NotificationSettings-C4ABj-TK.js → NotificationSettings-Dn_NtRXQ.js} +1 -1
  46. package/src/assets/web-panel/assets/{OrderTableRenderer-DIp8Xcbd.js → OrderTableRenderer-DVYYIizh.js} +1 -1
  47. package/src/assets/web-panel/assets/{Organization-uozl_gWK.js → Organization-Be2Kmr5j.js} +4 -4
  48. package/src/assets/web-panel/assets/{Overflow-BCZOM2hK.js → Overflow-Cu_-qRlR.js} +1 -1
  49. package/src/assets/web-panel/assets/{P2P-CArcaiaj.js → P2P-DD2HoGzE.js} +2 -2
  50. package/src/assets/web-panel/assets/{PdhVaultBrowser-Sgq2Srr8.js → PdhVaultBrowser-BRI7DVth.js} +3 -3
  51. package/src/assets/web-panel/assets/{Permissions-BYrQrXnH.js → Permissions-C9Srcs2M.js} +4 -4
  52. package/src/assets/web-panel/assets/{PersonalDataHub-BzHStAbz.js → PersonalDataHub-CUqcMgo1.js} +3 -3
  53. package/src/assets/web-panel/assets/{Pipeline-k7KqxX1M.js → Pipeline-HBrQGLXt.js} +1 -1
  54. package/src/assets/web-panel/assets/{Privacy-IumTUWqx.js → Privacy-D-B0vjwh.js} +1 -1
  55. package/src/assets/web-panel/assets/{ProjectInit-BRyImYTf.js → ProjectInit-eTeLIu9e.js} +2 -2
  56. package/src/assets/web-panel/assets/{ProjectSettings-BFIqTBFk.js → ProjectSettings-DrRqCsC6.js} +2 -2
  57. package/src/assets/web-panel/assets/{Projects-Dpid9CDg.js → Projects-1G9DNOhI.js} +1 -1
  58. package/src/assets/web-panel/assets/{Providers-CyyFnUPs.js → Providers-RkTZzpxP.js} +1 -1
  59. package/src/assets/web-panel/assets/{QrScannerModal-C82cRx-X.js → QrScannerModal-BSCUgsgC.js} +1 -1
  60. package/src/assets/web-panel/assets/{QuickAsk-DGxDF521.js → QuickAsk-CHgyM3Bz.js} +1 -1
  61. package/src/assets/web-panel/assets/{Recommend-Cns-Am1y.js → Recommend-0lry4OZq.js} +1 -1
  62. package/src/assets/web-panel/assets/{RemoteSession-R7OqAIlg.js → RemoteSession-Cn45UroZ.js} +2 -2
  63. package/src/assets/web-panel/assets/{Reputation-D7mgPIYV.js → Reputation-Q-Zjb707.js} +1 -1
  64. package/src/assets/web-panel/assets/{Row-B3lEURyd.js → Row-BdM70oda.js} +1 -1
  65. package/src/assets/web-panel/assets/{RssFeed-9_UVrpBt.js → RssFeed-DmOAKKap.js} +2 -2
  66. package/src/assets/web-panel/assets/{Search-ClZeO80q.js → Search-Dwavbm07.js} +1 -1
  67. package/src/assets/web-panel/assets/{Security-BNNJczEp.js → Security-DukXFCnk.js} +3 -3
  68. package/src/assets/web-panel/assets/{Services-C5SjrWUj.js → Services-BIlRnITu.js} +2 -2
  69. package/src/assets/web-panel/assets/{Skeleton-Ci_obQ-g.js → Skeleton-YYVQdhhQ.js} +1 -1
  70. package/src/assets/web-panel/assets/{Skills-DdebN15P.js → Skills-B8_iYHz2.js} +1 -1
  71. package/src/assets/web-panel/assets/{Sla-OinZP2vi.js → Sla-BdVrhT31.js} +1 -1
  72. package/src/assets/web-panel/assets/{SpeechSettings-CxzbNF51.js → SpeechSettings-CD3ggRx7.js} +1 -1
  73. package/src/assets/web-panel/assets/{SyncSettings-D06N_66b.js → SyncSettings-Bp02VZFH.js} +2 -2
  74. package/src/assets/web-panel/assets/{Tasks-BdEdW0AZ.js → Tasks-DEVmCEsr.js} +1 -1
  75. package/src/assets/web-panel/assets/{Templates-F1ctKmPa.js → Templates-B6czWc4N.js} +1 -1
  76. package/src/assets/web-panel/assets/{Tenant-CVz1Urot.js → Tenant-BCJLv17r.js} +1 -1
  77. package/src/assets/web-panel/assets/Terminal-CD132d2Y.js +3 -0
  78. package/src/assets/web-panel/assets/{TimelineRenderer-Doitzjmf.js → TimelineRenderer-ZB-CvkZl.js} +1 -1
  79. package/src/assets/web-panel/assets/{Tokens-BpyVRpVA.js → Tokens-BnSY0S-s.js} +1 -1
  80. package/src/assets/web-panel/assets/{Trigger-nWhWYTbU.js → Trigger-VZw9Oy2w.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trust-DK_G-wLx.js → Trust-pZq7Hjd2.js} +1 -1
  82. package/src/assets/web-panel/assets/{UkeySign-B5yBUojO.js → UkeySign-DnQaqk4q.js} +1 -1
  83. package/src/assets/web-panel/assets/{VideoEditing-C5D51qAe.js → VideoEditing-BEUfmvJV.js} +1 -1
  84. package/src/assets/web-panel/assets/{Wallet-CLbL9K7v.js → Wallet-CoZKMXJ2.js} +4 -4
  85. package/src/assets/web-panel/assets/{WebAuthn-DZUelI3V.js → WebAuthn-CBOGVx1I.js} +5 -5
  86. package/src/assets/web-panel/assets/{WorkflowEditor-8RPxt4KW.js → WorkflowEditor-huSKn7TT.js} +1 -1
  87. package/src/assets/web-panel/assets/{chat-4N4tOA3d.js → chat-A_3w6FBO.js} +1 -1
  88. package/src/assets/web-panel/assets/{colors-zbbGVrua.js → colors-D1Bem9Oy.js} +1 -1
  89. package/src/assets/web-panel/assets/{compact-item-D7iMkbnE.js → compact-item-CJYJj0oO.js} +1 -1
  90. package/src/assets/web-panel/assets/{createContext-CBzPJv-w.js → createContext-BkbFiKT4.js} +1 -1
  91. package/src/assets/web-panel/assets/devWarning-WDr3_M_N.js +1 -0
  92. package/src/assets/web-panel/assets/{hasIn-bHdrQSqZ.js → hasIn-CKvUafVY.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-DbE5D0WL.js → index-AjrSPnvv.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-BCr0geV9.js → index-B8i0lViZ.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-CiG1IZao.js → index-B9Svn0zc.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-B1s0Bz9O.js → index-BHdHSX06.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-QFObYeo1.js → index-BHdailyo.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-BnBOpqv3.js → index-BJwlEnYo.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-CdmMoYN1.js → index-BOoAQjJz.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DUyjUkY7.js → index-BSgWxAOG.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CqdPyWm5.js → index-BdutMsne.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-DmqlJed-.js → index-BiDWxzbn.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-S74FpAIn.js → index-By5a0T_W.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-kmh1TxRa.js → index-C-WIY-FQ.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-BTIjjXry.js → index-C37f6iey.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-BS4_Mwk6.js → index-C9bWmTcO.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-BBNr77E1.js → index-CBaosWRO.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-QNAG4JtR.js → index-CBlBVJ_m.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Bqmx24kh.js → index-CD62EEGo.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-CQfu1U78.js → index-CUj-l7GM.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-BJ4ZGyW0.js → index-CVS8Ymuq.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-Ci009ijp.js → index-ChkXUj3f.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-oDKNgCsP.js → index-Cj0OZ-37.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BZb8F8YG.js → index-Co3OFL0t.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-308gCGh7.js → index-Crp8CbRg.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-CPxkoKgA.js → index-D22zNXiS.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-xYCm6W2h.js → index-DTs_D1OL.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-BtbbdLnf.js → index-DfgCdFrN.js} +3 -3
  119. package/src/assets/web-panel/assets/{index-BsKehmmS.js → index-DjYrecNb.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CkxK86vf.js → index-DpW9cf3e.js} +1 -1
  121. package/src/assets/web-panel/assets/index-Dwix3p4g.js +1 -0
  122. package/src/assets/web-panel/assets/{index-CvRMA9uT.js → index-F--HuPG1.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-DE9j5YgT.js → index-Fuk6t_3K.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-B7b1hGry.js → index-JEAGMii9.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-D1YDh7Wr.js → index-PF-mpv8K.js} +1 -1
  126. package/src/assets/web-panel/assets/index-SHaoZ0CA.js +1 -0
  127. package/src/assets/web-panel/assets/{index-CQ6NcfWz.js → index-b-sbVdjQ.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-DyoNgbXl.js → index-pyvMVX8r.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-DISWAYce.js → index-qNTtOVi_.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-D4XKpj6c.js → index-tgO8iza6.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-CahryTX0.js → index-ttDQVhZy.js} +1 -1
  132. package/src/assets/web-panel/assets/{initDefaultProps-BD55yNBt.js → initDefaultProps-DtrnfsZH.js} +1 -1
  133. package/src/assets/web-panel/assets/{motion-B5Bbe77U.js → motion-D4zqSaX3.js} +1 -1
  134. package/src/assets/web-panel/assets/{move-CTvIqHEH.js → move-CGFGOUQj.js} +1 -1
  135. package/src/assets/web-panel/assets/{mtc-parser-BkNyPQKB.js → mtc-parser-DH2HvkJl.js} +1 -1
  136. package/src/assets/web-panel/assets/{omit-BaXJXgHA.js → omit-jJ2at5HX.js} +1 -1
  137. package/src/assets/web-panel/assets/{pickAttrs-Bw6-YTxH.js → pickAttrs-CRyMT1Fv.js} +1 -1
  138. package/src/assets/web-panel/assets/{placementArrow-BLdbkLqJ.js → placementArrow-DZ_CX0Pt.js} +1 -1
  139. package/src/assets/web-panel/assets/{responsiveObserve-IVYkzntU.js → responsiveObserve-wruHk-h5.js} +1 -1
  140. package/src/assets/web-panel/assets/{slide-DFMFwwtY.js → slide-BGgx8q67.js} +1 -1
  141. package/src/assets/web-panel/assets/{statusUtils-CURYRtZ1.js → statusUtils-Do5M7gKm.js} +1 -1
  142. package/src/assets/web-panel/assets/{styleChecker-Cfz63s1r.js → styleChecker-CRa-GZpX.js} +1 -1
  143. package/src/assets/web-panel/assets/{useFlexGapSupport-COJL0KE3.js → useFlexGapSupport-BxPcq6pj.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFs-YLLojQQf.js → useFs-v5O2ZcJm.js} +1 -1
  145. package/src/assets/web-panel/assets/{usePersonalDataHub-BF_21qUC.js → usePersonalDataHub--z2FU0Px.js} +1 -1
  146. package/src/assets/web-panel/assets/{vnode-9ZpkA7bb.js → vnode-1emidVKd.js} +1 -1
  147. package/src/assets/web-panel/assets/{zoom-DhtAfhl8.js → zoom-CcJaRyHs.js} +1 -1
  148. package/src/assets/web-panel/index.html +1 -1
  149. package/src/assets/web-panel/remote-session-sw.js +43 -0
  150. package/src/command-manifest.json +22 -1
  151. package/src/commands/a2a.js +19 -4
  152. package/src/commands/activitypub.js +20 -3
  153. package/src/commands/agent.js +71 -10
  154. package/src/commands/audit.js +40 -24
  155. package/src/commands/codeintel.js +320 -0
  156. package/src/commands/collab.js +15 -2
  157. package/src/commands/compliance.js +5 -0
  158. package/src/commands/config.js +4 -1
  159. package/src/commands/dao.js +86 -14
  160. package/src/commands/dev.js +2 -0
  161. package/src/commands/did.js +7 -1
  162. package/src/commands/dlp.js +23 -1
  163. package/src/commands/economy.js +29 -3
  164. package/src/commands/eval.js +255 -0
  165. package/src/commands/evomap.js +26 -0
  166. package/src/commands/governance.js +17 -3
  167. package/src/commands/hardening.js +18 -0
  168. package/src/commands/incentive.js +5 -0
  169. package/src/commands/init.js +46 -2
  170. package/src/commands/kg.js +4 -0
  171. package/src/commands/loop.js +6 -1
  172. package/src/commands/lowcode.js +15 -2
  173. package/src/commands/marketplace.js +40 -6
  174. package/src/commands/matrix.js +20 -1
  175. package/src/commands/memory.js +4 -1
  176. package/src/commands/mtc.js +7 -1
  177. package/src/commands/nostr.js +31 -4
  178. package/src/commands/note.js +7 -4
  179. package/src/commands/plugin.js +474 -0
  180. package/src/commands/pqc.js +5 -0
  181. package/src/commands/reputation.js +10 -1
  182. package/src/commands/scim.js +6 -0
  183. package/src/commands/session.js +32 -10
  184. package/src/commands/siem.js +11 -0
  185. package/src/commands/sla.js +18 -3
  186. package/src/commands/social.js +38 -5
  187. package/src/commands/sso.js +10 -2
  188. package/src/commands/stress.js +23 -4
  189. package/src/commands/team.js +463 -0
  190. package/src/commands/tech.js +2 -0
  191. package/src/commands/tenant.js +10 -1
  192. package/src/commands/terraform.js +6 -0
  193. package/src/commands/update.js +1 -1
  194. package/src/commands/zkp.js +20 -0
  195. package/src/gateways/ws/message-dispatcher.js +48 -2
  196. package/src/gateways/ws/remote-session-protocol.js +140 -42
  197. package/src/gateways/ws/ws-server.js +1 -1
  198. package/src/harness/jsonl-session-store.js +12 -5
  199. package/src/harness/plugin-manager.js +16 -4
  200. package/src/harness/prompt-compressor.js +27 -1
  201. package/src/harness/remote-command-ledger.js +189 -0
  202. package/src/harness/remote-session-push-apns.js +246 -0
  203. package/src/harness/remote-session-push-errors.js +15 -0
  204. package/src/harness/remote-session-push-fcm.js +9 -25
  205. package/src/harness/remote-session-push-huawei.js +174 -0
  206. package/src/harness/remote-session-push-oppo.js +171 -0
  207. package/src/harness/remote-session-push-senders.js +42 -0
  208. package/src/harness/remote-session-push-vivo.js +179 -0
  209. package/src/harness/remote-session-push-web.js +299 -0
  210. package/src/harness/remote-session-push-xiaomi.js +99 -0
  211. package/src/harness/worktree-isolator.js +16 -6
  212. package/src/index.js +6 -0
  213. package/src/lib/__tests__/logger.test.js +5 -2
  214. package/src/lib/a2a-protocol.js +25 -1
  215. package/src/lib/activitypub-bridge.js +61 -0
  216. package/src/lib/agent-core.js +4 -0
  217. package/src/lib/agent-economy.js +262 -29
  218. package/src/lib/agent-network.js +7 -1
  219. package/src/lib/agent-sandbox.js +161 -5
  220. package/src/lib/agent-team/task-lease.js +434 -0
  221. package/src/lib/agent-team/team-budget.js +165 -0
  222. package/src/lib/agent-team/team-mailbox.js +106 -0
  223. package/src/lib/agent-team/team-runner.js +282 -0
  224. package/src/lib/agent-team/team-worktree.js +236 -0
  225. package/src/lib/agents.js +18 -0
  226. package/src/lib/async-hook-supervisor.cjs +391 -0
  227. package/src/lib/audit-logger.js +7 -6
  228. package/src/lib/autonomous-developer.js +60 -0
  229. package/src/lib/chat-core.js +17 -4
  230. package/src/lib/collaboration-governance.js +56 -0
  231. package/src/lib/community-governance.js +68 -0
  232. package/src/lib/compliance-manager.js +63 -0
  233. package/src/lib/cross-chain.js +5 -0
  234. package/src/lib/dao-governance.js +151 -2
  235. package/src/lib/did-manager.js +23 -10
  236. package/src/lib/dlp-engine.js +70 -0
  237. package/src/lib/eval/runner.js +251 -0
  238. package/src/lib/eval/tasks.js +626 -0
  239. package/src/lib/eval/trend.js +200 -0
  240. package/src/lib/evolution-system.js +92 -0
  241. package/src/lib/evomap-federation.js +55 -0
  242. package/src/lib/evomap-governance.js +94 -0
  243. package/src/lib/fatal-handler.js +17 -1
  244. package/src/lib/hardening-manager.js +73 -0
  245. package/src/lib/hierarchical-memory.js +14 -8
  246. package/src/lib/knowledge-exporter.js +8 -2
  247. package/src/lib/knowledge-graph.js +79 -0
  248. package/src/lib/llm-providers.js +23 -14
  249. package/src/lib/logger.js +4 -1
  250. package/src/lib/lsp/__tests__/benchmark.test.js +88 -0
  251. package/src/lib/lsp/__tests__/code-intelligence.integration.test.js +129 -0
  252. package/src/lib/lsp/__tests__/code-intelligence.test.js +228 -0
  253. package/src/lib/lsp/__tests__/jsonrpc-stream.test.js +104 -0
  254. package/src/lib/lsp/__tests__/lsp-client.test.js +269 -0
  255. package/src/lib/lsp/__tests__/lsp-manager.test.js +333 -0
  256. package/src/lib/lsp/__tests__/lsp-server-registry.test.js +128 -0
  257. package/src/lib/lsp/benchmark.js +257 -0
  258. package/src/lib/lsp/code-intelligence.js +356 -0
  259. package/src/lib/lsp/jsonrpc-stream.js +139 -0
  260. package/src/lib/lsp/lsp-client.js +339 -0
  261. package/src/lib/lsp/lsp-manager.js +375 -0
  262. package/src/lib/lsp/lsp-server-registry.js +196 -0
  263. package/src/lib/matrix-bridge.js +84 -0
  264. package/src/lib/memory-manager.js +5 -3
  265. package/src/lib/nostr-bridge.js +53 -0
  266. package/src/lib/permission-engine.js +22 -4
  267. package/src/lib/plugin-monitor-supervisor.js +238 -0
  268. package/src/lib/plugin-runtime/__tests__/remote-source.test.js +256 -0
  269. package/src/lib/plugin-runtime/agents.js +51 -0
  270. package/src/lib/plugin-runtime/bin.js +100 -0
  271. package/src/lib/plugin-runtime/hooks.js +100 -0
  272. package/src/lib/plugin-runtime/install.js +396 -0
  273. package/src/lib/plugin-runtime/lsp.js +75 -0
  274. package/src/lib/plugin-runtime/manifest.js +458 -0
  275. package/src/lib/plugin-runtime/mcp.js +89 -0
  276. package/src/lib/plugin-runtime/monitors.js +100 -0
  277. package/src/lib/plugin-runtime/policy.js +152 -0
  278. package/src/lib/plugin-runtime/reload.js +79 -0
  279. package/src/lib/plugin-runtime/remote-source.js +240 -0
  280. package/src/lib/plugin-runtime/scopes.js +197 -0
  281. package/src/lib/plugin-runtime/settings.js +119 -0
  282. package/src/lib/plugin-runtime/signature.js +107 -0
  283. package/src/lib/plugin-runtime/skills.js +43 -0
  284. package/src/lib/plugin-runtime/trust.js +140 -0
  285. package/src/lib/pqc-manager.js +64 -0
  286. package/src/lib/reputation-optimizer.js +101 -0
  287. package/src/lib/sandbox-egress-proxy.js +262 -0
  288. package/src/lib/sandbox-fs-policy.js +112 -0
  289. package/src/lib/sandbox-network-policy.js +151 -0
  290. package/src/lib/sandbox-v2.js +24 -18
  291. package/src/lib/scim-manager.js +36 -0
  292. package/src/lib/session-manager.js +5 -2
  293. package/src/lib/settings-hook-events.cjs +78 -6
  294. package/src/lib/settings-hooks.cjs +30 -3
  295. package/src/lib/settings-loader.cjs +35 -1
  296. package/src/lib/siem-exporter.js +45 -0
  297. package/src/lib/skill-loader.js +38 -2
  298. package/src/lib/skill-marketplace.js +83 -0
  299. package/src/lib/sla-manager.js +88 -0
  300. package/src/lib/social-manager.js +74 -0
  301. package/src/lib/stress-tester.js +65 -0
  302. package/src/lib/tech-learning-engine.js +75 -0
  303. package/src/lib/telemetry/span-recorder.js +237 -0
  304. package/src/lib/tenant-saas.js +107 -0
  305. package/src/lib/terraform-manager.js +67 -0
  306. package/src/lib/token-incentive.js +180 -29
  307. package/src/lib/wallet-manager.js +81 -35
  308. package/src/lib/zkp-engine.js +87 -0
  309. package/src/repl/agent-repl.js +417 -6
  310. package/src/runtime/__tests__/auto-pin.test.js +104 -0
  311. package/src/runtime/agent-core.js +771 -104
  312. package/src/runtime/auto-pin.js +117 -0
  313. package/src/runtime/coding-agent-contract-shared.cjs +82 -8
  314. package/src/runtime/coding-agent-policy.cjs +32 -7
  315. package/src/runtime/fallback-model.js +134 -7
  316. package/src/runtime/headless-runner.js +388 -108
  317. package/src/runtime/mcp-config.js +46 -0
  318. package/src/assets/web-panel/assets/ChatBubbleRenderer-DCNfbdlx.js +0 -1
  319. package/src/assets/web-panel/assets/Terminal-BvAK_Zel.js +0 -3
  320. package/src/assets/web-panel/assets/devWarning-C2Z5LRgq.js +0 -1
  321. package/src/assets/web-panel/assets/index-BGp6Yr-Y.js +0 -1
  322. package/src/assets/web-panel/assets/index-BXiw9dQf.js +0 -1
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Plugin `settings` component — a plugin's default configuration (Phase 3.3o).
3
+ *
4
+ * A plugin ships a `settings.json` with defaults. We contribute ONLY the safe,
5
+ * non-security config-override keys — `env` (default environment variables) and
6
+ * `model` (a default model) — as the LOWEST-priority layer: the user's own
7
+ * settings, the system environment, and managed settings ALL override them.
8
+ *
9
+ * SECURITY: a plugin's settings deliberately CANNOT contribute permission rules,
10
+ * hooks, MCP servers, or any security-relevant key — those either have their own
11
+ * dedicated (trust-gated) wiring or must come from the user/managed settings, so
12
+ * a plugin can never widen the permission envelope through `settings.json`. Even
13
+ * so, because `env` can influence tool behavior, collection is trust-gated:
14
+ * only user/local-scope and explicitly-trusted project plugins contribute.
15
+ */
16
+
17
+ import fs from "fs";
18
+ import { discoverPlugins } from "./scopes.js";
19
+ import { partitionByTrust, warnUntrustedOnce } from "./trust.js";
20
+
21
+ export const _deps = { readFileSync: fs.readFileSync };
22
+
23
+ /** Keys a plugin's settings.json is allowed to contribute (safe subset). */
24
+ const SAFE_KEYS = new Set(["env", "model"]);
25
+
26
+ /**
27
+ * Merge trusted plugins' settings.json into a safe defaults object. A later
28
+ * plugin (in discovery precedence) wins on an env-key / model clash.
29
+ *
30
+ * @param {object} [opts] { cwd, scopes }
31
+ * @returns {{ env: Record<string,string>, model: string|null, sources: string[] }}
32
+ */
33
+ export function collectPluginSettings(opts = {}) {
34
+ let plugins = [];
35
+ try {
36
+ plugins = discoverPlugins({ cwd: opts.cwd, scopes: opts.scopes });
37
+ } catch {
38
+ return { env: {}, model: null, sources: [] };
39
+ }
40
+ const { trusted, skipped } = partitionByTrust(plugins);
41
+ warnUntrustedOnce(
42
+ skipped.filter((p) => p.manifest?.components?.settings).map((p) => p.name),
43
+ "settings",
44
+ );
45
+ const env = {};
46
+ let model = null;
47
+ const sources = [];
48
+ for (const p of trusted) {
49
+ if (!p.manifest || p.manifest.ok !== true) continue;
50
+ const s = p.manifest.components?.settings;
51
+ if (!s || !s.absPath) continue;
52
+ let parsed;
53
+ try {
54
+ parsed = JSON.parse(_deps.readFileSync(s.absPath, "utf8"));
55
+ } catch {
56
+ continue;
57
+ }
58
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
59
+ continue;
60
+ let contributed = false;
61
+ // ONLY the safe subset — everything else (permissions/hooks/mcp/…) ignored.
62
+ if (
63
+ SAFE_KEYS.has("env") &&
64
+ parsed.env &&
65
+ typeof parsed.env === "object" &&
66
+ !Array.isArray(parsed.env)
67
+ ) {
68
+ for (const [k, v] of Object.entries(parsed.env)) {
69
+ if (typeof v === "string") {
70
+ env[k] = v;
71
+ contributed = true;
72
+ }
73
+ }
74
+ }
75
+ if (
76
+ SAFE_KEYS.has("model") &&
77
+ typeof parsed.model === "string" &&
78
+ parsed.model.trim()
79
+ ) {
80
+ model = parsed.model.trim();
81
+ contributed = true;
82
+ }
83
+ if (contributed) sources.push(s.absPath);
84
+ }
85
+ return { env, model, sources };
86
+ }
87
+
88
+ /**
89
+ * Apply trusted plugins' default env vars to `env` (defaults to process.env) —
90
+ * but ONLY for keys not already set, so the user's / system's environment always
91
+ * wins. Session-scoped: returns `restore()` + the keys added.
92
+ *
93
+ * @param {object} [opts] { cwd, scopes, env }
94
+ * @returns {{ added: string[], model: string|null, restore: () => void }}
95
+ */
96
+ export function applyPluginSettingsEnv(opts = {}) {
97
+ const env = opts.env || process.env;
98
+ const { env: pluginEnv, model } = collectPluginSettings({
99
+ cwd: opts.cwd,
100
+ scopes: opts.scopes,
101
+ });
102
+ const added = [];
103
+ for (const [k, v] of Object.entries(pluginEnv)) {
104
+ if (env[k] === undefined) {
105
+ env[k] = v;
106
+ added.push(k);
107
+ }
108
+ }
109
+ let restored = false;
110
+ return {
111
+ added,
112
+ model,
113
+ restore: () => {
114
+ if (restored) return;
115
+ restored = true;
116
+ for (const k of added) delete env[k];
117
+ },
118
+ };
119
+ }
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Plugin signature lock (Phase 3.3l — `requireSignedPlugins` load enforcement).
3
+ *
4
+ * `verifyPluginManifest` (../plugin-security.js) verifies a plugin manifest's
5
+ * SHA-256 + detached Ed25519 signature, but only at the moment of `cc plugin
6
+ * add/validate`. To enforce signing at LOAD time (an org's requireSignedPlugins),
7
+ * install records the verification result in a `.plugin-lock.json` inside the
8
+ * immutable version dir; discovery then re-checks it fail-closed.
9
+ *
10
+ * The lock records the manifest's sha256 + the signing key's fingerprint. At
11
+ * load we RE-HASH the on-disk manifest and compare — so a manifest tampered with
12
+ * after install (even inside the version dir) fails the check. The signature
13
+ * itself covers only the manifest file, not every component file — that is a
14
+ * known limitation (documented), an integrity anchor rather than a full
15
+ * supply-chain seal; the immutable version dir + this re-hash catch manifest
16
+ * tampering, which is where the component wiring is declared.
17
+ */
18
+
19
+ import { createHash } from "node:crypto";
20
+ import fs from "fs";
21
+ import path from "path";
22
+
23
+ const LOCK = ".plugin-lock.json";
24
+
25
+ export const _deps = {
26
+ readFileSync: fs.readFileSync,
27
+ writeFileSync: fs.writeFileSync,
28
+ existsSync: fs.existsSync,
29
+ };
30
+
31
+ /** Record a verified signature into the version dir. */
32
+ export function writePluginLock(
33
+ versionDir,
34
+ { manifestFile, sha256, publicKeySha256, signatureVerified },
35
+ ) {
36
+ const rel = path.relative(versionDir, manifestFile).replace(/\\/g, "/");
37
+ const lock = {
38
+ lockVersion: 1,
39
+ manifest: rel || "plugin.json",
40
+ sha256,
41
+ publicKeySha256: publicKeySha256 || null,
42
+ signatureVerified: signatureVerified === true,
43
+ };
44
+ _deps.writeFileSync(
45
+ path.join(versionDir, LOCK),
46
+ JSON.stringify(lock, null, 2),
47
+ "utf8",
48
+ );
49
+ return lock;
50
+ }
51
+
52
+ /** Read a version dir's signature lock, or null when absent/unreadable. */
53
+ export function readPluginLock(versionDir) {
54
+ const p = path.join(versionDir, LOCK);
55
+ if (!_deps.existsSync(p)) return null;
56
+ try {
57
+ return JSON.parse(_deps.readFileSync(p, "utf8"));
58
+ } catch {
59
+ return null;
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Verify an installed plugin's recorded signature against its on-disk manifest.
65
+ * `signed:true` ONLY when a lock exists, was signature-verified, the manifest
66
+ * still hashes to the locked sha256 (tamper detection), and — when trustedKeys
67
+ * is a non-empty Set — the signing key fingerprint is among them.
68
+ *
69
+ * @param {{root:string}} plugin
70
+ * @param {object} [opts] { trustedKeys?: Set<string> }
71
+ * @returns {{ signed:boolean, reason?:string, publicKeySha256?:string }}
72
+ */
73
+ export function verifyInstalledSignature(plugin, opts = {}) {
74
+ const lock = readPluginLock(plugin.root);
75
+ if (!lock) return { signed: false, reason: "no signature lock" };
76
+ if (lock.signatureVerified !== true) {
77
+ return { signed: false, reason: "lock is not signature-verified" };
78
+ }
79
+ const manifestFile = path.join(plugin.root, lock.manifest || "plugin.json");
80
+ if (!_deps.existsSync(manifestFile)) {
81
+ return { signed: false, reason: "locked manifest file is missing" };
82
+ }
83
+ let sha;
84
+ try {
85
+ sha = createHash("sha256")
86
+ .update(_deps.readFileSync(manifestFile))
87
+ .digest("hex");
88
+ } catch {
89
+ return { signed: false, reason: "manifest unreadable" };
90
+ }
91
+ if (sha.toLowerCase() !== String(lock.sha256 || "").toLowerCase()) {
92
+ return {
93
+ signed: false,
94
+ reason: "manifest tampered since install (sha256 mismatch)",
95
+ };
96
+ }
97
+ const trustedKeys = opts.trustedKeys;
98
+ if (trustedKeys && trustedKeys.size > 0) {
99
+ if (!lock.publicKeySha256 || !trustedKeys.has(lock.publicKeySha256)) {
100
+ return {
101
+ signed: false,
102
+ reason: `signing key not trusted (${lock.publicKeySha256 || "unsigned"})`,
103
+ };
104
+ }
105
+ }
106
+ return { signed: true, publicKeySha256: lock.publicKeySha256 };
107
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Discover installed plugins' skill directories so the skill-loader can expose
3
+ * them to the agent (Phase 3.3 — plugin Skill component reaches the agent).
4
+ *
5
+ * A plugin ships skills under `<pluginRoot>/skills/<name>/SKILL.md` (the same
6
+ * `<group>/<skill>/SKILL.md` layout every skill layer uses), so each installed
7
+ * plugin's `skills/` directory becomes an extra skill layer. Only plugins whose
8
+ * manifest fully validated (`manifest.ok`) contribute — a plugin with a
9
+ * traversal/schema error in ANY component loads nothing.
10
+ */
11
+
12
+ import fs from "fs";
13
+ import path from "path";
14
+ import { discoverPlugins } from "./scopes.js";
15
+
16
+ export const _deps = { existsSync: fs.existsSync };
17
+
18
+ /**
19
+ * @param {object} [opts] { cwd, scopes }
20
+ * @returns {Array<{ name, scope, version, path }>} one entry per plugin that has
21
+ * a `skills/` directory; `path` is that directory (a scan root for the loader).
22
+ */
23
+ export function discoverPluginSkillLayers(opts = {}) {
24
+ let plugins = [];
25
+ try {
26
+ plugins = discoverPlugins({ cwd: opts.cwd, scopes: opts.scopes });
27
+ } catch {
28
+ return [];
29
+ }
30
+ const out = [];
31
+ for (const p of plugins) {
32
+ if (!p.manifest || p.manifest.ok !== true) continue;
33
+ const skillsDir = path.join(p.root, "skills");
34
+ if (!_deps.existsSync(skillsDir)) continue;
35
+ out.push({
36
+ name: p.name,
37
+ scope: p.scope,
38
+ version: p.version,
39
+ path: skillsDir,
40
+ });
41
+ }
42
+ return out;
43
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Plugin trust gating (Phase 3.3f) — decide whether a plugin's CODE-BEARING
3
+ * components (hooks that run shell, LSP servers that spawn binaries) are allowed
4
+ * to execute.
5
+ *
6
+ * Threat model: `cc plugin add owner/repo` and, worse, a cloned repo that ships
7
+ * a project-scope plugin under `.chainlesschain/plugins/`, could run arbitrary
8
+ * commands the moment the agent starts. So:
9
+ *
10
+ * - user / local scope → TRUSTED. The developer installed it on their own
11
+ * machine (same consent model as an npm dependency's lifecycle scripts).
12
+ * - project scope → UNTRUSTED until the user explicitly trusts it, since
13
+ * it can arrive with a git clone. Trust is pinned to the exact version, so a
14
+ * later version bump re-requires consent.
15
+ *
16
+ * Trust is recorded in the USER data dir (never in the repo), keyed by
17
+ * `<scope>:<name>` → { version, trustedAt }.
18
+ *
19
+ * Only code execution is gated here. Declarative components (skills are prompts,
20
+ * mcp/settings are config) load regardless; this is specifically about not
21
+ * running untrusted SHELL/binaries behind the user's back.
22
+ */
23
+
24
+ import fs from "fs";
25
+ import path from "path";
26
+ import { getElectronUserDataDir } from "../paths.js";
27
+
28
+ export const _deps = {
29
+ existsSync: fs.existsSync,
30
+ readFileSync: fs.readFileSync,
31
+ writeFileSync: fs.writeFileSync,
32
+ mkdirSync: fs.mkdirSync,
33
+ now: () => new Date().toISOString(),
34
+ // Path of the trust store; injectable so unit tests never touch the real
35
+ // user-data dir.
36
+ storePath: () => path.join(getElectronUserDataDir(), "plugin-trust.json"),
37
+ };
38
+
39
+ const AUTO_TRUSTED_SCOPES = new Set(["user", "local"]);
40
+
41
+ export function loadTrustStore() {
42
+ try {
43
+ const p = _deps.storePath();
44
+ if (!_deps.existsSync(p)) return {};
45
+ const data = JSON.parse(_deps.readFileSync(p, "utf8"));
46
+ return data && typeof data === "object" && !Array.isArray(data) ? data : {};
47
+ } catch {
48
+ return {};
49
+ }
50
+ }
51
+
52
+ function saveTrustStore(store) {
53
+ const p = _deps.storePath();
54
+ _deps.mkdirSync(path.dirname(p), { recursive: true });
55
+ _deps.writeFileSync(p, JSON.stringify(store, null, 2), "utf8");
56
+ }
57
+
58
+ function trustKey(scope, name) {
59
+ return `${scope}:${name}`;
60
+ }
61
+
62
+ /**
63
+ * May this plugin's code-bearing components run?
64
+ * @param {{ scope, name, version }} plugin
65
+ */
66
+ export function isPluginTrusted(plugin) {
67
+ if (!plugin || !plugin.name) return false;
68
+ if (AUTO_TRUSTED_SCOPES.has(plugin.scope)) return true;
69
+ const entry = loadTrustStore()[trustKey(plugin.scope, plugin.name)];
70
+ return Boolean(entry && entry.version === plugin.version);
71
+ }
72
+
73
+ /** Trust a plugin (records the exact version). */
74
+ export function trustPlugin(name, { scope = "project", version } = {}) {
75
+ if (!version) throw new Error("trustPlugin requires a version");
76
+ const store = loadTrustStore();
77
+ store[trustKey(scope, name)] = { version, trustedAt: _deps.now() };
78
+ saveTrustStore(store);
79
+ return { name, scope, version };
80
+ }
81
+
82
+ /** Revoke trust for a plugin at a scope. */
83
+ export function untrustPlugin(name, { scope = "project" } = {}) {
84
+ const store = loadTrustStore();
85
+ const key = trustKey(scope, name);
86
+ const existed = Object.prototype.hasOwnProperty.call(store, key);
87
+ delete store[key];
88
+ saveTrustStore(store);
89
+ return { name, scope, removed: existed };
90
+ }
91
+
92
+ /** All trust entries (for `cc plugin trust --list`). */
93
+ export function listTrust() {
94
+ return Object.entries(loadTrustStore()).map(([key, v]) => {
95
+ const idx = key.indexOf(":");
96
+ return {
97
+ scope: key.slice(0, idx),
98
+ name: key.slice(idx + 1),
99
+ version: v?.version || null,
100
+ trustedAt: v?.trustedAt || null,
101
+ };
102
+ });
103
+ }
104
+
105
+ /**
106
+ * Split discovered plugins into those whose code may run and those gated out.
107
+ * @returns {{ trusted: any[], skipped: any[] }}
108
+ */
109
+ export function partitionByTrust(plugins) {
110
+ const trusted = [];
111
+ const skipped = [];
112
+ for (const p of plugins || []) {
113
+ (isPluginTrusted(p) ? trusted : skipped).push(p);
114
+ }
115
+ return { trusted, skipped };
116
+ }
117
+
118
+ // One-time stderr notice so a user isn't mystified when a project plugin's
119
+ // hooks/servers silently don't run. Guarded so it prints at most once per
120
+ // (component-kind) per process.
121
+ const _warned = new Set();
122
+ export function warnUntrustedOnce(names, kind) {
123
+ if (!names || names.length === 0) return;
124
+ if (_warned.has(kind)) return;
125
+ _warned.add(kind);
126
+ const list = [...new Set(names)].join(", ");
127
+ try {
128
+ process.stderr.write(
129
+ `[plugins] skipped ${kind} from untrusted project plugin(s): ${list}\n` +
130
+ ` run \`cc plugin trust <name>\` to enable them.\n`,
131
+ );
132
+ } catch {
133
+ /* stderr notice is best-effort */
134
+ }
135
+ }
136
+
137
+ /** Test hook: reset the one-time warning guard. */
138
+ export function _resetTrustWarnings() {
139
+ _warned.clear();
140
+ }
@@ -178,6 +178,70 @@ export function ensurePQCTables(db) {
178
178
  `);
179
179
  }
180
180
 
181
+ /**
182
+ * Rehydrate _keys/_migrations from the persisted pqc_keys/pqc_migration_status
183
+ * tables. The `cc` CLI runs every command in a fresh process, so without this
184
+ * the Maps start empty and a key generated / migration run in a prior
185
+ * invocation is invisible (`cc pqc keys` reports "No PQC keys" and `cc pqc
186
+ * migration-status` is empty even when the rows exist; `cc pqc migrate` counts
187
+ * sourceKeys off the empty Map and reports "Migrated 0/0" while real keys sit
188
+ * unmigrated). Call after ensurePQCTables(db). NOTE: this module holds only
189
+ * public-key inventory metadata — there is no private key or sign/verify path
190
+ * here — so the impact is inventory visibility + migration accounting, not
191
+ * crypto verification.
192
+ */
193
+ export function loadFromDb(db) {
194
+ if (!db) return 0;
195
+ _keys.clear();
196
+ _migrations.clear();
197
+
198
+ const keyRows = db.prepare(`SELECT * FROM pqc_keys`).all();
199
+ for (const row of keyRows) {
200
+ let metadata = {};
201
+ try {
202
+ metadata = row.metadata ? JSON.parse(row.metadata) : {};
203
+ } catch {
204
+ metadata = {};
205
+ }
206
+ // Derived fields (family/publicKeyBytes/signatureBytes) come from the
207
+ // algorithm spec, not the DB — reconstruct them exactly as generateKey does.
208
+ const spec = ALGORITHM_SPECS[row.algorithm] || {};
209
+ _keys.set(row.id, {
210
+ id: row.id,
211
+ algorithm: row.algorithm,
212
+ family: spec.family ?? null,
213
+ purpose: row.purpose,
214
+ publicKey: row.public_key,
215
+ keySize: row.key_size ?? spec.keySize ?? 0,
216
+ publicKeyBytes: spec.publicKeyBytes ?? null,
217
+ signatureBytes: spec.signatureBytes ?? null,
218
+ hybridMode: !!row.hybrid_mode,
219
+ classicalAlgorithm: row.classical_algorithm ?? null,
220
+ status: row.status,
221
+ metadata,
222
+ createdAt: row.created_at ?? null,
223
+ });
224
+ }
225
+
226
+ const migRows = db.prepare(`SELECT * FROM pqc_migration_status`).all();
227
+ for (const row of migRows) {
228
+ _migrations.set(row.id, {
229
+ id: row.id,
230
+ planName: row.plan_name,
231
+ sourceAlgorithm: row.source_algorithm,
232
+ targetAlgorithm: row.target_algorithm,
233
+ totalKeys: row.total_keys ?? 0,
234
+ migratedKeys: row.migrated_keys ?? 0,
235
+ status: row.status,
236
+ startedAt: row.started_at ?? null,
237
+ completedAt: row.completed_at ?? null,
238
+ errorMessage: row.error_message ?? null,
239
+ });
240
+ }
241
+
242
+ return _keys.size + _migrations.size;
243
+ }
244
+
181
245
  /* ── Key Management ───────────────────────────────────────── */
182
246
 
183
247
  export function listKeys(filter = {}) {
@@ -509,6 +509,107 @@ export function _resetState() {
509
509
  _maxConcurrentOptimizations = DEFAULT_MAX_CONCURRENT_OPTIMIZATIONS;
510
510
  }
511
511
 
512
+ /**
513
+ * Rehydrate the in-memory Maps from the persisted reputation_* tables. The CLI
514
+ * runs each `cc reputation` subcommand in a fresh node process, so
515
+ * _observations/_runs/_analytics start empty every invocation. Every write
516
+ * dual-writes (Map + INSERT into reputation_observations/
517
+ * reputation_optimization_runs/reputation_analytics) but every read
518
+ * (computeScore/listScores/detectAnomalies/getOptimizationStatus/getAnalytics/
519
+ * listOptimizationRuns/applyOptimizedParams + the V2 drivers) is Map-only and
520
+ * nothing SELECTed the tables back — so observed scores read back as 0, `list`/
521
+ * `runs`/`anomalies` were always empty, and `status`/`complete`/`apply <runId>`
522
+ * threw "Optimization run not found" for a run that genuinely exists on disk.
523
+ * Call after ensureReputationTables(db).
524
+ *
525
+ * Non-persisted fields default safely: run.history=[] (V1), errorMessage=null.
526
+ */
527
+ export function loadFromDb(db) {
528
+ if (!db) return 0;
529
+ ensureReputationTables(db);
530
+ _observations.clear();
531
+ _runs.clear();
532
+ _analytics.clear();
533
+
534
+ for (const r of db
535
+ .prepare(
536
+ `SELECT observation_id, did, score, kind, weight, recorded_at
537
+ FROM reputation_observations ORDER BY recorded_at ASC`,
538
+ )
539
+ .all()) {
540
+ if (!_observations.has(r.did)) _observations.set(r.did, []);
541
+ _observations.get(r.did).push({
542
+ observationId: r.observation_id,
543
+ did: r.did,
544
+ score: Number(r.score),
545
+ kind: r.kind,
546
+ weight: Number(r.weight),
547
+ recordedAt: Number(r.recorded_at),
548
+ });
549
+ }
550
+
551
+ for (const r of db
552
+ .prepare(
553
+ `SELECT run_id, objective, iterations, param_space, best_params, best_score,
554
+ status, created_at, completed_at
555
+ FROM reputation_optimization_runs ORDER BY created_at ASC`,
556
+ )
557
+ .all()) {
558
+ // One corrupt param/params cell must not sink the whole run list.
559
+ let paramSpace = {};
560
+ let bestParams = null;
561
+ try {
562
+ paramSpace = r.param_space ? JSON.parse(r.param_space) : {};
563
+ } catch {
564
+ paramSpace = {};
565
+ }
566
+ try {
567
+ bestParams = r.best_params ? JSON.parse(r.best_params) : null;
568
+ } catch {
569
+ bestParams = null;
570
+ }
571
+ _runs.set(r.run_id, {
572
+ runId: r.run_id,
573
+ objective: r.objective,
574
+ iterations: Number(r.iterations),
575
+ paramSpace,
576
+ bestParams,
577
+ bestScore: r.best_score == null ? null : Number(r.best_score),
578
+ errorMessage: null,
579
+ status: r.status,
580
+ createdAt: Number(r.created_at),
581
+ completedAt: r.completed_at == null ? null : Number(r.completed_at),
582
+ history: [],
583
+ _seq: ++_seq,
584
+ });
585
+ }
586
+
587
+ for (const r of db
588
+ .prepare(
589
+ `SELECT analytics_id, run_id, reputation_distribution, anomalies, recommendations, created_at
590
+ FROM reputation_analytics ORDER BY created_at ASC`,
591
+ )
592
+ .all()) {
593
+ const parse = (v, fallback) => {
594
+ try {
595
+ return v ? JSON.parse(v) : fallback;
596
+ } catch {
597
+ return fallback;
598
+ }
599
+ };
600
+ _analytics.set(r.run_id, {
601
+ analyticsId: r.analytics_id,
602
+ runId: r.run_id,
603
+ reputationDistribution: parse(r.reputation_distribution, {}),
604
+ anomalies: parse(r.anomalies, []),
605
+ recommendations: parse(r.recommendations, []),
606
+ createdAt: Number(r.created_at),
607
+ });
608
+ }
609
+
610
+ return _observations.size + _runs.size + _analytics.size;
611
+ }
612
+
512
613
  /* ═══════════════════════════════════════════════════════════════
513
614
  * V2 (Phase 60) — Frozen enums + async optimization lifecycle +
514
615
  * concurrency limiter + patch-merged setRunStatus + stats-v2.