chainlesschain 0.162.175 → 0.162.177

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 (311) hide show
  1. package/package.json +10 -10
  2. package/src/assets/web-panel/assets/{AIOps-DherW0Rh.js → AIOps-DT-VPWuN.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-CDGfqt2Y.js → ActionButton-DyOreOVN.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-BYhkzdgD.js → Analytics-DslNsKux.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-cEKk1cpb.js → AppLayout-BNJJAYME.js} +5 -5
  6. package/src/assets/web-panel/assets/{Artifacts-_aXR3WWc.js → Artifacts-DoaAtEcY.js} +1 -1
  7. package/src/assets/web-panel/assets/{Audit-CYAf-gY7.js → Audit-DPG3WdJ9.js} +1 -1
  8. package/src/assets/web-panel/assets/{BackgroundAgents-D4Q20phR.js → BackgroundAgents-C_JO6R5G.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-Cq0Tyk58.js → Backup-Cv3BooyX.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-CPj_CdAv.js → BaseInput-D2uQXWu-.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-BQ-Qq0es.js → Chat-B4Vczyf3.js} +4 -4
  12. package/src/assets/web-panel/assets/ChatBubbleRenderer-DE6reP99.js +1 -0
  13. package/src/assets/web-panel/assets/{Checkbox-rke6l3yg.js → Checkbox-qTgk4VeP.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-DiacrIPq.js → Codegen-DlLWcIzj.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-Cx3BY-Up.js → Col-DNO73qp7.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-DfmWiQy8.js → Community-vRDNpc4j.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-DdQnpxy5.js → Compact-CEWtIXni.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-lzliOH_r.js → Compliance-KgYC9Fxi.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-CYx4Un5k.js → Cowork-zj5wvkpT.js} +2 -2
  20. package/src/assets/web-panel/assets/{Cron-BGDcPFlo.js → Cron-BLDoCozU.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-0_X5g2ri.js → Crosschain-BYnff4VY.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-C0PEf3Eu.js → DID-C75VFsVm.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-DULQjQ58.js → Dashboard-C4Gutni2.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-DGRHRbW6.js → Dropdown-B5dbO4Kx.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-ChX8XPwB.js → EmailListRenderer-BDipZtHJ.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-Dyq6IBNu.js → FamilyGuardDashboard-DmIzt8jj.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-DH1NfAL2.js → Federation-D9QOS-uW.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-BN1I_uNi.js → FormItemContext-B47HRwAm.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-Dq_2UYpe.js → GenericCardRenderer-3R4mXmgV.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-BAy1yvI2.js → Git-DrNXZf1C.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-Db6Q2iSy.js → Governance-BGd7JR98.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-0ub6yHcr.js → Inference-D-2he1ed.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-DtLetM36.js → KnowledgeGraph-C0sHIbK5.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-Bcoy7CUd.js → Logs-DiBQO-jL.js} +2 -2
  35. package/src/assets/web-panel/assets/{MarkdownRenderer-BfEMFAXf.js → MarkdownRenderer-DL_5eV2D.js} +1 -1
  36. package/src/assets/web-panel/assets/{Marketplace-tt2rzwRR.js → Marketplace-VR59OdrC.js} +1 -1
  37. package/src/assets/web-panel/assets/{McpTools-BhOgX-MU.js → McpTools-DrPzwSd3.js} +3 -3
  38. package/src/assets/web-panel/assets/{Memory-BJUxeWBL.js → Memory-CBgKALwQ.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileBridge-BwUY2G9w.js → MobileBridge-pQ9Tn-Mn.js} +1 -1
  40. package/src/assets/web-panel/assets/{MobileProjects-BLRfHhqi.js → MobileProjects-mASB6jyj.js} +1 -1
  41. package/src/assets/web-panel/assets/{Mtc-B2WMboOm.js → Mtc-DTMgE7HC.js} +2 -2
  42. package/src/assets/web-panel/assets/{MtcAudit-8pNEXO63.js → MtcAudit-CwTnCtiL.js} +2 -2
  43. package/src/assets/web-panel/assets/{Multisig-C1wm5a_1.js → Multisig-ngm6WU8f.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-C1QpKF7g.js → NLProgramming-4YO4Qww9.js} +1 -1
  45. package/src/assets/web-panel/assets/{Notes-CiQUcxFu.js → Notes-DP1k45mF.js} +3 -3
  46. package/src/assets/web-panel/assets/{NotificationSettings-BblDPJ_x.js → NotificationSettings-r2H8yPKb.js} +1 -1
  47. package/src/assets/web-panel/assets/{OrderTableRenderer-DRjYcPtb.js → OrderTableRenderer-CoM_Zw0J.js} +1 -1
  48. package/src/assets/web-panel/assets/{Organization-Dp3VKB0X.js → Organization-DrO7jRWS.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-Czx161m9.js → Overflow-Cnwu4i4t.js} +1 -1
  50. package/src/assets/web-panel/assets/{P2P-ClFi6wOs.js → P2P-zi-cDwA_.js} +2 -2
  51. package/src/assets/web-panel/assets/{PdhVaultBrowser-CRweW0lz.js → PdhVaultBrowser-DBEryDv7.js} +3 -3
  52. package/src/assets/web-panel/assets/{Permissions-BzcRoqTn.js → Permissions-lqXK2C3x.js} +4 -4
  53. package/src/assets/web-panel/assets/{PersonalDataHub-ChGTpNMd.js → PersonalDataHub-b63T3HJM.js} +2 -2
  54. package/src/assets/web-panel/assets/{Pipeline-BMOOpKWA.js → Pipeline-Kep5KAGW.js} +1 -1
  55. package/src/assets/web-panel/assets/{Privacy-D0AZHObH.js → Privacy-CHdvOAh1.js} +1 -1
  56. package/src/assets/web-panel/assets/{ProjectInit-yYFlZ6Ja.js → ProjectInit-BhKfdwe9.js} +2 -2
  57. package/src/assets/web-panel/assets/{ProjectSettings-DJNVuMQs.js → ProjectSettings-Yavk9K8A.js} +2 -2
  58. package/src/assets/web-panel/assets/{Projects-Br0rBWH1.js → Projects-CN8E_5Mq.js} +1 -1
  59. package/src/assets/web-panel/assets/Providers-Bfym6SQn.js +1 -0
  60. package/src/assets/web-panel/assets/{QrScannerModal-81NZOitV.js → QrScannerModal-CLSQcrlR.js} +1 -1
  61. package/src/assets/web-panel/assets/{QuickAsk-Dic2lCbJ.js → QuickAsk-VPa2WKQN.js} +1 -1
  62. package/src/assets/web-panel/assets/{Recommend-Dh9iwViE.js → Recommend-CGXR8jVU.js} +1 -1
  63. package/src/assets/web-panel/assets/{RemoteSession-Bq9VYEFy.js → RemoteSession-C_20YfMB.js} +2 -2
  64. package/src/assets/web-panel/assets/{Reputation-CxFZ-NbJ.js → Reputation-awZh68UV.js} +1 -1
  65. package/src/assets/web-panel/assets/{Row-BVSLcaX2.js → Row-Ctb4oiYN.js} +1 -1
  66. package/src/assets/web-panel/assets/{RssFeed-BbC-5DOH.js → RssFeed-D3sdjvUV.js} +3 -3
  67. package/src/assets/web-panel/assets/{Search-BfjZ1GCr.js → Search-C-zfA4kT.js} +1 -1
  68. package/src/assets/web-panel/assets/{Security-CVjhOV5r.js → Security-D9XlmHA3.js} +4 -4
  69. package/src/assets/web-panel/assets/{Services-D45u-Aqe.js → Services-C3UKnr41.js} +2 -2
  70. package/src/assets/web-panel/assets/{Skeleton-WkGoK4he.js → Skeleton-BQxagZfF.js} +1 -1
  71. package/src/assets/web-panel/assets/Skills-q6eb6KPZ.js +1 -0
  72. package/src/assets/web-panel/assets/{Sla-Bf4QTF3E.js → Sla-DveENvek.js} +1 -1
  73. package/src/assets/web-panel/assets/{SpeechSettings-DVpZdbMN.js → SpeechSettings-BFjXLNgF.js} +1 -1
  74. package/src/assets/web-panel/assets/{SyncSettings-DEEojoMS.js → SyncSettings-BpHgbaP9.js} +2 -2
  75. package/src/assets/web-panel/assets/Tasks-DvepRb8-.js +1 -0
  76. package/src/assets/web-panel/assets/{Templates-Bzl-9wY5.js → Templates-DEiaoyve.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tenant-0khxUOB8.js → Tenant-ITg774nY.js} +1 -1
  78. package/src/assets/web-panel/assets/{Terminal-DWGYhAYU.js → Terminal-D3ZBcvnb.js} +2 -2
  79. package/src/assets/web-panel/assets/{TimelineRenderer-B0Y4LONc.js → TimelineRenderer-BsLU6JjU.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tokens-DEE07SFh.js → Tokens-Cb5Pquc9.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trigger-BM7xvA5z.js → Trigger-Dwfy-m9N.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trust-Dv3ijvvZ.js → Trust-CnlSRGG0.js} +1 -1
  83. package/src/assets/web-panel/assets/{UkeySign-B1-enmMt.js → UkeySign-Y4TlvKVo.js} +1 -1
  84. package/src/assets/web-panel/assets/{VideoEditing-DYiIPByd.js → VideoEditing-BpKLtTTO.js} +1 -1
  85. package/src/assets/web-panel/assets/{Wallet-D-y374BQ.js → Wallet-LLBzIq8x.js} +4 -4
  86. package/src/assets/web-panel/assets/{WebAuthn-HBDjcUhi.js → WebAuthn-BeSRiusP.js} +4 -4
  87. package/src/assets/web-panel/assets/{WorkflowEditor-sKn4qTID.js → WorkflowEditor-BK_l1tXO.js} +1 -1
  88. package/src/assets/web-panel/assets/{chat-TVYhaBXj.js → chat-DYd-X7Wg.js} +1 -1
  89. package/src/assets/web-panel/assets/{colors-DMADxY9v.js → colors-C9uip71j.js} +1 -1
  90. package/src/assets/web-panel/assets/{compact-item-OftcHpO_.js → compact-item-JBrfjUP6.js} +1 -1
  91. package/src/assets/web-panel/assets/{createContext-DW1zVUSN.js → createContext-D03fbuiq.js} +1 -1
  92. package/src/assets/web-panel/assets/devWarning-B8LQ8leS.js +1 -0
  93. package/src/assets/web-panel/assets/{hasIn-CaUathNp.js → hasIn-DLQOR6l-.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-Cmdv6Dev.js → index-5YN7F5bO.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-iDmgT2Dg.js → index-6GuLRpBQ.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-77kgkUgY.js → index-B0X76LjX.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-CM8W07sc.js → index-B46YcgsV.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-C9JoaYSs.js → index-BNCdRmWf.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-CpDtN0dl.js → index-BYv-LWdy.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CZXYI5LU.js → index-Ba-Ps_AJ.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DWVZ3T0t.js → index-BcBZwlnG.js} +1 -1
  102. package/src/assets/web-panel/assets/{index--5UvwqH_.js → index-BdH9l8wl.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BBNg08cD.js → index-BfOs_bmg.js} +3 -3
  104. package/src/assets/web-panel/assets/index-Bh8BPtqR.js +1 -0
  105. package/src/assets/web-panel/assets/{index-s-EnkUCn.js → index-BnQgRjsm.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-Lr0MO-GU.js → index-BpYKLrUT.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-B-19mFhn.js → index-BuNFCZCx.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-CeCIYYG7.js → index-ByHO3SqZ.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-hXq7QRA_.js → index-C2zmOsyD.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-8YelceUU.js → index-CChQBM1d.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-B52Ztt8Q.js → index-CChaISMb.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-DKjqFpYa.js → index-CILVyK3b.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-DAfT3EMd.js → index-CL0ixCxk.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-sm1sGIxW.js → index-CS63r8h3.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-DHi634g9.js → index-CVZWiUE_.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-BEzLLVYd.js → index-Ce0Bf1YF.js} +1 -1
  117. package/src/assets/web-panel/assets/index-CeVrHLzZ.js +1 -0
  118. package/src/assets/web-panel/assets/{index-pSVCBsG4.js → index-Ck17i0OD.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-GUKz4Pv9.js → index-Cpn19c9k.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CKNdnJRo.js → index-CqWk1FLG.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-Bg-7FpaL.js → index-CwoDpKzW.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DYwwUKDg.js → index-D-1SqEpQ.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-DZdT8nio.js → index-D4UY5Z60.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-BvRw4Fna.js → index-D8KvuDz0.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-kdMl_0zL.js → index-DNMAAUVk.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CK-p7Hji.js → index-DYLZY4uh.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-DXcqvWBp.js → index-DaokIHt3.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-BFVbDpqg.js → index-Q7mmL6w4.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-BJ1PjRY3.js → index-SO6lgMg0.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-BSp1Ofvx.js → index-iahNhZwm.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-BupSWDcl.js → index-l08afIbV.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-D63QVAiJ.js → index-rIxxfdTN.js} +1 -1
  133. package/src/assets/web-panel/assets/{initDefaultProps-DdcKTlQR.js → initDefaultProps-CG9z1c6w.js} +1 -1
  134. package/src/assets/web-panel/assets/{motion-CL-hTBQj.js → motion-B1Ky7Zff.js} +1 -1
  135. package/src/assets/web-panel/assets/{move-qYSAkxNG.js → move-DME8X2P1.js} +1 -1
  136. package/src/assets/web-panel/assets/{mtc-parser-ZwRSZtRP.js → mtc-parser-cuJYSWB7.js} +1 -1
  137. package/src/assets/web-panel/assets/{omit-Bld-8ftI.js → omit-UI_EE0uZ.js} +1 -1
  138. package/src/assets/web-panel/assets/{pickAttrs-DGHs-a9Z.js → pickAttrs-BIoE_Z_V.js} +1 -1
  139. package/src/assets/web-panel/assets/{placementArrow-DRQPMyI5.js → placementArrow-B48-9HKN.js} +1 -1
  140. package/src/assets/web-panel/assets/{responsiveObserve-C5MJG_Yo.js → responsiveObserve-D7x_GDgD.js} +1 -1
  141. package/src/assets/web-panel/assets/{slide-VZ-fpZCD.js → slide-DjzC5_7m.js} +1 -1
  142. package/src/assets/web-panel/assets/{statusUtils-9ocfCyHk.js → statusUtils-C6BIymhh.js} +1 -1
  143. package/src/assets/web-panel/assets/{styleChecker-B6QAwAN5.js → styleChecker-B4dGrdD9.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFlexGapSupport-Bq1twor3.js → useFlexGapSupport-Bken4aNE.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFs-DKZq96tz.js → useFs-BMlqECqv.js} +1 -1
  146. package/src/assets/web-panel/assets/{usePersonalDataHub-D0RmRVXf.js → usePersonalDataHub-DLdrfmMa.js} +1 -1
  147. package/src/assets/web-panel/assets/{vnode-D6kEj_tt.js → vnode-CKJQmxa0.js} +1 -1
  148. package/src/assets/web-panel/assets/{zoom-2yfasoQf.js → zoom-CaZunuau.js} +1 -1
  149. package/src/assets/web-panel/index.html +1 -1
  150. package/src/auth/npm-auth.js +30 -5
  151. package/src/commands/agenda.js +83 -5
  152. package/src/commands/agent.js +42 -4
  153. package/src/commands/background-session.js +11 -4
  154. package/src/commands/batch.js +79 -27
  155. package/src/commands/changelog.js +15 -4
  156. package/src/commands/config.js +70 -5
  157. package/src/commands/context.js +36 -2
  158. package/src/commands/eval.js +21 -6
  159. package/src/commands/hook.js +2 -2
  160. package/src/commands/hub.js +19 -1
  161. package/src/commands/loop.js +9 -2
  162. package/src/commands/memory.js +21 -6
  163. package/src/commands/permissions.js +57 -1
  164. package/src/commands/plugin.js +2 -0
  165. package/src/commands/review.js +23 -11
  166. package/src/commands/routine.js +31 -8
  167. package/src/commands/session.js +11 -3
  168. package/src/commands/skill.js +2 -0
  169. package/src/commands/statusline.js +3 -3
  170. package/src/commands/team.js +20 -7
  171. package/src/commands/update.js +65 -10
  172. package/src/data/changelog.json +293 -51
  173. package/src/gateways/terminal/PtyManager.js +8 -1
  174. package/src/gateways/ws/message-dispatcher.js +3 -0
  175. package/src/gateways/ws/session-protocol.js +26 -0
  176. package/src/gateways/ws/ws-agent-handler.js +107 -69
  177. package/src/gateways/ws/ws-server.js +74 -2
  178. package/src/harness/background-task-manager.js +18 -6
  179. package/src/harness/background-task-worker.js +11 -18
  180. package/src/harness/jsonl-session-store.js +13 -6
  181. package/src/harness/mcp-client.js +195 -2
  182. package/src/harness/worktree-isolator.js +18 -21
  183. package/src/lib/__tests__/personal-data-hub-aichat-wizard.test.js +15 -0
  184. package/src/lib/agent-coordinator.js +4 -0
  185. package/src/lib/agent-core.js +5 -0
  186. package/src/lib/agent-ipc-bus.js +44 -5
  187. package/src/lib/agent-sandbox.js +16 -2
  188. package/src/lib/agent-schedule-store.js +55 -0
  189. package/src/lib/agent-team/team-worktree.js +28 -6
  190. package/src/lib/agent-tool-admission.js +104 -0
  191. package/src/lib/agent-worktree.js +20 -19
  192. package/src/lib/api-key-helper.js +10 -2
  193. package/src/lib/async-hook-supervisor.cjs +135 -15
  194. package/src/lib/async-hook-supervisor.js +47 -0
  195. package/src/lib/background-agent-supervisor.js +35 -12
  196. package/src/lib/background-task-manager.js +5 -1
  197. package/src/lib/changelog.js +76 -11
  198. package/src/lib/channels/channel-manager.js +6 -0
  199. package/src/lib/channels/telegram-channel.js +11 -1
  200. package/src/lib/channels/webhook-channel.js +15 -3
  201. package/src/lib/checkpoint-store.js +10 -2
  202. package/src/lib/chrome-connector.js +6 -2
  203. package/src/lib/claude-code-bridge.js +24 -8
  204. package/src/lib/cli-anything-bridge.js +82 -25
  205. package/src/lib/cloud/bundle.js +12 -2
  206. package/src/lib/code-review.js +32 -8
  207. package/src/lib/computer-use/control-backend.js +18 -3
  208. package/src/lib/context-breakdown.js +46 -0
  209. package/src/lib/context-source-ledger.js +43 -0
  210. package/src/lib/diff-review-follow-up.js +154 -0
  211. package/src/lib/doctor-checkup.js +18 -6
  212. package/src/lib/downloader.js +17 -3
  213. package/src/lib/ensure-utf8.js +11 -3
  214. package/src/lib/eval/tasks.js +25 -31
  215. package/src/lib/event-runtime-producer.js +58 -0
  216. package/src/lib/event-runtime-store.js +354 -0
  217. package/src/lib/event-runtime-worker.js +109 -0
  218. package/src/lib/execution-backend.js +72 -21
  219. package/src/lib/git-integration.js +19 -4
  220. package/src/lib/hook-manager.js +6 -15
  221. package/src/lib/hook-runner.cjs +88 -8
  222. package/src/lib/hook-runner.js +55 -0
  223. package/src/lib/hooks-v2-producers.js +15 -0
  224. package/src/lib/hooks-v2-runtime.js +70 -21
  225. package/src/lib/host-adb-bridge.js +129 -24
  226. package/src/lib/ide-context.js +128 -1
  227. package/src/lib/interaction-adapter.js +39 -0
  228. package/src/lib/json-schema-validate.js +190 -36
  229. package/src/lib/lan-pairing-preflight.js +13 -2
  230. package/src/lib/lsp/__tests__/benchmark.test.js +61 -0
  231. package/src/lib/lsp/__tests__/lsp-client.test.js +6 -1
  232. package/src/lib/lsp/__tests__/lsp-server-registry.test.js +18 -0
  233. package/src/lib/lsp/benchmark.js +20 -4
  234. package/src/lib/lsp/lsp-client.js +22 -3
  235. package/src/lib/lsp/lsp-manager.js +4 -0
  236. package/src/lib/lsp/lsp-server-registry.js +11 -2
  237. package/src/lib/mcp-oauth.js +8 -2
  238. package/src/lib/npm-invocation.js +29 -0
  239. package/src/lib/orchestrator.js +8 -2
  240. package/src/lib/packer/pack-update-applier.js +14 -2
  241. package/src/lib/packer/pkg-runner.js +13 -2
  242. package/src/lib/packer/precheck.js +33 -16
  243. package/src/lib/packer/smoke-runner.js +18 -5
  244. package/src/lib/packer/web-panel-builder.js +16 -2
  245. package/src/lib/paths.js +1 -1
  246. package/src/lib/permission-rules.cjs +5 -1
  247. package/src/lib/personal-data-hub-aichat-wizard.js +22 -6
  248. package/src/lib/personal-data-hub-wiring.js +27 -3
  249. package/src/lib/plan-mode.js +204 -11
  250. package/src/lib/plugin-monitor-supervisor.js +48 -6
  251. package/src/lib/plugin-runtime/bin.js +45 -0
  252. package/src/lib/plugin-runtime/hooks.js +14 -1
  253. package/src/lib/plugin-runtime/install.js +11 -3
  254. package/src/lib/plugin-runtime/lsp.js +3 -0
  255. package/src/lib/plugin-runtime/mcp.js +8 -1
  256. package/src/lib/plugin-runtime/monitors.js +4 -0
  257. package/src/lib/plugin-runtime/plugin-options.js +74 -7
  258. package/src/lib/plugin-runtime/signature.js +45 -0
  259. package/src/lib/pr-create.js +21 -8
  260. package/src/lib/pr-link-ledger.js +15 -3
  261. package/src/lib/process-execution-broker/credential-agent.js +23 -3
  262. package/src/lib/process-execution-broker/index.js +315 -38
  263. package/src/lib/process-execution-broker/patch-child-process.js +2 -3
  264. package/src/lib/process-manager.js +18 -3
  265. package/src/lib/publish-workspace.js +14 -6
  266. package/src/lib/repl-bang-memorize.js +10 -2
  267. package/src/lib/repl-goal.js +19 -2
  268. package/src/lib/secret-store.js +159 -0
  269. package/src/lib/service-manager.js +64 -29
  270. package/src/lib/settings-hook-events.cjs +74 -9
  271. package/src/lib/settings-hook-events.js +20 -0
  272. package/src/lib/settings-hooks.cjs +4 -0
  273. package/src/lib/side-effect-ledger.js +22 -0
  274. package/src/lib/skill-packs/generator.js +18 -9
  275. package/src/lib/skill-process-broker.js +71 -0
  276. package/src/lib/slash-commands.js +10 -2
  277. package/src/lib/status-line.cjs +28 -7
  278. package/src/lib/status-line.js +33 -0
  279. package/src/lib/sub-agent-context.js +5 -0
  280. package/src/lib/sub-agent-profiles.js +4 -0
  281. package/src/lib/turn-context.js +14 -8
  282. package/src/lib/unattended-action-policy.js +83 -0
  283. package/src/lib/update-notice.js +6 -2
  284. package/src/lib/with-file-lock.js +7 -0
  285. package/src/lib/ws-server.js +1 -0
  286. package/src/repl/agent-repl.js +60 -23
  287. package/src/repl/clipboard-copy.js +8 -2
  288. package/src/repl/pr-comments.js +30 -7
  289. package/src/runtime/agent-core.js +554 -118
  290. package/src/runtime/agent-runtime.js +1 -0
  291. package/src/runtime/coding-agent-contract-shared.cjs +52 -0
  292. package/src/runtime/coding-agent-policy.cjs +20 -0
  293. package/src/runtime/diagnostics.js +73 -8
  294. package/src/runtime/headless-runner.js +88 -10
  295. package/src/runtime/headless-stream.js +343 -21
  296. package/src/runtime/mcp-config.js +16 -1
  297. package/src/runtime/session-slash-commands.js +506 -0
  298. package/src/skills/video-editing/extractors/audio-extractor.js +13 -5
  299. package/src/skills/video-editing/extractors/video-extractor.js +13 -3
  300. package/src/skills/video-editing/media-process.js +20 -0
  301. package/src/skills/video-editing/render/audio-mix.js +13 -3
  302. package/src/skills/video-editing/render/ffmpeg-concat.js +7 -2
  303. package/src/skills/video-editing/render/ffmpeg-extract.js +7 -2
  304. package/src/workers/background-agent-worker.js +6 -2
  305. package/src/assets/web-panel/assets/ChatBubbleRenderer-Ci97vNTs.js +0 -1
  306. package/src/assets/web-panel/assets/Providers-zZRhNtSu.js +0 -1
  307. package/src/assets/web-panel/assets/Skills-D_jvQZcj.js +0 -1
  308. package/src/assets/web-panel/assets/Tasks-DFwxpLIk.js +0 -1
  309. package/src/assets/web-panel/assets/devWarning-CLOk6rdE.js +0 -1
  310. package/src/assets/web-panel/assets/index-CSgUfMTM.js +0 -1
  311. package/src/assets/web-panel/assets/index-DliSZvAP.js +0 -1
