chainlesschain 0.162.149 → 0.162.151

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 (285) hide show
  1. package/README.md +1 -1
  2. package/package.json +3 -2
  3. package/src/assets/web-panel/assets/{AIOps-BJif14yR.js → AIOps-DuEOzebi.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-CXek6gJY.js → ActionButton-C6GiJa5H.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-BgQhdAJi.js → Analytics-BBIiL_pO.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-DTYl5NtR.js → AppLayout-CuI2gZRy.js} +3 -3
  7. package/src/assets/web-panel/assets/{Audit-BzATQAeR.js → Audit-CbUjfr-K.js} +1 -1
  8. package/src/assets/web-panel/assets/{Backup-BzdPEQhL.js → Backup-CsSW9ljf.js} +1 -1
  9. package/src/assets/web-panel/assets/{BaseInput-BM0KVh8E.js → BaseInput-kM3rLe7F.js} +1 -1
  10. package/src/assets/web-panel/assets/{Chat-D7fHXHkz.js → Chat-kfE51YN3.js} +4 -4
  11. package/src/assets/web-panel/assets/{ChatBubbleRenderer-Wm34RR-b.js → ChatBubbleRenderer-Bg2FTW6A.js} +1 -1
  12. package/src/assets/web-panel/assets/{Checkbox-CAiSQ9vO.js → Checkbox-jYb1uj-M.js} +1 -1
  13. package/src/assets/web-panel/assets/{Codegen-Df40CrEe.js → Codegen-X9XiD5Lj.js} +1 -1
  14. package/src/assets/web-panel/assets/{Col-DIT2fNFU.js → Col-BfbHu1xI.js} +1 -1
  15. package/src/assets/web-panel/assets/{Community-CSTIbW2k.js → Community-c4oJMFS-.js} +1 -1
  16. package/src/assets/web-panel/assets/{Compact-DtqXZZUi.js → Compact-BFmnZpH7.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compliance-CUtzw6o7.js → Compliance-s9shVHBS.js} +1 -1
  18. package/src/assets/web-panel/assets/{Cowork-CezmlnmU.js → Cowork-C5da--TC.js} +2 -2
  19. package/src/assets/web-panel/assets/{Cron-P4BITarg.js → Cron-9kNbyNE4.js} +2 -2
  20. package/src/assets/web-panel/assets/{Crosschain-BRRiYwvq.js → Crosschain-C1k3NJD4.js} +1 -1
  21. package/src/assets/web-panel/assets/{DID-L5ijB9i4.js → DID-DkheEvNK.js} +2 -2
  22. package/src/assets/web-panel/assets/{Dashboard-CFxro4ob.js → Dashboard-C3FuSGmJ.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dropdown-BmAFCQ71.js → Dropdown-CAV6FMFD.js} +1 -1
  24. package/src/assets/web-panel/assets/{EmailListRenderer-DJBCEuon.js → EmailListRenderer-Cc-Ulc4l.js} +1 -1
  25. package/src/assets/web-panel/assets/{FamilyGuardDashboard-z4oLq6eT.js → FamilyGuardDashboard-8CitHEtv.js} +1 -1
  26. package/src/assets/web-panel/assets/{Federation-DsVCpHMF.js → Federation-DFSZ5KDt.js} +1 -1
  27. package/src/assets/web-panel/assets/{FormItemContext-DP3bP5th.js → FormItemContext-CEWCtnG2.js} +1 -1
  28. package/src/assets/web-panel/assets/{GenericCardRenderer-BAXP2Gc6.js → GenericCardRenderer-CwRzNzmX.js} +1 -1
  29. package/src/assets/web-panel/assets/{Git-I3g_bAw9.js → Git-0rgDM7cJ.js} +2 -2
  30. package/src/assets/web-panel/assets/{Governance-jHS5-ioS.js → Governance-CfBKtK9F.js} +1 -1
  31. package/src/assets/web-panel/assets/{Inference-CPL7sfx9.js → Inference-CzcUVvud.js} +1 -1
  32. package/src/assets/web-panel/assets/{KnowledgeGraph-Jf236h4C.js → KnowledgeGraph-Dwc4YL4A.js} +1 -1
  33. package/src/assets/web-panel/assets/{Logs-Cm2tcSKg.js → Logs-DgFPwR2F.js} +2 -2
  34. package/src/assets/web-panel/assets/{Marketplace-CZK82rhi.js → Marketplace-DnpPTbGU.js} +1 -1
  35. package/src/assets/web-panel/assets/{McpTools-CZCeji7a.js → McpTools-DRxxINyW.js} +4 -4
  36. package/src/assets/web-panel/assets/{Memory-3l2KVS9k.js → Memory-OhmW_6Z3.js} +2 -2
  37. package/src/assets/web-panel/assets/{MobileBridge-VYdpoLh6.js → MobileBridge-DkTW-RK5.js} +1 -1
  38. package/src/assets/web-panel/assets/{MobileProjects-CiB9cmm1.js → MobileProjects-DpCGV_lI.js} +1 -1
  39. package/src/assets/web-panel/assets/{Mtc-wCFZbBuL.js → Mtc--vmkL0AS.js} +2 -2
  40. package/src/assets/web-panel/assets/{MtcAudit-1a3THIyG.js → MtcAudit-DGoFWjD4.js} +4 -4
  41. package/src/assets/web-panel/assets/{Multisig-DMzLB2hG.js → Multisig-B4kWgq95.js} +3 -3
  42. package/src/assets/web-panel/assets/{NLProgramming-D9wZbf6l.js → NLProgramming-YQwvommE.js} +1 -1
  43. package/src/assets/web-panel/assets/{Notes-hrFe2ZM-.js → Notes-CgjtUADJ.js} +3 -3
  44. package/src/assets/web-panel/assets/{NotificationSettings-CHGX5Jwm.js → NotificationSettings-6JDrpBG5.js} +1 -1
  45. package/src/assets/web-panel/assets/OrderTableRenderer-PM6IlxjO.js +1 -0
  46. package/src/assets/web-panel/assets/{Organization-By7FkhtY.js → Organization-8McOT_OF.js} +4 -4
  47. package/src/assets/web-panel/assets/{Overflow--khGSzJn.js → Overflow-DAZpSCGc.js} +1 -1
  48. package/src/assets/web-panel/assets/{P2P-CAG9dH35.js → P2P-B7l2ZWLy.js} +2 -2
  49. package/src/assets/web-panel/assets/{PdhVaultBrowser-B3SQZmK9.js → PdhVaultBrowser-W1Ud-NAL.js} +3 -3
  50. package/src/assets/web-panel/assets/{Permissions-D35ec6JA.js → Permissions-Czm_w9u_.js} +4 -4
  51. package/src/assets/web-panel/assets/{PersonalDataHub-CxBF7hW_.js → PersonalDataHub-B4F0_ZVM.js} +2 -2
  52. package/src/assets/web-panel/assets/{Pipeline-s6EtOO1s.js → Pipeline-B37aFiWv.js} +1 -1
  53. package/src/assets/web-panel/assets/{Privacy-BbJYmWmO.js → Privacy-94KBnRrD.js} +1 -1
  54. package/src/assets/web-panel/assets/{ProjectInit-VGQq1jMT.js → ProjectInit-B5h8_dlh.js} +2 -2
  55. package/src/assets/web-panel/assets/{ProjectSettings-B1ew3Teh.js → ProjectSettings-lmeI3Lpm.js} +2 -2
  56. package/src/assets/web-panel/assets/Projects-D5AYOasl.js +1 -0
  57. package/src/assets/web-panel/assets/{Providers-mrO47FIK.js → Providers-B3cNWwJg.js} +1 -1
  58. package/src/assets/web-panel/assets/{QrScannerModal-IJF2mHyw.js → QrScannerModal-CHRvOw1R.js} +1 -1
  59. package/src/assets/web-panel/assets/{QuickAsk-CU0wN_Z0.js → QuickAsk-D1JMgFEd.js} +1 -1
  60. package/src/assets/web-panel/assets/{Recommend-DhN37R6G.js → Recommend-EYWGR79p.js} +1 -1
  61. package/src/assets/web-panel/assets/{RemoteSession-D_xOX_hu.js → RemoteSession-BAMC2pJt.js} +2 -2
  62. package/src/assets/web-panel/assets/{Reputation-D_Ssv7uH.js → Reputation-X2Hk1XG_.js} +1 -1
  63. package/src/assets/web-panel/assets/{Row-Kx5dKxX7.js → Row-Eq98LRtU.js} +1 -1
  64. package/src/assets/web-panel/assets/{RssFeed-BlGwqZkY.js → RssFeed-i76s6z_o.js} +2 -2
  65. package/src/assets/web-panel/assets/{Search-hLFQzxpb.js → Search-D_Es7CAI.js} +1 -1
  66. package/src/assets/web-panel/assets/{Security-DMlvsVt4.js → Security-kayD2e94.js} +3 -3
  67. package/src/assets/web-panel/assets/{Services-Bd0Qsj2m.js → Services-Ctsm6ul8.js} +2 -2
  68. package/src/assets/web-panel/assets/{Skeleton-DFclq9X3.js → Skeleton-CRNYlfdf.js} +1 -1
  69. package/src/assets/web-panel/assets/{Skills-BNtln2qY.js → Skills-DkZYpF4-.js} +1 -1
  70. package/src/assets/web-panel/assets/{Sla-Dch5H19G.js → Sla-DXkoBcOP.js} +1 -1
  71. package/src/assets/web-panel/assets/{SpeechSettings-2UfQcU1g.js → SpeechSettings-DXi_GI1d.js} +1 -1
  72. package/src/assets/web-panel/assets/{SyncSettings-CD9YQr4i.js → SyncSettings-rNKpfomn.js} +2 -2
  73. package/src/assets/web-panel/assets/{Tasks-BNu-7MzI.js → Tasks-XF4uPtG-.js} +1 -1
  74. package/src/assets/web-panel/assets/{Templates-D1n9CaIR.js → Templates-i0Hzfeyu.js} +1 -1
  75. package/src/assets/web-panel/assets/{Tenant-DenL3iBW.js → Tenant-sMpHAi27.js} +1 -1
  76. package/src/assets/web-panel/assets/Terminal-BoZvaYAl.js +3 -0
  77. package/src/assets/web-panel/assets/{TimelineRenderer-D87IfukO.js → TimelineRenderer-yuC6K7Rf.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tokens-BkiZc8E3.js → Tokens-B8O8i0s6.js} +1 -1
  79. package/src/assets/web-panel/assets/{Trigger-BNRSytGN.js → Trigger-Bv6yrlCr.js} +1 -1
  80. package/src/assets/web-panel/assets/{Trust-Bwbd4X2m.js → Trust-C4mW95Ev.js} +1 -1
  81. package/src/assets/web-panel/assets/{UkeySign-B8O2bs0o.js → UkeySign-DV6yKaHn.js} +1 -1
  82. package/src/assets/web-panel/assets/{VideoEditing-C2fL8zmH.js → VideoEditing-UI479-sD.js} +1 -1
  83. package/src/assets/web-panel/assets/{Wallet-BORYDdE1.js → Wallet-M5oV9EVP.js} +4 -4
  84. package/src/assets/web-panel/assets/{WebAuthn-C0V5S2FM.js → WebAuthn-DDyDHPDR.js} +4 -4
  85. package/src/assets/web-panel/assets/{WorkflowEditor-2dR0fcHL.js → WorkflowEditor-RoBv4rqk.js} +1 -1
  86. package/src/assets/web-panel/assets/{chat-BmuAFAn8.js → chat-Cw1mE5LS.js} +1 -1
  87. package/src/assets/web-panel/assets/{colors-CN3smMcK.js → colors-BFP62Gwf.js} +1 -1
  88. package/src/assets/web-panel/assets/{compact-item-DCnxb4kW.js → compact-item-17HL6pyC.js} +1 -1
  89. package/src/assets/web-panel/assets/{createContext-vlR43pHn.js → createContext-D55X4fZX.js} +1 -1
  90. package/src/assets/web-panel/assets/devWarning-CqbHYuRc.js +1 -0
  91. package/src/assets/web-panel/assets/{hasIn-D04tHYFd.js → hasIn-D3E5mNsP.js} +1 -1
  92. package/src/assets/web-panel/assets/{index-DbVsQBOH.js → index--44J50mc.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-TslMTwNy.js → index-ASPYTzMK.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-CTOCnIQ7.js → index-BC6zxOlU.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-ljuBiQW9.js → index-BEa1RW4c.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-jzR7Ujuw.js → index-BQmZg5si.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-BudvKQfG.js → index-BY_xZ2jy.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-CP9m9Ggr.js → index-BgN5G5vF.js} +3 -3
  99. package/src/assets/web-panel/assets/{index-Cr-A0FYJ.js → index-BnGpft-Z.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-D5LZVZ0L.js → index-Bq83UBDr.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-ToUh2b1-.js → index-Bzpp2z2S.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-DbADHwhr.js → index-CFYGn88j.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-ClhAHDK3.js → index-CGyTos4p.js} +1 -1
  104. package/src/assets/web-panel/assets/index-CKBI1U5K.js +1 -0
  105. package/src/assets/web-panel/assets/{index-C-6NO5il.js → index-CLEzsZ8A.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-D8vwp4qp.js → index-CR9rNUvi.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-_FIkN3jd.js → index-CW6LLoJO.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-D65_XseV.js → index-C_MfcrLf.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-CnXebZLL.js → index-Cdvk2_2q.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-D_n8_vfI.js → index-CjCwi7we.js} +1 -1
  111. package/src/assets/web-panel/assets/index-CkLp6DTO.js +1 -0
  112. package/src/assets/web-panel/assets/{index-DDwLgQY9.js → index-CvCFKojj.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-430S68MN.js → index-D4LHSde4.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BXRg8GFQ.js → index-DCLu84x-.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-DTtRscUa.js → index-DD_qGBrt.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-BasvsWDM.js → index-DIRvdwBX.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-BeGDEXFs.js → index-DOjA8bvj.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CsAsCPJ6.js → index-Da27u6j0.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-D28DeAAB.js → index-DkBVYlE4.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CngCC8hC.js → index-DtAnPBWP.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-B78xL3s2.js → index-DzG7mkgW.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DIpY0qM5.js → index-H9_X1Cg_.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-C5Sxb1sE.js → index-ITeEHb8L.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-BTPEZTk1.js → index-KtLJXn4s.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-hpvvtAZ3.js → index-RYZgFIwo.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-HhNjnCfe.js → index-gAVxDiTZ.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-DTWg-18U.js → index-paVubXzn.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-BqhASEL4.js → index-tUH_6bdJ.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-DYAtmqiv.js → index-tVRPgYGr.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-0DnaZGkC.js → index-uSsiwgZ2.js} +1 -1
  131. package/src/assets/web-panel/assets/{initDefaultProps-C3wUb4je.js → initDefaultProps-Ckp7xVZS.js} +1 -1
  132. package/src/assets/web-panel/assets/{motion-D-jYFUNA.js → motion-DUZgCpn6.js} +1 -1
  133. package/src/assets/web-panel/assets/{move-tqb8nwJ2.js → move-B2rttglH.js} +1 -1
  134. package/src/assets/web-panel/assets/{mtc-parser-DSOjMJMz.js → mtc-parser-BYWcLTuN.js} +1 -1
  135. package/src/assets/web-panel/assets/{omit-CJ7VimIW.js → omit-DhHqKeFx.js} +1 -1
  136. package/src/assets/web-panel/assets/{pickAttrs-qXiG1iT3.js → pickAttrs-ANpJaWMO.js} +1 -1
  137. package/src/assets/web-panel/assets/{placementArrow-CkGBcy1Z.js → placementArrow-CfZWe7CA.js} +1 -1
  138. package/src/assets/web-panel/assets/{responsiveObserve-D3WvTlLO.js → responsiveObserve-D7Xz2y-R.js} +1 -1
  139. package/src/assets/web-panel/assets/{slide-BEE2ftge.js → slide-DekqCBY9.js} +1 -1
  140. package/src/assets/web-panel/assets/{statusUtils-CsfBpxiG.js → statusUtils-BET6XU7h.js} +1 -1
  141. package/src/assets/web-panel/assets/{styleChecker-xPrIiJPI.js → styleChecker-qHmJjV62.js} +1 -1
  142. package/src/assets/web-panel/assets/{useFlexGapSupport-C5Yd-SCR.js → useFlexGapSupport-BoMCTNyu.js} +1 -1
  143. package/src/assets/web-panel/assets/{useFs-D_MDS8HI.js → useFs-TdW-NgFC.js} +1 -1
  144. package/src/assets/web-panel/assets/{usePersonalDataHub-BqJh-usA.js → usePersonalDataHub-Dyox7wCu.js} +1 -1
  145. package/src/assets/web-panel/assets/{vnode-chm_p-gz.js → vnode-XUn5S8CP.js} +1 -1
  146. package/src/assets/web-panel/assets/{zoom-3-YDNz0Z.js → zoom-Ls77i8hn.js} +1 -1
  147. package/src/assets/web-panel/index.html +1 -1
  148. package/src/command-manifest.json +8 -1
  149. package/src/commands/a2a.js +19 -4
  150. package/src/commands/activitypub.js +20 -3
  151. package/src/commands/agent.js +27 -5
  152. package/src/commands/audit.js +40 -24
  153. package/src/commands/changelog.js +148 -0
  154. package/src/commands/codeintel.js +68 -0
  155. package/src/commands/collab.js +15 -2
  156. package/src/commands/compliance.js +5 -0
  157. package/src/commands/config.js +4 -1
  158. package/src/commands/dao.js +86 -14
  159. package/src/commands/dev.js +2 -0
  160. package/src/commands/did.js +7 -1
  161. package/src/commands/dlp.js +23 -1
  162. package/src/commands/economy.js +29 -3
  163. package/src/commands/eval.js +7 -0
  164. package/src/commands/evomap.js +26 -0
  165. package/src/commands/governance.js +17 -3
  166. package/src/commands/hardening.js +18 -0
  167. package/src/commands/incentive.js +5 -0
  168. package/src/commands/init.js +46 -2
  169. package/src/commands/kg.js +4 -0
  170. package/src/commands/loop.js +6 -1
  171. package/src/commands/lowcode.js +15 -2
  172. package/src/commands/marketplace.js +40 -6
  173. package/src/commands/matrix.js +20 -1
  174. package/src/commands/memory.js +4 -1
  175. package/src/commands/mtc.js +7 -1
  176. package/src/commands/nostr.js +31 -4
  177. package/src/commands/note.js +7 -4
  178. package/src/commands/plugin.js +125 -5
  179. package/src/commands/pqc.js +5 -0
  180. package/src/commands/reputation.js +10 -1
  181. package/src/commands/scim.js +6 -0
  182. package/src/commands/session.js +32 -10
  183. package/src/commands/siem.js +11 -0
  184. package/src/commands/sla.js +18 -3
  185. package/src/commands/social.js +38 -5
  186. package/src/commands/sso.js +10 -2
  187. package/src/commands/stress.js +23 -4
  188. package/src/commands/team.js +9 -2
  189. package/src/commands/tech.js +2 -0
  190. package/src/commands/tenant.js +10 -1
  191. package/src/commands/terraform.js +6 -0
  192. package/src/commands/update.js +1 -1
  193. package/src/commands/zkp.js +20 -0
  194. package/src/data/changelog.json +189 -0
  195. package/src/gateways/ws/message-dispatcher.js +5 -2
  196. package/src/gateways/ws/remote-session-protocol.js +110 -42
  197. package/src/harness/jsonl-session-store.js +12 -5
  198. package/src/harness/plugin-manager.js +16 -4
  199. package/src/harness/remote-command-ledger.js +46 -15
  200. package/src/harness/worktree-isolator.js +16 -6
  201. package/src/index.js +2 -0
  202. package/src/lib/__tests__/logger.test.js +5 -2
  203. package/src/lib/a2a-protocol.js +25 -1
  204. package/src/lib/activitypub-bridge.js +61 -0
  205. package/src/lib/agent-core.js +2 -0
  206. package/src/lib/agent-economy.js +262 -29
  207. package/src/lib/agent-network.js +7 -1
  208. package/src/lib/agent-team/team-runner.js +25 -9
  209. package/src/lib/agent-team/team-worktree.js +36 -4
  210. package/src/lib/async-hook-supervisor.cjs +102 -16
  211. package/src/lib/audit-logger.js +7 -6
  212. package/src/lib/autonomous-developer.js +60 -0
  213. package/src/lib/changelog.js +252 -0
  214. package/src/lib/chat-core.js +17 -4
  215. package/src/lib/collaboration-governance.js +56 -0
  216. package/src/lib/community-governance.js +68 -0
  217. package/src/lib/compliance-manager.js +63 -0
  218. package/src/lib/cross-chain.js +5 -0
  219. package/src/lib/dao-governance.js +151 -2
  220. package/src/lib/did-manager.js +23 -10
  221. package/src/lib/dlp-engine.js +70 -0
  222. package/src/lib/eval/runner.js +89 -1
  223. package/src/lib/eval/tasks.js +170 -0
  224. package/src/lib/eval/trend.js +16 -1
  225. package/src/lib/evolution-system.js +92 -0
  226. package/src/lib/evomap-federation.js +55 -0
  227. package/src/lib/evomap-governance.js +94 -0
  228. package/src/lib/fatal-handler.js +17 -1
  229. package/src/lib/hardening-manager.js +73 -0
  230. package/src/lib/hierarchical-memory.js +14 -8
  231. package/src/lib/knowledge-exporter.js +8 -2
  232. package/src/lib/knowledge-graph.js +79 -0
  233. package/src/lib/llm-providers.js +23 -14
  234. package/src/lib/logger.js +4 -1
  235. package/src/lib/lsp/__tests__/benchmark.test.js +88 -0
  236. package/src/lib/lsp/__tests__/lsp-client.test.js +11 -0
  237. package/src/lib/lsp/__tests__/lsp-manager.test.js +69 -0
  238. package/src/lib/lsp/benchmark.js +257 -0
  239. package/src/lib/lsp/lsp-client.js +30 -9
  240. package/src/lib/lsp/lsp-manager.js +54 -2
  241. package/src/lib/lsp/lsp-server-registry.js +15 -4
  242. package/src/lib/matrix-bridge.js +84 -0
  243. package/src/lib/memory-manager.js +5 -3
  244. package/src/lib/nostr-bridge.js +53 -0
  245. package/src/lib/permission-engine.js +22 -4
  246. package/src/lib/plugin-runtime/__tests__/remote-source.test.js +256 -0
  247. package/src/lib/plugin-runtime/hooks.js +20 -4
  248. package/src/lib/plugin-runtime/install.js +9 -1
  249. package/src/lib/plugin-runtime/monitors.js +20 -4
  250. package/src/lib/plugin-runtime/policy.js +9 -1
  251. package/src/lib/plugin-runtime/remote-source.js +240 -0
  252. package/src/lib/plugin-runtime/signature.js +16 -0
  253. package/src/lib/pqc-manager.js +64 -0
  254. package/src/lib/reputation-optimizer.js +101 -0
  255. package/src/lib/sandbox-egress-proxy.js +195 -59
  256. package/src/lib/sandbox-fs-policy.js +112 -0
  257. package/src/lib/sandbox-network-policy.js +44 -5
  258. package/src/lib/sandbox-v2.js +14 -14
  259. package/src/lib/scim-manager.js +36 -0
  260. package/src/lib/session-manager.js +5 -2
  261. package/src/lib/settings-hooks.cjs +1 -0
  262. package/src/lib/siem-exporter.js +45 -0
  263. package/src/lib/skill-loader.js +20 -2
  264. package/src/lib/skill-marketplace.js +83 -0
  265. package/src/lib/sla-manager.js +88 -0
  266. package/src/lib/social-manager.js +74 -0
  267. package/src/lib/stress-tester.js +65 -0
  268. package/src/lib/tech-learning-engine.js +75 -0
  269. package/src/lib/telemetry/span-recorder.js +12 -1
  270. package/src/lib/tenant-saas.js +107 -0
  271. package/src/lib/terraform-manager.js +67 -0
  272. package/src/lib/token-incentive.js +180 -29
  273. package/src/lib/wallet-manager.js +81 -35
  274. package/src/lib/zkp-engine.js +87 -0
  275. package/src/repl/agent-repl.js +17 -2
  276. package/src/runtime/__tests__/auto-pin.test.js +104 -0
  277. package/src/runtime/agent-core.js +241 -68
  278. package/src/runtime/auto-pin.js +117 -0
  279. package/src/runtime/headless-runner.js +35 -0
  280. package/src/assets/web-panel/assets/OrderTableRenderer-CRIFE2Tj.js +0 -1
  281. package/src/assets/web-panel/assets/Projects-CGcNIs_g.js +0 -1
  282. package/src/assets/web-panel/assets/Terminal-ZzU0Io1Y.js +0 -3
  283. package/src/assets/web-panel/assets/devWarning-DxwmsL4j.js +0 -1
  284. package/src/assets/web-panel/assets/index-Cg2ldRfU.js +0 -1
  285. package/src/assets/web-panel/assets/index-Dwzo-dtJ.js +0 -1
