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
@@ -6,6 +6,7 @@
6
6
  import crypto from "crypto";
7
7
  import { safeJsonParse } from "./safe-json.js";
8
8
  import { evaluateNetworkAccess } from "./sandbox-network-policy.js";
9
+ import { evaluatePathAccess } from "./sandbox-fs-policy.js";
9
10
  import { createRequire } from "module";
10
11
 
11
12
  const _require = createRequire(import.meta.url);
@@ -142,20 +143,19 @@ export function ensureSandboxTables(db) {
142
143
  // ─── Permission checking ──────────────────────────────────────
143
144
 
144
145
  function checkFilePermission(permissions, filePath, mode) {
145
- const fs = permissions.fileSystem || {};
146
- const denied = fs.denied || [];
147
- for (const d of denied) {
148
- if (filePath.startsWith(d)) return false;
149
- }
150
- if (mode === "read") {
151
- const allowed = fs.read || [];
152
- return allowed.some((p) => filePath.startsWith(p));
153
- }
154
- if (mode === "write") {
155
- const allowed = fs.write || [];
156
- return allowed.some((p) => filePath.startsWith(p));
157
- }
158
- return false;
146
+ // Delegate to the shared path policy: `path.resolve` collapses `..` (traversal),
147
+ // a `path.relative` boundary rejects `/tmpfoo` matching `/tmp`, and symlinks are
148
+ // resolved so a link inside an allowed dir can't escape. The old check was
149
+ // `filePath.startsWith(root)` and let all three through.
150
+ const fsPol = permissions.fileSystem || {};
151
+ return evaluatePathAccess(filePath, {
152
+ mode,
153
+ policy: {
154
+ read: fsPol.read || [],
155
+ write: fsPol.write || [],
156
+ denied: fsPol.denied || [],
157
+ },
158
+ }).allowed;
159
159
  }
160
160
 
161
161
  function checkNetworkPermission(permissions, host) {
@@ -211,6 +211,42 @@ export function _resetState() {
211
211
  _syncLog.length = 0;
212
212
  }
213
213
 
214
+ /**
215
+ * Rehydrate the in-memory _users Map from the persisted scim_resources table.
216
+ * The CLI runs each `cc scim` subcommand in a fresh node process, so _users
217
+ * starts empty every invocation. createUser dual-writes (Map + INSERT INTO
218
+ * scim_resources) but listUsers/getUser/deleteUser/getStatus are Map-only and
219
+ * nothing SELECTed the table back — so a provisioned user was invisible next
220
+ * invocation (`No SCIM users.` / `User not found`), and deleteUser threw before
221
+ * its DELETE ran, orphaning rows with no CLI path to remove them. The duplicate
222
+ * check in createUser was also blind, allowing duplicate userNames on disk.
223
+ * Call after ensureSCIMTables(db).
224
+ *
225
+ * Mirrors the write-side shape exactly (active INTEGER→boolean).
226
+ */
227
+ export function loadFromDb(db) {
228
+ if (!db) return 0;
229
+ ensureSCIMTables(db);
230
+ _users.clear();
231
+ for (const r of db
232
+ .prepare(
233
+ `SELECT id, display_name, user_name, email, active, created_at, updated_at
234
+ FROM scim_resources WHERE resource_type = 'User' ORDER BY created_at ASC`,
235
+ )
236
+ .all()) {
237
+ _users.set(r.id, {
238
+ id: r.id,
239
+ userName: r.user_name,
240
+ displayName: r.display_name || r.user_name,
241
+ email: r.email || null,
242
+ active: !!r.active,
243
+ createdAt: r.created_at,
244
+ updatedAt: r.updated_at,
245
+ });
246
+ }
247
+ return _users.size;
248
+ }
249
+
214
250
  /* ═══════════════════════════════════════════════════════════════
215
251
  * V2 Surface — SCIM provisioning lifecycle layer.
216
252
  * Tracks identities and sync-job lifecycle independent of legacy
@@ -129,10 +129,13 @@ export function getSession(db, sessionId) {
129
129
 
130
130
  return {
131
131
  ...session,
132
- messages: JSON.parse(session.messages || "[]"),
132
+ // A single corrupt (non-JSON, non-empty) column must not make the whole
133
+ // session unloadable — that would block resume of the user's own data.
134
+ // Matches the safeJsonParse fallback listSessions already uses.
135
+ messages: safeJsonParse(session.messages, []),
133
136
  metadata:
134
137
  typeof session.metadata === "string"
135
- ? JSON.parse(session.metadata || "{}")
138
+ ? safeJsonParse(session.metadata, {})
136
139
  : session.metadata || {},
137
140
  };
138
141
  }
@@ -48,6 +48,7 @@ const HOOK_EVENTS = Object.freeze([
48
48
  "ConfigChange",
49
49
  "PreCompact",
50
50
  "Notification",
51
+ "PermissionRequest",
51
52
  ]);
52
53
 
53
54
  /**
@@ -136,6 +136,51 @@ export function _resetState() {
136
136
  _exports.length = 0;
137
137
  }
138
138
 
139
+ /**
140
+ * Rehydrate the in-memory _targets Map from the persisted siem_exports table.
141
+ * The CLI runs each `cc siem` subcommand in a fresh node process, so _targets
142
+ * starts empty every invocation. addTarget dual-writes (Map + INSERT INTO
143
+ * siem_exports) but every read (listTargets/exportLogs/getSIEMStats/
144
+ * removeTarget/setTargetStatus/listTargetsByStatus) is Map-only and nothing
145
+ * SELECTed the table back — so a target added in one invocation was invisible in
146
+ * the next (`No SIEM targets configured.`) and `siem export <id>` hard-crashed
147
+ * with `Target not found` for a target that genuinely exists on disk. Call after
148
+ * ensureSIEMTables(db).
149
+ */
150
+ export function loadFromDb(db) {
151
+ if (!db) return 0;
152
+ ensureSIEMTables(db);
153
+ _targets.clear();
154
+ for (const r of db
155
+ .prepare(
156
+ `SELECT id, target_type, target_url, format, last_exported_log_id,
157
+ exported_count, last_export_at, status, config, created_at
158
+ FROM siem_exports ORDER BY created_at ASC`,
159
+ )
160
+ .all()) {
161
+ // One corrupt config cell must not sink the whole target load.
162
+ let config = {};
163
+ try {
164
+ config = r.config ? JSON.parse(r.config) : {};
165
+ } catch {
166
+ config = {};
167
+ }
168
+ _targets.set(r.id, {
169
+ id: r.id,
170
+ type: r.target_type,
171
+ url: r.target_url,
172
+ format: r.format,
173
+ exportedCount: Number(r.exported_count) || 0,
174
+ lastExportAt: r.last_export_at ?? null,
175
+ lastExportedLogId: r.last_exported_log_id ?? null,
176
+ status: r.status,
177
+ config,
178
+ createdAt: r.created_at,
179
+ });
180
+ }
181
+ return _targets.size;
182
+ }
183
+
139
184
  // ═══════════════════════════════════════════════════════════════
140
185
  // V2 Canonical Surface (Phase 51)
141
186
  // ═══════════════════════════════════════════════════════════════
@@ -84,6 +84,17 @@ export const LAYER_NAMES = [
84
84
  * `<group>/<skill>/SKILL.md` layouts (infinite-recursion / deep-tree guard). */
85
85
  export const MAX_SKILL_NEST_DEPTH = 5;
86
86
 
87
+ // Frontmatter keys (camelCased) that are semantically strings and are consumed
88
+ // with string methods; they must never be number/boolean-coerced. `version` is
89
+ // deliberately excluded — it is only string-interpolated and existing behavior
90
+ // coerces it to a number.
91
+ const STRING_SCALAR_FIELDS = new Set([
92
+ "name",
93
+ "displayName",
94
+ "description",
95
+ "category",
96
+ ]);
97
+
87
98
  /**
88
99
  * Simple YAML frontmatter parser (no dependencies)
89
100
  * Shared utility extracted from skill.js
@@ -165,8 +176,15 @@ export function parseSkillMd(content) {
165
176
  continue;
166
177
  }
167
178
 
168
- // Handle booleans and numbers
169
- if (value === "true") value = true;
179
+ // Handle booleans and numbers. These fields are string-semantic and get
180
+ // used with string methods downstream (skill.id.includes(),
181
+ // description.substring(), category/displayName.toLowerCase()); coercing a
182
+ // bare numeric ("2024") or boolean value to Number/Boolean makes those
183
+ // throw and aborts the whole `cc skill list/search/run` command on a
184
+ // single such skill — so never coerce them. (version stays coercible.)
185
+ if (STRING_SCALAR_FIELDS.has(camelKey))
186
+ value = value.replace(/^['"]|['"]$/g, "");
187
+ else if (value === "true") value = true;
170
188
  else if (value === "false") value = false;
171
189
  else if (value === "null") value = null;
172
190
  else if (/^\d+(\.\d+)?$/.test(value)) value = parseFloat(value);
@@ -109,6 +109,89 @@ export function ensureMarketplaceTables(db) {
109
109
  );
110
110
  }
111
111
 
112
+ /**
113
+ * Hydrate the in-memory _services/_invocations Maps from the DB. The CLI is
114
+ * one-shot: both start empty each process. Writes dual-write (Map + INSERT) but
115
+ * every read (getService/listServices/listInvocations/getInvocationStats/
116
+ * getMarketplaceStatsV2) and _mustGetService (record/status/invoke) is Map-only
117
+ * and nothing SELECTed the tables back — so a published service was invisible on
118
+ * the next invocation, and record/show/status threw "Service not found". Call
119
+ * after ensureMarketplaceTables(db).
120
+ *
121
+ * V2 timing fields (startedAt/completedAt) are not persisted → default null.
122
+ */
123
+ export function loadFromDb(db) {
124
+ if (!db) return 0;
125
+ ensureMarketplaceTables(db);
126
+ _services.clear();
127
+ _invocations.clear();
128
+
129
+ for (const r of db
130
+ .prepare(
131
+ `SELECT id, name, version, description, endpoint, pricing, status, owner, invocation_count, created_at, updated_at
132
+ FROM skill_services ORDER BY created_at ASC`,
133
+ )
134
+ .all()) {
135
+ // One corrupt pricing cell must not crash the whole service load.
136
+ let pricing = null;
137
+ try {
138
+ pricing = r.pricing ? JSON.parse(r.pricing) : null;
139
+ } catch {
140
+ pricing = null;
141
+ }
142
+ _services.set(r.id, {
143
+ id: r.id,
144
+ name: r.name,
145
+ version: r.version,
146
+ description: r.description || "",
147
+ endpoint: r.endpoint,
148
+ pricing,
149
+ status: r.status,
150
+ owner: r.owner,
151
+ invocationCount: Number(r.invocation_count) || 0,
152
+ createdAt: Number(r.created_at),
153
+ updatedAt: Number(r.updated_at),
154
+ _seq: ++_seq,
155
+ });
156
+ }
157
+
158
+ for (const r of db
159
+ .prepare(
160
+ `SELECT id, service_id, caller_id, input, output, status, duration_ms, error, created_at
161
+ FROM skill_invocations ORDER BY created_at ASC`,
162
+ )
163
+ .all()) {
164
+ let input = null;
165
+ let output = null;
166
+ try {
167
+ input = r.input == null ? null : JSON.parse(r.input);
168
+ } catch {
169
+ input = r.input;
170
+ }
171
+ try {
172
+ output = r.output == null ? null : JSON.parse(r.output);
173
+ } catch {
174
+ output = r.output;
175
+ }
176
+ _invocations.set(r.id, {
177
+ id: r.id,
178
+ serviceId: r.service_id,
179
+ callerId: r.caller_id,
180
+ input,
181
+ output,
182
+ status: r.status,
183
+ durationMs: r.duration_ms == null ? null : Number(r.duration_ms),
184
+ error: r.error,
185
+ createdAt: Number(r.created_at),
186
+ startedAt: null,
187
+ completedAt: null,
188
+ _seq: ++_seq,
189
+ });
190
+ }
191
+
192
+ return _services.size + _invocations.size;
193
+ }
194
+
112
195
  /* ── Catalogs ──────────────────────────────────────────────── */
113
196
 
114
197
  export function listServiceStatus() {
@@ -484,6 +484,94 @@ export function _resetState() {
484
484
  _maxActiveSlasPerOrg = DEFAULT_MAX_ACTIVE_SLAS_PER_ORG;
485
485
  }
486
486
 
487
+ /**
488
+ * Rehydrate the in-memory Maps from the persisted sla_* tables. The CLI runs
489
+ * each `cc sla` subcommand in a fresh node process, so _contracts/_metrics/
490
+ * _violations start empty every invocation. Every write dual-writes (Map +
491
+ * INSERT into sla_contracts/sla_metrics/sla_violations) but every read (listSLAs/
492
+ * getSLA/getSLAMetrics/checkViolations/listViolations/calculateCompensation/
493
+ * generateReport) is Map-only and nothing SELECTed the tables back — so `sla
494
+ * list` reported none, and `show`/`record`/`metrics`/`report` threw "SLA not
495
+ * found" for a contract that genuinely exists on disk. Call after
496
+ * ensureSlaTables(db).
497
+ */
498
+ export function loadFromDb(db) {
499
+ if (!db) return 0;
500
+ ensureSlaTables(db);
501
+ _contracts.clear();
502
+ _metrics.clear();
503
+ _violations.clear();
504
+
505
+ for (const r of db
506
+ .prepare(
507
+ `SELECT sla_id, org_id, tier, terms, monthly_fee, start_date, end_date, status, created_at, updated_at
508
+ FROM sla_contracts ORDER BY created_at ASC`,
509
+ )
510
+ .all()) {
511
+ // One corrupt terms cell must not sink the whole contract list.
512
+ let terms = {};
513
+ try {
514
+ terms = r.terms ? JSON.parse(r.terms) : {};
515
+ } catch {
516
+ terms = {};
517
+ }
518
+ _contracts.set(r.sla_id, {
519
+ slaId: r.sla_id,
520
+ orgId: r.org_id,
521
+ tier: r.tier,
522
+ terms,
523
+ monthlyFee: Number(r.monthly_fee) || 0,
524
+ startDate: Number(r.start_date),
525
+ endDate: Number(r.end_date),
526
+ status: r.status,
527
+ createdAt: Number(r.created_at),
528
+ updatedAt: Number(r.updated_at),
529
+ _seq: ++_seq,
530
+ });
531
+ }
532
+
533
+ for (const r of db
534
+ .prepare(
535
+ `SELECT metric_id, sla_id, term, value, recorded_at
536
+ FROM sla_metrics ORDER BY recorded_at ASC`,
537
+ )
538
+ .all()) {
539
+ if (!_metrics.has(r.sla_id)) _metrics.set(r.sla_id, []);
540
+ _metrics.get(r.sla_id).push({
541
+ metricId: r.metric_id,
542
+ slaId: r.sla_id,
543
+ term: r.term,
544
+ value: Number(r.value),
545
+ recordedAt: Number(r.recorded_at),
546
+ });
547
+ }
548
+
549
+ for (const r of db
550
+ .prepare(
551
+ `SELECT violation_id, sla_id, term, severity, expected_value, actual_value,
552
+ deviation_percent, compensation_amount, occurred_at, resolved_at
553
+ FROM sla_violations ORDER BY occurred_at ASC`,
554
+ )
555
+ .all()) {
556
+ _violations.set(r.violation_id, {
557
+ violationId: r.violation_id,
558
+ slaId: r.sla_id,
559
+ term: r.term,
560
+ severity: r.severity,
561
+ expectedValue: Number(r.expected_value),
562
+ actualValue: Number(r.actual_value),
563
+ deviationPercent:
564
+ r.deviation_percent == null ? null : Number(r.deviation_percent),
565
+ compensationAmount:
566
+ r.compensation_amount == null ? null : Number(r.compensation_amount),
567
+ occurredAt: Number(r.occurred_at),
568
+ resolvedAt: r.resolved_at == null ? null : Number(r.resolved_at),
569
+ });
570
+ }
571
+
572
+ return _contracts.size + _metrics.size + _violations.size;
573
+ }
574
+
487
575
  /* ═══════════════════════════════════════════════════════════════
488
576
  * V2 (Phase 61) — Frozen enums + contract/violation state
489
577
  * machines + active-per-org cap + auto-expire + stats-v2.
@@ -54,6 +54,80 @@ export function ensureSocialTables(db) {
54
54
  `);
55
55
  }
56
56
 
57
+ /**
58
+ * Hydrate the in-memory stores from the DB. The CLI is one-shot: every command
59
+ * runs in a fresh process, so the module-level Maps start empty. Write paths
60
+ * dual-write (Map + DB), but the read paths (listContacts/listFriends/listPosts/
61
+ * getChatMessages/getChatThreads/getSocialStats) read the Maps ONLY — so without
62
+ * this, a user's persisted contacts/friends/posts/messages are invisible on the
63
+ * next invocation. Mirrors social-graph.loadFromDb (the asymmetry tell: graph
64
+ * commands hydrate, social commands didn't). Call after ensureSocialTables(db).
65
+ */
66
+ export function loadFromDb(db) {
67
+ if (!db) return 0;
68
+ _contacts.clear();
69
+ _friends.clear();
70
+ _posts.clear();
71
+ _messages.clear();
72
+
73
+ for (const r of db
74
+ .prepare(
75
+ `SELECT id, name, did, email, notes, created_at FROM social_contacts`,
76
+ )
77
+ .all()) {
78
+ _contacts.set(r.id, {
79
+ id: r.id,
80
+ name: r.name,
81
+ did: r.did || null,
82
+ email: r.email || null,
83
+ notes: r.notes || "",
84
+ createdAt: r.created_at,
85
+ });
86
+ }
87
+
88
+ for (const r of db
89
+ .prepare(`SELECT id, contact_id, status, created_at FROM social_friends`)
90
+ .all()) {
91
+ // Keyed by contact_id to match addFriend's _friends.set(contactId, ...).
92
+ _friends.set(r.contact_id, {
93
+ id: r.id,
94
+ contactId: r.contact_id,
95
+ status: r.status,
96
+ createdAt: r.created_at,
97
+ });
98
+ }
99
+
100
+ for (const r of db
101
+ .prepare(`SELECT id, author, content, likes, created_at FROM social_posts`)
102
+ .all()) {
103
+ _posts.set(r.id, {
104
+ id: r.id,
105
+ author: r.author,
106
+ content: r.content,
107
+ likes: r.likes,
108
+ createdAt: r.created_at,
109
+ });
110
+ }
111
+
112
+ for (const r of db
113
+ .prepare(
114
+ `SELECT id, thread_id, sender, recipient, content, read, created_at FROM social_messages`,
115
+ )
116
+ .all()) {
117
+ _messages.set(r.id, {
118
+ id: r.id,
119
+ threadId: r.thread_id,
120
+ sender: r.sender,
121
+ recipient: r.recipient,
122
+ content: r.content,
123
+ read: !!r.read,
124
+ createdAt: r.created_at,
125
+ });
126
+ }
127
+
128
+ return _contacts.size + _friends.size + _posts.size + _messages.size;
129
+ }
130
+
57
131
  /* ── Contacts ──────────────────────────────────────────────── */
58
132
 
59
133
  export function addContact(db, name, did, email, notes) {
@@ -95,6 +95,71 @@ export function ensureStressTables(db) {
95
95
  `);
96
96
  }
97
97
 
98
+ /**
99
+ * Rehydrate _runs/_results from the persisted stress_test_runs/
100
+ * stress_test_results tables. The `cc` CLI runs every command in a fresh
101
+ * process, so without this the Maps start empty and a run recorded in a prior
102
+ * invocation is invisible (`cc stress list` shows "No stress tests recorded.";
103
+ * `cc stress show <id>` throws "Stress test not found"). Call after
104
+ * ensureStressTables(db).
105
+ */
106
+ export function loadFromDb(db) {
107
+ if (!db) return 0;
108
+ _runs.clear();
109
+ _results.clear();
110
+
111
+ const resultRows = db.prepare(`SELECT * FROM stress_test_results`).all();
112
+ for (const row of resultRows) {
113
+ let bottlenecks = [];
114
+ let capacityRecommendations = [];
115
+ try {
116
+ bottlenecks = row.bottlenecks ? JSON.parse(row.bottlenecks) : [];
117
+ } catch {
118
+ bottlenecks = [];
119
+ }
120
+ try {
121
+ capacityRecommendations = row.capacity_recommendations
122
+ ? JSON.parse(row.capacity_recommendations)
123
+ : [];
124
+ } catch {
125
+ capacityRecommendations = [];
126
+ }
127
+ _results.set(row.test_id, {
128
+ resultId: row.result_id,
129
+ testId: row.test_id,
130
+ tps: row.tps,
131
+ avgResponseTime: row.avg_response_time,
132
+ p50ResponseTime: row.p50_response_time,
133
+ p95ResponseTime: row.p95_response_time,
134
+ p99ResponseTime: row.p99_response_time,
135
+ errorRate: row.error_rate,
136
+ bottlenecks,
137
+ capacityRecommendations,
138
+ createdAt: row.created_at,
139
+ });
140
+ }
141
+
142
+ const runRows = db.prepare(`SELECT * FROM stress_test_runs`).all();
143
+ for (const row of runRows) {
144
+ _runs.set(row.test_id, {
145
+ testId: row.test_id,
146
+ loadLevel: row.load_level,
147
+ concurrency: row.concurrency,
148
+ requestsPerSecond: row.requests_per_second,
149
+ duration: row.duration,
150
+ status: row.status,
151
+ startedAt: row.started_at,
152
+ completedAt: row.completed_at ?? null,
153
+ // _seq is a per-process monotonic tiebreaker; started_at is the primary
154
+ // sort key. Reassign in load order — ties (same ms) are the only case it
155
+ // affects and are cosmetic for history ordering.
156
+ _seq: ++_seq,
157
+ });
158
+ }
159
+
160
+ return _runs.size + _results.size;
161
+ }
162
+
98
163
  /* ── Synthetic metrics ─────────────────────────────────────── */
99
164
 
100
165
  // Deterministic quasi-random: stable across runs for the same inputs. Tests
@@ -169,6 +169,81 @@ export function ensureTechLearningTables(db) {
169
169
  );
170
170
  }
171
171
 
172
+ /**
173
+ * Rehydrate _profiles/_practices from the persisted tech_stack_profiles/
174
+ * learned_practices tables. The `cc` CLI runs every command in a fresh process,
175
+ * so without this the Maps start empty and a profile/practice recorded in a
176
+ * prior invocation is invisible (`cc tech profile` returns null, `cc tech
177
+ * practices` shows nothing, `cc tech recommend` can't infer the latest stack).
178
+ * Call after ensureTechLearningTables(db). The profile's frameworks/databases/
179
+ * tools/libraries are not stored as columns — they are reconstructed from the
180
+ * classified tech_stack exactly as analyzeTechStack derives them.
181
+ */
182
+ export function loadFromDb(db) {
183
+ if (!db) return 0;
184
+ _profiles.clear();
185
+ _practices.clear();
186
+
187
+ const profileRows = db.prepare(`SELECT * FROM tech_stack_profiles`).all();
188
+ for (const row of profileRows) {
189
+ let classified = [];
190
+ let deps = [];
191
+ let languages = [];
192
+ try {
193
+ classified = row.tech_stack ? JSON.parse(row.tech_stack) : [];
194
+ } catch {
195
+ classified = [];
196
+ }
197
+ try {
198
+ deps = row.dependencies ? JSON.parse(row.dependencies) : [];
199
+ } catch {
200
+ deps = [];
201
+ }
202
+ try {
203
+ languages = row.languages ? JSON.parse(row.languages) : [];
204
+ } catch {
205
+ languages = [];
206
+ }
207
+ const byType = (t) =>
208
+ classified.filter((d) => d.type === t).map((d) => d.name);
209
+ _profiles.set(row.project_path, {
210
+ profileId: row.profile_id,
211
+ projectPath: row.project_path,
212
+ languages,
213
+ frameworks: byType(TECH_TYPES.FRAMEWORK),
214
+ databases: byType(TECH_TYPES.DATABASE),
215
+ tools: byType(TECH_TYPES.TOOL),
216
+ libraries: byType(TECH_TYPES.LIBRARY),
217
+ totalDependencies: deps.length,
218
+ analysisTimestamp: row.analysis_timestamp,
219
+ createdAt: row.created_at,
220
+ updatedAt: row.updated_at,
221
+ _seq: ++_seq,
222
+ });
223
+ }
224
+
225
+ const practiceRows = db.prepare(`SELECT * FROM learned_practices`).all();
226
+ for (const row of practiceRows) {
227
+ _practices.set(row.practice_id, {
228
+ practiceId: row.practice_id,
229
+ techType: row.tech_type,
230
+ techName: row.tech_name,
231
+ patternName: row.pattern_name,
232
+ level: row.level,
233
+ description: row.description ?? "",
234
+ codeExample: row.code_example ?? "",
235
+ usageCount: row.usage_count ?? 0,
236
+ score: row.score ?? 0,
237
+ source: row.source,
238
+ learnedAt: row.learned_at,
239
+ updatedAt: row.updated_at,
240
+ _seq: ++_seq,
241
+ });
242
+ }
243
+
244
+ return _profiles.size + _practices.size;
245
+ }
246
+
172
247
  /* ── Parsers for dependency manifests ──────────────────────── */
173
248
 
174
249
  function _readIfExists(filePath) {
@@ -20,6 +20,16 @@ function spanId() {
20
20
  return _seq.toString(16).padStart(16, "0");
21
21
  }
22
22
 
23
+ // One trace per recorder (a "run"). The OTLP/OTel spec treats an ALL-ZERO
24
+ // traceId as INVALID, so a strict collector would drop every span exported with
25
+ // `"0".repeat(32)` — defeating toOtlp()'s purpose. Derive a non-zero, monotonic
26
+ // (RNG-free, snapshot-replayable) 32-hex traceId per recorder instead.
27
+ let _traceSeq = 0;
28
+ function newTraceId() {
29
+ _traceSeq = (_traceSeq + 1) % Number.MAX_SAFE_INTEGER;
30
+ return _traceSeq.toString(16).padStart(32, "0"); // never all-zero (starts at 1)
31
+ }
32
+
23
33
  export class TelemetryRecorder {
24
34
  constructor({
25
35
  now = () => Date.now(),
@@ -27,6 +37,7 @@ export class TelemetryRecorder {
27
37
  } = {}) {
28
38
  this._now = typeof now === "function" ? now : () => now;
29
39
  this.serviceName = serviceName;
40
+ this.traceId = newTraceId(); // one trace per recorder (valid non-zero id)
30
41
  this._spans = []; // completed spans
31
42
  this._counters = new Map(); // name → { total, byAttr }
32
43
  this._failures = new Map(); // category → count
@@ -171,7 +182,7 @@ export class TelemetryRecorder {
171
182
  {
172
183
  scope: { name: "chainlesschain.cli" },
173
184
  spans: this._spans.map((s) => ({
174
- traceId: "0".repeat(32),
185
+ traceId: this.traceId,
175
186
  spanId: s.id,
176
187
  parentSpanId: s.parentId || "",
177
188
  name: s.name,