@@ -96,6 +96,27 @@ async function ensureSessionHandler(server, ws, session) {
96
96
  envelopeBus: server.envelopeBus || null,
97
97
  });
98
98
 
99
+ // Route MCP elicitation through the authenticated WS question channel. The
100
+ // MCP client may be shared by the runtime, so this is deliberately only a
101
+ // transport hook; the MCP request/answer ids remain inside the pending
102
+ // interaction entry and unknown answers are ignored by the adapter.
103
+ if (
104
+ session.mcpClient &&
105
+ typeof session.mcpClient.setElicitationHandler === "function"
106
+ ) {
107
+ session.mcpClient.setElicitationHandler(
108
+ async (request) => {
109
+ const answer = await session.interaction.askElicitation(request);
110
+ if (answer == null) return { action: "cancel" };
111
+ if (typeof answer === "object") {
112
+ return { action: "accept", content: answer };
113
+ }
114
+ return { action: "accept", content: { value: answer } };
115
+ },
116
+ { sessionId: session.id, timeoutMs: 180000 },
117
+ );
118
+ }
119
+
99
120
  let handler;
100
121
  if (session.type === "chat") {
101
122
  const { WSChatHandler } = await import("../../lib/ws-chat-handler.js");
@@ -444,6 +465,11 @@ export function handleSessionList(server, id, ws) {
444
465
  export function handleSessionClose(server, id, ws, message) {
445
466
  const { sessionId } = message;
446
467
 
468
+ const closingSession = server.sessionManager?.getSession?.(sessionId);
469
+ if (closingSession?.mcpClient?.clearElicitationHandler) {
470
+ closingSession.mcpClient.clearElicitationHandler(sessionId);
471
+ }
472
+
447
473
  const handler = server.sessionHandlers.get(sessionId);
448
474
  if (handler && handler.destroy) {
449
475
  handler.destroy();
@@ -13,6 +13,7 @@
13
13
 
14
14
  import { agentLoop, formatToolArgs } from "../../runtime/agent-core.js";
15
15
  import { classifyToolSideEffect } from "../../lib/side-effect-ledger.js";
16
+ import { DiffReviewFollowUpTracker } from "../../lib/diff-review-follow-up.js";
16
17
  import {
17
18
  loadSideEffectLedger,
18
19
  persistSideEffectLedger,
@@ -88,6 +89,8 @@ export class WSAgentHandler {
88
89
  const abortController = new AbortController();
89
90
  this._abortController = abortController;
90
91
  this._activeRequestId = requestId || null;
92
+ let sideEffectLedger = null;
93
+ let diffReviewFollowUps = null;
91
94
 
92
95
  try {
93
96
  const { session } = this;
@@ -159,88 +162,123 @@ export class WSAgentHandler {
159
162
  // persisted BEFORE it settles) and commit/fail on its result, so a bridge
160
163
  // worker killed mid-flight is surfaced for verification on resume (see
161
164
  // handleSessionResume) instead of being blindly replayed.
162
- const sideEffectLedger = loadSideEffectLedger(session.id);
165
+ sideEffectLedger = loadSideEffectLedger(session.id);
166
+ diffReviewFollowUps = new DiffReviewFollowUpTracker(sideEffectLedger);
163
167
  let currentSideEffectOpId = null;
164
168
 
165
- for await (const event of agentLoop(session.messages, loopOptions)) {
166
- switch (event.type) {
167
- case "slot-filling":
168
- this.interaction.emit("slot-filling", {
169
- requestId,
170
- slot: event.slot,
171
- question: event.question,
172
- });
173
- break;
174
-
175
- case "tool-executing":
176
- this.interaction.emit("tool-executing", {
177
- requestId,
178
- tool: event.tool,
179
- args: event.args,
180
- display: formatToolArgs(event.tool, event.args),
181
- });
182
- currentSideEffectOpId = null;
183
- {
184
- const se = classifyToolSideEffect(event.tool, event.args);
185
- if (se) {
186
- const opId = `ws:${session.id}:${Date.now()}:${this._sideEffectSeq++}`;
187
- currentSideEffectOpId = opId;
188
- sideEffectLedger
189
- .prepare(opId, {
190
- kind: se.kind,
191
- key: se.key,
192
- meta: {
193
- tool: event.tool,
194
- idempotencyKey: operationIdempotencyKey({
169
+ const runAgentTurn = async () => {
170
+ for await (const event of agentLoop(session.messages, loopOptions)) {
171
+ switch (event.type) {
172
+ case "slot-filling":
173
+ this.interaction.emit("slot-filling", {
174
+ requestId,
175
+ slot: event.slot,
176
+ question: event.question,
177
+ });
178
+ break;
179
+
180
+ case "tool-executing":
181
+ this.interaction.emit("tool-executing", {
182
+ requestId,
183
+ tool: event.tool,
184
+ args: event.args,
185
+ display: formatToolArgs(event.tool, event.args),
186
+ });
187
+ currentSideEffectOpId = null;
188
+ {
189
+ const se = classifyToolSideEffect(event.tool, event.args);
190
+ if (se) {
191
+ const opId = `ws:${session.id}:${Date.now()}:${this._sideEffectSeq++}`;
192
+ currentSideEffectOpId = opId;
193
+ sideEffectLedger
194
+ .prepare(opId, {
195
+ kind: se.kind,
196
+ key: se.key,
197
+ meta: {
195
198
  tool: event.tool,
196
- args: event.args,
197
- }),
198
- },
199
- })
200
- .start(opId);
199
+ idempotencyKey: operationIdempotencyKey({
200
+ tool: event.tool,
201
+ args: event.args,
202
+ }),
203
+ },
204
+ })
205
+ .start(opId);
206
+ persistSideEffectLedger(session.id, sideEffectLedger);
207
+ }
208
+ }
209
+ break;
210
+
211
+ case "tool-result":
212
+ this.interaction.emit("tool-result", {
213
+ requestId,
214
+ tool: event.tool,
215
+ result: event.result,
216
+ error: event.error,
217
+ });
218
+ if (currentSideEffectOpId) {
219
+ const err = event.error || event.result?.error || null;
220
+ if (event.result?._diffReviewAudit) {
221
+ diffReviewFollowUps.observe(
222
+ sideEffectLedger,
223
+ currentSideEffectOpId,
224
+ event.result._diffReviewAudit,
225
+ );
226
+ }
227
+ if (err)
228
+ sideEffectLedger.fail(
229
+ currentSideEffectOpId,
230
+ String(err).slice(0, 200),
231
+ );
232
+ else sideEffectLedger.commit(currentSideEffectOpId);
201
233
  persistSideEffectLedger(session.id, sideEffectLedger);
234
+ currentSideEffectOpId = null;
202
235
  }
203
- }
204
- break;
205
-
206
- case "tool-result":
207
- this.interaction.emit("tool-result", {
208
- requestId,
209
- tool: event.tool,
210
- result: event.result,
211
- error: event.error,
212
- });
213
- if (currentSideEffectOpId) {
214
- const err = event.error || event.result?.error || null;
215
- if (err)
216
- sideEffectLedger.fail(
217
- currentSideEffectOpId,
218
- String(err).slice(0, 200),
219
- );
220
- else sideEffectLedger.commit(currentSideEffectOpId);
221
- persistSideEffectLedger(session.id, sideEffectLedger);
222
- currentSideEffectOpId = null;
223
- }
224
- break;
225
-
226
- case "response-complete":
227
- if (event.content) {
228
- session.messages.push({
229
- role: "assistant",
236
+ break;
237
+
238
+ case "response-complete":
239
+ if (event.content) {
240
+ session.messages.push({
241
+ role: "assistant",
242
+ content: event.content,
243
+ });
244
+ }
245
+ this.interaction.emit("response-complete", {
246
+ requestId,
230
247
  content: event.content,
231
248
  });
232
- }
233
- this.interaction.emit("response-complete", {
234
- requestId,
235
- content: event.content,
236
- });
237
- break;
249
+ break;
250
+ }
238
251
  }
252
+ };
253
+
254
+ if (session.mcpClient?.withElicitationContext) {
255
+ await session.mcpClient.withElicitationContext(
256
+ session.id,
257
+ runAgentTurn,
258
+ );
259
+ } else {
260
+ await runAgentTurn();
261
+ }
262
+ if (
263
+ diffReviewFollowUps.complete(sideEffectLedger, {
264
+ status: "completed-without-reproposal",
265
+ }).length > 0
266
+ ) {
267
+ persistSideEffectLedger(session.id, sideEffectLedger);
239
268
  }
240
269
 
241
270
  // Update last activity
242
271
  session.lastActivity = new Date().toISOString();
243
272
  } catch (err) {
273
+ if (
274
+ sideEffectLedger &&
275
+ diffReviewFollowUps?.complete(sideEffectLedger, {
276
+ status: "interrupted",
277
+ reason: isAbortError(err) ? "aborted" : err.message,
278
+ }).length > 0
279
+ ) {
280
+ persistSideEffectLedger(this.session.id, sideEffectLedger);
281
+ }
244
282
  if (isAbortError(err) || abortController.signal.aborted) {
245
283
  return;
246
284
  }
@@ -11,7 +11,6 @@
11
11
  */
12
12
 
13
13
  import { EventEmitter } from "node:events";
14
- import { spawn } from "node:child_process";
15
14
  import { createHash, timingSafeEqual } from "node:crypto";
16
15
  import { fileURLToPath } from "node:url";
17
16
  import { dirname, join } from "node:path";
@@ -113,6 +112,11 @@ import {
113
112
  handleArtifactRemove,
114
113
  handleArtifactShow,
115
114
  } from "./artifact-protocol.js";
115
+ import { executionBroker } from "../../lib/process-execution-broker/index.js";
116
+
117
+ export const _deps = {
118
+ spawn: (...args) => executionBroker.spawn(...args),
119
+ };
116
120
 
117
121
  const __filename = fileURLToPath(import.meta.url);
118
122
  const __dirname = dirname(__filename);
@@ -216,6 +220,7 @@ export class ChainlessChainWSServer extends EventEmitter {
216
220
  * @param {string} [options.token] - If set, clients must authenticate first
217
221
  * @param {number} [options.maxConnections=10]
218
222
  * @param {number} [options.timeout=30000] - Command execution timeout (ms)
223
+ * @param {Function} [options.spawn] - Process seam for tests
219
224
  */
220
225
  constructor(options = {}) {
221
226
  super();
@@ -240,6 +245,7 @@ export class ChainlessChainWSServer extends EventEmitter {
240
245
  // grace window so it can't hold a maxConnections slot forever (see
241
246
  // AUTH_TIMEOUT_MS). `??` so an explicit 0 (disable) is honoured.
242
247
  this.authTimeoutMs = options.authTimeoutMs ?? AUTH_TIMEOUT_MS;
248
+ this._spawnProcess = options.spawn || _deps.spawn;
243
249
 
244
250
  /** Optional Phase-5 envelope bus for fan-out to hosted HTTP SSE. */
245
251
  this.envelopeBus = options.envelopeBus || null;
@@ -255,6 +261,7 @@ export class ChainlessChainWSServer extends EventEmitter {
255
261
 
256
262
  /** Session manager for stateful agent/chat sessions */
257
263
  this.sessionManager = options.sessionManager || null;
264
+ this.projectRoot = options.projectRoot || process.cwd();
258
265
 
259
266
  /** Session handlers: sessionId → WSAgentHandler | WSChatHandler */
260
267
  this.sessionHandlers = new Map();
@@ -530,6 +537,67 @@ export class ChainlessChainWSServer extends EventEmitter {
530
537
  return this._dispatcher.dispatch(clientId, ws, message);
531
538
  }
532
539
 
540
+ /** Read the same .claude settings rules used by the Agent Core. */
541
+ async _handlePermissionRulesGet(id, ws) {
542
+ try {
543
+ const { loadSettings } = await import("../../lib/settings-loader.cjs");
544
+ const loaded = loadSettings({ cwd: this.projectRoot });
545
+ this._send(ws, {
546
+ id,
547
+ type: "permission-rules",
548
+ rules: loaded.rules,
549
+ sources: loaded.sources,
550
+ files: loaded.files,
551
+ managed: loaded.managed || null,
552
+ });
553
+ } catch (error) {
554
+ this._send(ws, {
555
+ id,
556
+ type: "error",
557
+ code: "PERMISSION_RULES_READ_FAILED",
558
+ message: error.message,
559
+ });
560
+ }
561
+ }
562
+
563
+ /** Persist one rule through settings-loader; managed policy remains authoritative. */
564
+ async _handlePermissionRulesSet(id, ws, message) {
565
+ try {
566
+ const decision = String(message.decision || "").toLowerCase();
567
+ if (!["allow", "ask", "deny"].includes(decision)) {
568
+ throw new Error("decision must be allow, ask, or deny");
569
+ }
570
+ const rulesMod = await import("../../lib/permission-rules.cjs");
571
+ const mod = rulesMod.default || rulesMod;
572
+ if (!mod.parseRule(message.rule)) throw new Error("invalid permission rule");
573
+ const { addRule } = await import("../../lib/settings-loader.cjs");
574
+ const scope = ["project", "local", "user"].includes(message.scope)
575
+ ? message.scope
576
+ : "project";
577
+ const result = addRule({
578
+ cwd: this.projectRoot,
579
+ kind: decision,
580
+ rule: message.rule,
581
+ scope,
582
+ });
583
+ this._send(ws, {
584
+ id,
585
+ type: "permission-rule-updated",
586
+ ...result,
587
+ decision,
588
+ rule: message.rule,
589
+ scope,
590
+ });
591
+ } catch (error) {
592
+ this._send(ws, {
593
+ id,
594
+ type: "error",
595
+ code: "PERMISSION_RULES_WRITE_FAILED",
596
+ message: error.message,
597
+ });
598
+ }
599
+ }
600
+
533
601
  /**
534
602
  * Handle an orchestrate message — runs ChainlessChain orchestration with
535
603
  * real-time progress pushed back over this WebSocket connection.
@@ -854,7 +922,7 @@ export class ChainlessChainWSServer extends EventEmitter {
854
922
  return;
855
923
  }
856
924
 
857
- const child = spawn(process.execPath, [BIN_PATH, ...args], {
925
+ const child = this._spawnProcess(process.execPath, [BIN_PATH, ...args], {
858
926
  env: {
859
927
  ...process.env,
860
928
  FORCE_COLOR: "0",
@@ -870,6 +938,10 @@ export class ChainlessChainWSServer extends EventEmitter {
870
938
  },
871
939
  stdio: ["pipe", "pipe", "pipe"],
872
940
  windowsHide: true,
941
+ origin: "gateway:ws-command",
942
+ policy: "allow",
943
+ scope: "gateway",
944
+ shell: false,
873
945
  });
874
946
 
875
947
  this.processes.set(id, child);
@@ -1,19 +1,23 @@
1
1
  /**
2
2
  * Background Task Manager - daemon task queue with completion notifications.
3
3
  *
4
- * Tasks run in child_process.fork() for isolation.
4
+ * Tasks run in a brokered Node child with an IPC channel for isolation.
5
5
  * Queue persisted to .chainlesschain/tasks/queue.jsonl.
6
6
  * Completion notifications delivered to REPL callback.
7
7
  *
8
8
  * Feature-flag gated: BACKGROUND_TASKS
9
9
  */
10
10
 
11
- import { fork } from "node:child_process";
12
11
  import { existsSync, mkdirSync, appendFileSync, readFileSync } from "node:fs";
13
12
  import { join } from "node:path";
14
13
  import { createHash } from "node:crypto";
15
14
  import { EventEmitter } from "node:events";
16
15
  import { getHomeDir } from "../lib/paths.js";
16
+ import executionBroker from "../lib/process-execution-broker/index.js";
17
+
18
+ export const _deps = {
19
+ spawn: executionBroker.spawn.bind(executionBroker),
20
+ };
17
21
 
18
22
  function getTasksDir() {
19
23
  const dir = join(getHomeDir(), "tasks");
@@ -114,13 +118,21 @@ export class BackgroundTaskManager extends EventEmitter {
114
118
  task.recoverySourceStatus = null;
115
119
  this._recordHistory(task, "started", { status: task.status });
116
120
 
117
- const child = fork(
118
- join(import.meta.dirname || ".", "background-task-worker.js"),
119
- [task.command, task.cwd, task.type],
121
+ const workerPath = join(
122
+ import.meta.dirname || ".",
123
+ "background-task-worker.js",
124
+ );
125
+ const child = _deps.spawn(
126
+ process.execPath,
127
+ [...process.execArgv, workerPath, task.command, task.cwd, task.type],
120
128
  {
121
129
  cwd: task.cwd,
122
- silent: true,
130
+ stdio: ["pipe", "pipe", "pipe", "ipc"],
123
131
  env: { ...process.env, CC_TASK_ID: taskId },
132
+ origin: "background-task:worker",
133
+ policy: "allow",
134
+ scope: "background-task",
135
+ shell: false,
124
136
  },
125
137
  );
126
138
 
@@ -5,7 +5,7 @@
5
5
  * Sends messages to parent: { type: "heartbeat"|"result"|"error", ... }
6
6
  */
7
7
 
8
- import { execSync } from "node:child_process";
8
+ import executionBroker from "../lib/process-execution-broker/index.js";
9
9
 
10
10
  const [command, cwd, type] = process.argv.slice(2);
11
11
 
@@ -14,23 +14,16 @@ const heartbeat = setInterval(() => {
14
14
  }, 5000);
15
15
 
16
16
  try {
17
- let result;
18
-
19
- if (type === "shell") {
20
- result = execSync(command, {
21
- cwd: cwd || process.cwd(),
22
- encoding: "utf-8",
23
- timeout: 300000,
24
- maxBuffer: 10 * 1024 * 1024,
25
- });
26
- } else {
27
- result = execSync(command, {
28
- cwd: cwd || process.cwd(),
29
- encoding: "utf-8",
30
- timeout: 300000,
31
- maxBuffer: 10 * 1024 * 1024,
32
- });
33
- }
17
+ const result = executionBroker.execSync(command, {
18
+ cwd: cwd || process.cwd(),
19
+ encoding: "utf-8",
20
+ timeout: 300000,
21
+ maxBuffer: 10 * 1024 * 1024,
22
+ origin: `background-task:command:${type || "unknown"}`,
23
+ policy: "allow",
24
+ scope: "background-task",
25
+ shell: true,
26
+ });
34
27
 
35
28
  if (process.send) {
36
29
  process.send({ type: "result", data: result || "Done" });
@@ -20,6 +20,7 @@ import {
20
20
  verifyTranscriptText,
21
21
  TRANSCRIPT_CHAIN_STATUS,
22
22
  } from "./transcript-integrity.js";
23
+ import { withFileLock } from "../lib/with-file-lock.js";
23
24
 
24
25
  function getSessionsDir() {
25
26
  const dir = join(getHomeDir(), "sessions");
@@ -82,12 +83,18 @@ function _resolveChainTail(sessionId, filePath) {
82
83
 
83
84
  export function appendEvent(sessionId, type, data) {
84
85
  const filePath = sessionPath(sessionId);
85
- const prevHash = _resolveChainTail(sessionId, filePath);
86
- const core = { type, timestamp: Date.now(), data };
87
- const hash = computeEventHash(prevHash, core);
88
- const line = JSON.stringify({ ...core, prevHash, hash }) + "\n";
89
- appendFileSync(filePath, line, "utf-8");
90
- _chainTailCache.set(sessionId, hash);
86
+ withFileLock(
87
+ filePath,
88
+ () => {
89
+ const prevHash = _resolveChainTail(sessionId, filePath);
90
+ const core = { type, timestamp: Date.now(), data };
91
+ const hash = computeEventHash(prevHash, core);
92
+ const line = JSON.stringify({ ...core, prevHash, hash }) + "\n";
93
+ appendFileSync(filePath, line, "utf-8");
94
+ _chainTailCache.set(sessionId, hash);
95
+ },
96
+ { failIfUnavailable: true },
97
+ );
91
98
  }
92
99
 
93
100
  /**