@@ -23,9 +23,10 @@
23
23
  * flight — a rapid PostToolUse hook can't stack N copies of itself;
24
24
  * - a maxConcurrent cap — overflow is DROPPED with a recorded skip, never
25
25
  * queued unbounded;
26
- * - a per-hook timeout that kills the child;
27
- * - reaping of every child on stopAll() / process 'exit', so a session never
28
- * leaves an orphan hook process.
26
+ * - a per-hook timeout that TREE-kills the child (shell + the real command it
27
+ * spawned a bare child.kill would orphan the grandchild);
28
+ * - tree-reaping of every child on stopAll() / process 'exit', so a session
29
+ * never leaves an orphan hook process.
29
30
  *
30
31
  * `_deps.spawn` / `_deps.now` are injected so the whole supervisor is unit-
31
32
  * testable with fake child processes (no real shell).
@@ -37,6 +38,12 @@ const { tryParseDecision } = require("./hook-runner.cjs");
37
38
  const DEFAULT_TIMEOUT_MS = 60000;
38
39
  const MAX_TIMEOUT_MS = 600000;
39
40
  const DEFAULT_MAX_CONCURRENT = 4;
41
+ // Ring cap on undrained records (parity with PluginMonitorSupervisor's
42
+ // OUTPUT_RING): drainResults()/drainRewakes() normally clear each turn, but a
43
+ // stalled/absent drain over a high-frequency hook would otherwise grow these
44
+ // arrays without bound. Keep only the most recent RESULT_RING; older records
45
+ // are dropped oldest-first.
46
+ const RESULT_RING = 500;
40
47
 
41
48
  class AsyncHookSupervisor {
42
49
  constructor(opts = {}) {
@@ -46,20 +53,87 @@ class AsyncHookSupervisor {
46
53
  : DEFAULT_MAX_CONCURRENT;
47
54
  this._deps = {
48
55
  spawn: opts.spawn || cpDefault.spawn,
56
+ spawnSync: opts.spawnSync || cpDefault.spawnSync,
49
57
  now: opts.now || (() => Date.now()),
50
58
  };
51
59
  this._running = new Map(); // key -> { child, timer }
52
60
  this._results = []; // completed records awaiting drainResults()
53
61
  this._rewakes = []; // failed asyncRewake records awaiting drainRewakes()
54
62
  this._stopped = false;
63
+ // The exit reaper is installed LAZILY (on first spawn), not in the ctor:
64
+ // a supervisor that never dispatches a hook (or the many built in tests)
65
+ // must not leave a permanent `process.once('exit')` listener behind —
66
+ // that accumulates across sessions/instances into a MaxListenersExceeded
67
+ // leak. Mirrors PluginMonitorSupervisor._installExitHook.
55
68
  this._exitHook = () => this.stopAll();
56
- process.once("exit", this._exitHook);
69
+ this._exitHookInstalled = false;
57
70
  }
58
71
 
59
72
  _key(hook) {
60
73
  return `${hook.event || ""}::${hook.command}`;
61
74
  }
62
75
 
76
+ /**
77
+ * Kill a hook child's WHOLE process tree. Hooks run with `shell: true`, so the
78
+ * real command is a grandchild of the shell — a plain `child.kill()` only
79
+ * signals the shell (POSIX: reparents + keeps the command running; Windows:
80
+ * killing cmd.exe never touches its children), orphaning the actual hook
81
+ * process. POSIX: the child is spawned detached (its own group), so a negative
82
+ * pid signals the whole group. Windows: `taskkill /T` walks the tree. Both are
83
+ * SYNCHRONOUS (spawnSync / process.kill) so this is safe inside stopAll() and
84
+ * the process 'exit' reaper, where async work would be cut off. A child with no
85
+ * real pid (the unit-test fakes) falls back to its own `.kill()`.
86
+ */
87
+ _killChildTree(child, signal = "SIGTERM") {
88
+ if (!child) return;
89
+ const pid = child.pid;
90
+ if (typeof pid !== "number" || pid <= 0) {
91
+ try {
92
+ child.kill(signal);
93
+ } catch {
94
+ /* already gone / fake with no kill */
95
+ }
96
+ return;
97
+ }
98
+ try {
99
+ if (process.platform === "win32") {
100
+ const r = this._deps.spawnSync(
101
+ "taskkill",
102
+ ["/pid", String(pid), "/T", "/F"],
103
+ { windowsHide: true },
104
+ );
105
+ // If taskkill couldn't launch, fall back to a direct kill.
106
+ if (r && r.error) child.kill(signal);
107
+ } else {
108
+ // Negative pid → the whole process group (requires the detached spawn).
109
+ try {
110
+ process.kill(-pid, signal);
111
+ } catch {
112
+ child.kill(signal);
113
+ }
114
+ }
115
+ } catch {
116
+ try {
117
+ child.kill(signal);
118
+ } catch {
119
+ /* already gone */
120
+ }
121
+ }
122
+ }
123
+
124
+ /** Install the process-exit reaper exactly once, only when a child exists. */
125
+ _installExitHook() {
126
+ if (this._exitHookInstalled) return;
127
+ this._exitHookInstalled = true;
128
+ process.once("exit", this._exitHook);
129
+ }
130
+
131
+ /** Append a result record, bounded to the most recent RESULT_RING. */
132
+ _pushResult(rec) {
133
+ this._results.push(rec);
134
+ if (this._results.length > RESULT_RING) this._results.shift();
135
+ }
136
+
63
137
  /**
64
138
  * Dispatch a batch of async hooks fire-and-forget. Returns IMMEDIATELY with a
65
139
  * per-hook disposition (`{command, dispatched, reason?}`) — it never awaits a
@@ -100,7 +174,7 @@ class AsyncHookSupervisor {
100
174
  });
101
175
  // Record the skip so the caller/agent can SEE that a hook was dropped
102
176
  // (silent truncation would read as "the hook ran and said nothing").
103
- this._results.push({
177
+ this._pushResult({
104
178
  command: hook.command,
105
179
  event: hook.event || null,
106
180
  ok: false,
@@ -121,6 +195,9 @@ class AsyncHookSupervisor {
121
195
  }
122
196
 
123
197
  _spawnOne(hook, payload, opts) {
198
+ // A live child now exists — arm the exit reaper so a session never leaves
199
+ // an orphan hook process (installed once, only from here).
200
+ this._installExitHook();
124
201
  const key = this._key(hook);
125
202
  const started = this._deps.now();
126
203
  const rawTimeout = Number(
@@ -136,6 +213,10 @@ class AsyncHookSupervisor {
136
213
  child = this._deps.spawn(hook.command, {
137
214
  cwd: opts.cwd || process.cwd(),
138
215
  shell: true,
216
+ // POSIX: own process group so a timeout / stopAll can signal the whole
217
+ // tree (shell + the real hook command), not just the shell wrapper.
218
+ // No-op on Windows, where the tree is reaped via `taskkill /T` instead.
219
+ detached: process.platform !== "win32",
139
220
  env: {
140
221
  ...process.env,
141
222
  CLAUDE_HOOK_EVENT: hook.event || payload.hook_event_name || "",
@@ -158,6 +239,13 @@ class AsyncHookSupervisor {
158
239
  this._running.set(key, rec);
159
240
 
160
241
  try {
242
+ // `.end(data)` flushes ASYNCHRONOUSLY: if the hook exited before consuming
243
+ // stdin (a fast command), the write fails with an async EPIPE emitted as an
244
+ // 'error' event on the stream — NOT a sync throw this catch can see. With no
245
+ // listener that becomes an uncaught exception that crashes the process (seen
246
+ // on Linux CI). Attach a no-op error handler first so a closed-stdin write
247
+ // is swallowed as the non-fatal condition it is.
248
+ child.stdin?.on("error", () => {});
161
249
  child.stdin?.end(JSON.stringify(payload));
162
250
  } catch {
163
251
  /* stdin may already be closed — non-fatal */
@@ -171,11 +259,9 @@ class AsyncHookSupervisor {
171
259
 
172
260
  const timer = setTimeout(() => {
173
261
  killedByTimeout = true;
174
- try {
175
- child.kill("SIGTERM");
176
- } catch {
177
- /* already gone */
178
- }
262
+ // Tree-kill: a hook that spawned a subprocess (e.g. `npm test`) must not
263
+ // leave that subprocess orphaned when it exceeds its timeout.
264
+ this._killChildTree(child, "SIGTERM");
179
265
  }, timeout);
180
266
  if (typeof timer.unref === "function") timer.unref();
181
267
  rec.timer = timer;
@@ -240,11 +326,12 @@ class AsyncHookSupervisor {
240
326
  ts: now,
241
327
  ms: fields.started != null ? now - fields.started : 0,
242
328
  };
243
- this._results.push(rec);
329
+ this._pushResult(rec);
244
330
  // A rewake fires only for a hook that OPTED IN and finished in a failure
245
331
  // state — a passing async check should not re-engage the agent.
246
332
  if (hook.asyncRewake && !rec.ok) {
247
333
  this._rewakes.push(rec);
334
+ if (this._rewakes.length > RESULT_RING) this._rewakes.shift();
248
335
  }
249
336
  }
250
337
 
@@ -283,11 +370,9 @@ class AsyncHookSupervisor {
283
370
  } catch {
284
371
  /* ignore */
285
372
  }
286
- try {
287
- rec.child.kill("SIGTERM");
288
- } catch {
289
- /* already gone */
290
- }
373
+ // Tree-kill (not a bare child.kill) so a session end / process exit never
374
+ // leaves an orphaned hook subprocess — the guarantee this class documents.
375
+ this._killChildTree(rec.child, "SIGTERM");
291
376
  this._running.delete(key);
292
377
  }
293
378
  try {
@@ -295,6 +380,7 @@ class AsyncHookSupervisor {
295
380
  } catch {
296
381
  /* ignore */
297
382
  }
383
+ this._exitHookInstalled = false;
298
384
  }
299
385
  }
300
386
 
@@ -5,6 +5,7 @@
5
5
 
6
6
  import crypto from "crypto";
7
7
  import { safeJsonParse } from "./safe-json.js";
8
+ import { escapeLike } from "./sql-like.js";
8
9
 
9
10
  /**
10
11
  * Event types for audit logging.
@@ -183,13 +184,13 @@ export function queryLogs(db, filters = {}) {
183
184
  }
184
185
 
185
186
  if (filters.operation) {
186
- sql += " AND operation LIKE ?";
187
- params.push(`%${filters.operation}%`);
187
+ sql += " AND operation LIKE ? ESCAPE '\\'";
188
+ params.push(`%${escapeLike(filters.operation)}%`);
188
189
  }
189
190
 
190
191
  if (filters.actor) {
191
- sql += " AND actor LIKE ?";
192
- params.push(`%${filters.actor}%`);
192
+ sql += " AND actor LIKE ? ESCAPE '\\'";
193
+ params.push(`%${escapeLike(filters.actor)}%`);
193
194
  }
194
195
 
195
196
  if (filters.riskLevel) {
@@ -214,8 +215,8 @@ export function queryLogs(db, filters = {}) {
214
215
 
215
216
  if (filters.search) {
216
217
  // Search in operation field (primary search field for CLI)
217
- sql += " AND operation LIKE ?";
218
- params.push(`%${filters.search}%`);
218
+ sql += " AND operation LIKE ? ESCAPE '\\'";
219
+ params.push(`%${escapeLike(filters.search)}%`);
219
220
  }
220
221
 
221
222
  sql += " ORDER BY created_at DESC";
@@ -151,6 +151,66 @@ export function ensureAutonomousDevTables(db) {
151
151
  );
152
152
  }
153
153
 
154
+ /**
155
+ * Rehydrate _sessions/_adrs from the persisted dev_sessions/
156
+ * architecture_decisions tables. The `cc` CLI runs every command in a fresh
157
+ * process, so without this the Maps start empty and a session/ADR created in a
158
+ * prior invocation is invisible (`cc dev list`/`show`/`adrs` show nothing) and
159
+ * every mutation — recordADR, advancePhase, etc. — throws "Session not found"
160
+ * against the empty Map. Call after ensureAutonomousDevTables(db).
161
+ */
162
+ export function loadFromDb(db) {
163
+ if (!db) return 0;
164
+ _sessions.clear();
165
+ _adrs.clear();
166
+
167
+ const parse = (v, fallback) => {
168
+ if (v == null) return fallback;
169
+ try {
170
+ return JSON.parse(v);
171
+ } catch {
172
+ return fallback;
173
+ }
174
+ };
175
+
176
+ const sessionRows = db.prepare(`SELECT * FROM dev_sessions`).all();
177
+ for (const row of sessionRows) {
178
+ _sessions.set(row.session_id, {
179
+ sessionId: row.session_id,
180
+ requirement: row.requirement,
181
+ currentPhase: row.current_phase,
182
+ status: row.status,
183
+ autonomyLevel: row.autonomy_level ?? 2,
184
+ codeChanges: parse(row.code_changes, []),
185
+ testResults: parse(row.test_results, null),
186
+ reviewFeedback: parse(row.review_feedback, null),
187
+ startedAt: row.started_at,
188
+ completedAt: row.completed_at ?? null,
189
+ createdBy: row.created_by ?? null,
190
+ updatedAt: row.updated_at,
191
+ _seq: ++_seq,
192
+ });
193
+ }
194
+
195
+ const adrRows = db.prepare(`SELECT * FROM architecture_decisions`).all();
196
+ for (const row of adrRows) {
197
+ _adrs.set(row.adr_id, {
198
+ adrId: row.adr_id,
199
+ sessionId: row.session_id,
200
+ title: row.title,
201
+ context: row.context,
202
+ decision: row.decision,
203
+ consequences: row.consequences ?? "",
204
+ alternatives: parse(row.alternatives, []),
205
+ status: row.status,
206
+ createdAt: row.created_at,
207
+ _seq: ++_seq,
208
+ });
209
+ }
210
+
211
+ return _sessions.size + _adrs.size;
212
+ }
213
+
154
214
  /* ── Catalogs ──────────────────────────────────────────────── */
155
215
 
156
216
  export function listAutonomyLevels() {
@@ -0,0 +1,252 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
+
7
+ /**
8
+ * The `cc changelog` data source.
9
+ *
10
+ * The canonical update record is the repository-root `CHANGELOG.md`, which is
11
+ * organized by PRODUCT version (`## [v5.0.3.x]`). Each block references the CLI
12
+ * npm version (`chainlesschain 0.162.x`) it shipped. This parser distills that
13
+ * into a CLI-focused view: it keeps only blocks that actually reference a CLI
14
+ * npm version, and within each block keeps only the CLI-relevant sub-sections.
15
+ *
16
+ * At publish time `scripts/build-changelog.mjs` runs `parseChangelog` over the
17
+ * root CHANGELOG and writes the result to `src/data/changelog.json`, which is
18
+ * bundled with the npm package. `loadChangelog()` reads that file (with a
19
+ * fallback to parsing a raw CHANGELOG.md for in-repo dev use).
20
+ */
21
+
22
+ // Signals that a `### ` sub-section HEADING is about the CLI npm package rather
23
+ // than the desktop app / Android / iOS / PDH portions of the same product
24
+ // release. CASE-SENSITIVE on purpose: real CLI notes write the acronym "CLI"
25
+ // (e.g. "cc CLI 0.162.150", "CLI 安全"), whereas PDH/Android bundle-roll notes
26
+ // write the version tag lowercase ("(pdh 0.4.6 / cli 0.162.48)"). Matching only
27
+ // uppercase "CLI" keeps collector releases that merely bundle a cli bump out of
28
+ // the CLI view. Heading-only (not body) for the same reason.
29
+ const CLI_HEADING_SIGNAL = /\bCLI\b|命令行/;
30
+
31
+ // A block with no `### ` sub-sections is a CLI release only if its header or
32
+ // preamble uses CLI-publish language. Same case-sensitivity: a lowercase
33
+ // bundle-roll "cli 0.162.x" mention is not enough.
34
+ const CLI_PUBLISH_SIGNAL = /\bCLI\b|命令行|catch-up/;
35
+
36
+ // CLI npm versions are 3-segment (0.162.x). The `(?<![\d.])` / `(?!\.\d)` guards
37
+ // stop a 4-segment PRODUCT version (v5.0.3.134) from matching as "5.0.3".
38
+ const V = "(?<![\\d.])(\\d+\\.\\d+\\.\\d+)(?!\\.\\d)";
39
+
40
+ /**
41
+ * Extract every CLI npm version token referenced in a block of text and return
42
+ * the "primary" one (the highest semver — the released target in a
43
+ * `0.162.149 → 0.162.150` style note).
44
+ *
45
+ * @param {string} text
46
+ * @returns {{ primary: string|null, all: string[] }}
47
+ */
48
+ export function extractCliVersions(text) {
49
+ const found = new Set();
50
+ const patterns = [
51
+ // "cc CLI 0.162.150", "CLI 0.162.150"
52
+ new RegExp(`(?:cc\\s+)?cli\\s+${V}`, "gi"),
53
+ // "chainlesschain` 0.162.149 → **0.162.150**" (capture the arrow target)
54
+ new RegExp(
55
+ `chainlesschain[\`\\s]+(?:\\d+\\.\\d+\\.\\d+\\s*(?:→|->)\\s*)?\\*{0,2}${V}`,
56
+ "gi",
57
+ ),
58
+ // bare "cli 0.162.71" inside "(pdh 0.4.25 / cli 0.162.71)"
59
+ new RegExp(`\\bcli\\s+${V}`, "gi"),
60
+ // "→ 0.162.150" / "→ **0.162.150**"
61
+ new RegExp(`(?:→|->)\\s*\\*{0,2}${V}`, "gi"),
62
+ ];
63
+ for (const re of patterns) {
64
+ let m;
65
+ while ((m = re.exec(text)) !== null) {
66
+ found.add(m[1]);
67
+ }
68
+ }
69
+ // The CLI npm package (`chainlesschain`) is on the 0.x alpha track; the
70
+ // product line is 5.x. Keeping only major-0 tokens discards any product
71
+ // version (v5.0.3.x) or desktop-app-vue (5.0.3-alpha.x) tokens that slip past
72
+ // the context regexes, so the "primary" is always a real CLI npm version.
73
+ const all = [...found].filter((v) => v.startsWith("0."));
74
+ const primary =
75
+ all.length === 0
76
+ ? null
77
+ : all.reduce(
78
+ (best, v) => (compareSemver(v, best) > 0 ? v : best),
79
+ all[0],
80
+ );
81
+ return { primary, all };
82
+ }
83
+
84
+ /** Numeric semver compare for plain X.Y.Z (no prerelease). */
85
+ export function compareSemver(a, b) {
86
+ const pa = a.split(".").map(Number);
87
+ const pb = b.split(".").map(Number);
88
+ for (let i = 0; i < 3; i++) {
89
+ if ((pa[i] || 0) !== (pb[i] || 0)) return (pa[i] || 0) - (pb[i] || 0);
90
+ }
91
+ return 0;
92
+ }
93
+
94
+ /**
95
+ * Parse a raw CHANGELOG.md string into CLI-focused release entries.
96
+ *
97
+ * @param {string} md
98
+ * @returns {Array<{
99
+ * productVersion: string,
100
+ * cliVersion: string|null,
101
+ * cliVersions: string[],
102
+ * date: string|null,
103
+ * title: string,
104
+ * sections: Array<{ heading: string, body: string }>,
105
+ * }>}
106
+ */
107
+ export function parseChangelog(md) {
108
+ const lines = md.split(/\r?\n/);
109
+ const blocks = [];
110
+ let current = null;
111
+
112
+ for (const line of lines) {
113
+ const h2 = line.match(/^##\s+(.+)$/);
114
+ if (h2 && !line.startsWith("###")) {
115
+ if (current) blocks.push(current);
116
+ current = { header: h2[1].trim(), lines: [] };
117
+ continue;
118
+ }
119
+ if (current) current.lines.push(line);
120
+ }
121
+ if (current) blocks.push(current);
122
+
123
+ const releases = [];
124
+ for (const block of blocks) {
125
+ const parsed = parseBlockHeader(block.header);
126
+ const bodyText = block.lines.join("\n");
127
+ const fullText = block.header + "\n" + bodyText;
128
+
129
+ const { primary, all } = extractCliVersions(fullText);
130
+ // A release must reference a CLI npm version at all.
131
+ if (!primary) continue;
132
+
133
+ // CLI-relevance gate is decided by section HEADINGS (or, for a section-less
134
+ // block, by CLI-publish language) — not by a bare bundled-cli mention.
135
+ const sections = extractCliSections(block.lines, block.header);
136
+ if (!sections) continue;
137
+
138
+ releases.push({
139
+ productVersion: parsed.version,
140
+ cliVersion: primary,
141
+ cliVersions: all.sort(compareSemver),
142
+ date: parsed.date,
143
+ title: parsed.title,
144
+ sections,
145
+ });
146
+ }
147
+ return releases;
148
+ }
149
+
150
+ /** Parse "## [v5.0.3.134] - 2026-07-03 — title" into parts. */
151
+ function parseBlockHeader(header) {
152
+ const tag = header.match(/\[([^\]]+)\]/);
153
+ const version = tag ? tag[1] : header;
154
+ const rest = header.replace(/\[[^\]]+\]\s*/, "");
155
+ const dateMatch = rest.match(/(\d{4}-\d{2}-\d{2})/);
156
+ const date = dateMatch ? dateMatch[1] : null;
157
+ // Title = text after the em dash separator, else whatever remains.
158
+ let title = "";
159
+ const emDash = rest.split(/\s+—\s+/);
160
+ if (emDash.length > 1) {
161
+ title = emDash.slice(1).join(" — ").trim();
162
+ } else {
163
+ title = rest
164
+ .replace(/^-\s*/, "")
165
+ .replace(/\d{4}-\d{2}-\d{2}/, "")
166
+ .trim();
167
+ }
168
+ return { version, date, title };
169
+ }
170
+
171
+ /**
172
+ * Split a block body into `### ` sub-sections and keep only CLI-relevant ones.
173
+ *
174
+ * Returns:
175
+ * - an array of CLI sections, when the block is a CLI release; or
176
+ * - `null`, when the block is NOT a CLI release (all-non-CLI sub-sections, e.g.
177
+ * a PDH/Android collector release that merely bundles a new cli version).
178
+ *
179
+ * @param {string[]} bodyLines
180
+ * @param {string} header
181
+ * @returns {Array<{heading:string, body:string}>|null}
182
+ */
183
+ function extractCliSections(bodyLines, header) {
184
+ const sections = [];
185
+ const preamble = [];
186
+ let cur = null;
187
+ for (const line of bodyLines) {
188
+ const h3 = line.match(/^###\s+(.+)$/);
189
+ if (h3) {
190
+ if (cur) sections.push(cur);
191
+ cur = { heading: h3[1].trim(), lines: [] };
192
+ continue;
193
+ }
194
+ if (cur) cur.lines.push(line);
195
+ else preamble.push(line); // before the first ### (blockquote summary etc.)
196
+ }
197
+ if (cur) sections.push(cur);
198
+
199
+ if (sections.length === 0) {
200
+ // Section-less block: CLI release only if the `##` TITLE names the CLI.
201
+ // The preamble is NOT consulted — every block carries a boilerplate
202
+ // "Version surfaces: CLI 0.162.x → ..." line, so a body match would let
203
+ // every PDH/Android release through.
204
+ if (!CLI_PUBLISH_SIGNAL.test(header)) return null;
205
+ const body = preamble.join("\n").trim();
206
+ return body ? [{ heading: "", body }] : [];
207
+ }
208
+
209
+ const cliSections = sections
210
+ .filter((s) => CLI_HEADING_SIGNAL.test(s.heading))
211
+ .map((s) => ({ heading: s.heading, body: s.lines.join("\n").trim() }));
212
+
213
+ // Has `### ` sections but none are CLI-headed → not a CLI release.
214
+ return cliSections.length > 0 ? cliSections : null;
215
+ }
216
+
217
+ /**
218
+ * Resolve and load the CLI changelog data.
219
+ *
220
+ * Order is CHANGELOG-FIRST so the data can never go stale: when the repo-root
221
+ * CHANGELOG.md is reachable (source checkout / dev / this monorepo) it is parsed
222
+ * live, always reflecting the latest edits. The bundled `src/data/changelog.json`
223
+ * (a build artifact, refreshed at `prepublishOnly`) is only the fallback for an
224
+ * installed npm package, where CHANGELOG.md is not shipped.
225
+ *
226
+ * @returns {{ source: string, releases: Array }}
227
+ */
228
+ export function loadChangelog() {
229
+ const changelogCandidates = [
230
+ path.join(__dirname, "..", "..", "CHANGELOG.md"), // packages/cli/CHANGELOG.md
231
+ path.join(__dirname, "..", "..", "..", "..", "CHANGELOG.md"), // repo root
232
+ ];
233
+ for (const p of changelogCandidates) {
234
+ if (fs.existsSync(p)) {
235
+ return {
236
+ source: "CHANGELOG.md",
237
+ releases: parseChangelog(fs.readFileSync(p, "utf-8")),
238
+ };
239
+ }
240
+ }
241
+ // Installed npm package: CHANGELOG.md isn't shipped, use the bundled artifact.
242
+ const jsonPath = path.join(__dirname, "..", "data", "changelog.json");
243
+ if (fs.existsSync(jsonPath)) {
244
+ try {
245
+ const data = JSON.parse(fs.readFileSync(jsonPath, "utf-8"));
246
+ if (Array.isArray(data.releases)) return data;
247
+ } catch {
248
+ /* fall through to empty */
249
+ }
250
+ }
251
+ return { source: null, releases: [] };
252
+ }
@@ -134,6 +134,11 @@ export async function streamOllama(
134
134
  const reader = response.body.getReader();
135
135
  const decoder = new TextDecoder();
136
136
  let fullResponse = "";
137
+ // Buffer incomplete lines across reads: an NDJSON line can be split across two
138
+ // stream chunks (TCP doesn't align to '\n'), so parsing each chunk in
139
+ // isolation would drop the split line entirely (both halves fail JSON.parse).
140
+ // Keep the trailing partial for the next read — same pattern as streamAnthropic.
141
+ let buf = "";
137
142
 
138
143
  try {
139
144
  while (true) {
@@ -141,10 +146,12 @@ export async function streamOllama(
141
146
  if (done) break;
142
147
  guard.bump();
143
148
 
144
- const text = decoder.decode(value, { stream: true });
145
- const lines = text.split("\n").filter(Boolean);
149
+ buf += decoder.decode(value, { stream: true });
150
+ const lines = buf.split("\n");
151
+ buf = lines.pop() || "";
146
152
 
147
153
  for (const line of lines) {
154
+ if (!line) continue;
148
155
  try {
149
156
  const json = JSON.parse(line);
150
157
  if (json.message?.content) {
@@ -225,6 +232,11 @@ export async function streamOpenAI(
225
232
  const reader = response.body.getReader();
226
233
  const decoder = new TextDecoder();
227
234
  let fullResponse = "";
235
+ // Buffer incomplete lines across reads: an SSE `data:` line can be split
236
+ // across two stream chunks, so parsing each chunk in isolation would drop the
237
+ // split line (both halves fail JSON.parse) — losing content and usage. Keep
238
+ // the trailing partial for the next read — same pattern as streamAnthropic.
239
+ let buf = "";
228
240
 
229
241
  try {
230
242
  while (true) {
@@ -232,8 +244,9 @@ export async function streamOpenAI(
232
244
  if (done) break;
233
245
  guard.bump();
234
246
 
235
- const text = decoder.decode(value, { stream: true });
236
- const lines = text.split("\n").filter(Boolean);
247
+ buf += decoder.decode(value, { stream: true });
248
+ const lines = buf.split("\n");
249
+ buf = lines.pop() || "";
237
250
 
238
251
  for (const line of lines) {
239
252
  if (line.startsWith("data: ")) {
@@ -129,6 +129,62 @@ export function ensureGovernanceTables(db) {
129
129
  );
130
130
  }
131
131
 
132
+ /**
133
+ * Rehydrate _decisions/_agentLevels from the persisted governance_decisions/
134
+ * autonomy_levels tables. The `cc` CLI runs every command in a fresh process, so
135
+ * without this the Maps start empty and a decision/level set in a prior
136
+ * invocation is invisible (`cc collab decisions`/`show`/`agents` show nothing),
137
+ * decision voting throws "not found", and setAutonomyLevel on a cold Map takes
138
+ * the INSERT branch on an already-persisted agent_id → PRIMARY KEY conflict.
139
+ * Call after ensureGovernanceTables(db).
140
+ */
141
+ export function loadFromDb(db) {
142
+ if (!db) return 0;
143
+ _decisions.clear();
144
+ _agentLevels.clear();
145
+
146
+ const parse = (v, fallback) => {
147
+ if (v == null) return fallback;
148
+ try {
149
+ return JSON.parse(v);
150
+ } catch {
151
+ return fallback;
152
+ }
153
+ };
154
+
155
+ const decisionRows = db.prepare(`SELECT * FROM governance_decisions`).all();
156
+ for (const row of decisionRows) {
157
+ _decisions.set(row.decision_id, {
158
+ decisionId: row.decision_id,
159
+ type: row.type,
160
+ proposal: row.proposal,
161
+ status: row.status,
162
+ votes: parse(row.votes, {}),
163
+ resolution: row.resolution ?? null,
164
+ executedAt: row.executed_at ?? null,
165
+ createdAt: row.created_at,
166
+ updatedAt: row.updated_at,
167
+ _seq: ++_seq,
168
+ });
169
+ }
170
+
171
+ const levelRows = db.prepare(`SELECT * FROM autonomy_levels`).all();
172
+ for (const row of levelRows) {
173
+ _agentLevels.set(row.agent_id, {
174
+ agentId: row.agent_id,
175
+ currentLevel: row.current_level,
176
+ permissions: parse(row.permissions, []),
177
+ adjustmentHistory: parse(row.adjustment_history, []),
178
+ lastReviewAt: row.last_review_at ?? null,
179
+ createdAt: row.created_at,
180
+ updatedAt: row.updated_at,
181
+ _seq: ++_seq,
182
+ });
183
+ }
184
+
185
+ return _decisions.size + _agentLevels.size;
186
+ }
187
+
132
188
  /* ── Catalogs ──────────────────────────────────────────────── */
133
189
 
134
190
  export function listDecisionTypes() {