chainlesschain 0.165.4 → 0.165.6

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 (214) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/.build-hash +1 -1
  3. package/src/assets/web-panel/assets/{AIOps-C__nnraW.js → AIOps-vfoDb6HZ.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-CsKWHEZ-.js → ActionButton-Cm5f7p93.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-BhIjfjWO.js → Analytics-yRuvgWxa.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-BjuXFzWZ.js → AppLayout-BROsC4h1.js} +4 -4
  7. package/src/assets/web-panel/assets/{Artifacts-k6whDkZJ.js → Artifacts-CimHApb1.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-C4FBMYRh.js → Audit-DI8kr8zI.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-C_vRrSXk.js → BackgroundAgents-DSLzKy-n.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-CngFZeVp.js → Backup-DkH_n2r1.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-B_H9EBRm.js → BaseInput-CKSrUoRA.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-DLEC5kt7.js → Chat-ClwfMXUS.js} +3 -3
  13. package/src/assets/web-panel/assets/ChatBubbleRenderer-CjMaqfL7.js +1 -0
  14. package/src/assets/web-panel/assets/{Checkbox-m3ClR4xh.js → Checkbox-BYTehcQG.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-CmLSFrgp.js → Codegen-B8AMcp6J.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-DFGQteHN.js → Col-BNSogPo3.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-EUUVORHE.js → Community-JxPvGb8O.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-2PSg0Yr7.js → Compact-DF7bFAgE.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-CcKur7gB.js → Compliance-Bvhqnwrq.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-DK_Fezfa.js → Cowork-BDS0CJvM.js} +3 -3
  21. package/src/assets/web-panel/assets/{Cron-Dbw89xl7.js → Cron-DqvRfxoQ.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-CH66h_Ec.js → Crosschain-CDcIvnqS.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-D1igRb17.js → DID-D7jaUxU3.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-DVAsrobk.js → Dashboard-B5A18wEV.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-Dl7W8AQs.js → Dropdown-_6IVkGag.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-D5tpaEQC.js → EmailListRenderer-C9PeiKCG.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-O_VQf8gq.js → FamilyGuardDashboard-DXjuEHrX.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-BTVcgS9n.js → Federation-B4IAR9zv.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-BRnkJAIz.js → FormItemContext-CxQeSNx1.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-8OWSCkDj.js → GenericCardRenderer-B8GS-Y3N.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-WXLYTQj2.js → Git-BS8SouUX.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-BezaUhtc.js → Governance-Dq9aYb5Q.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-CuRay3Gu.js → Inference-BrCEe9AJ.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-DfWLDW1m.js → KnowledgeGraph-DybOpiY2.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-C55y2pPY.js → Logs-DBpzbRfx.js} +2 -2
  36. package/src/assets/web-panel/assets/MarkdownRenderer-CFyt8iUd.js +1 -0
  37. package/src/assets/web-panel/assets/{Marketplace-Dk08Uycg.js → Marketplace-Cc7CCSCu.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-C11fSB5V.js → McpTools-DFaIhOfu.js} +3 -3
  39. package/src/assets/web-panel/assets/{Memory-mr0eZc97.js → Memory-KCqlp9ol.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-C0iCSRbb.js → MobileBridge-Bys84ySN.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-CY-xMG8Z.js → MobileProjects-B-6qU-je.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-Bplqc_Wc.js → Mtc-BgY-fvCq.js} +4 -4
  43. package/src/assets/web-panel/assets/{MtcAudit-BlzwsoSM.js → MtcAudit-B8pCmqQJ.js} +4 -4
  44. package/src/assets/web-panel/assets/{Multisig-BBLmTty6.js → Multisig-BbOmYutA.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-DtT1uf1W.js → NLProgramming-BocLQz_M.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-DcqQAxTK.js → Notes-CSwbxEop.js} +3 -3
  47. package/src/assets/web-panel/assets/{NotificationSettings-cb0kWoZe.js → NotificationSettings-CqFNSYG3.js} +1 -1
  48. package/src/assets/web-panel/assets/{OrderTableRenderer-kw9HZQNN.js → OrderTableRenderer-C6gMfAk7.js} +1 -1
  49. package/src/assets/web-panel/assets/{Organization-DlTlbkUN.js → Organization-QrDXVdMJ.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-pp1qs-oY.js → Overflow-Cxntotjt.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-BESLnyYz.js → P2P-CIdBOwNq.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-B-J1mGuf.js → PdhVaultBrowser-CT5aP8rD.js} +3 -3
  53. package/src/assets/web-panel/assets/{Permissions-B36PeT1_.js → Permissions-DH7OM8XU.js} +4 -4
  54. package/src/assets/web-panel/assets/{PersonalDataHub-CTK2ad-3.js → PersonalDataHub-CnJqbWce.js} +3 -3
  55. package/src/assets/web-panel/assets/{Pipeline-zJNGXsac.js → Pipeline-5C3HG1kH.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-b9fz0Qf0.js → Privacy-B4yIp7xK.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-DjZbZgiB.js → ProjectInit-BMvt-2M0.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-C-hHJXlD.js → ProjectSettings-CvSTEMRG.js} +2 -2
  59. package/src/assets/web-panel/assets/Projects-BKBJxEek.js +1 -0
  60. package/src/assets/web-panel/assets/Providers-BdwUqFWN.js +1 -0
  61. package/src/assets/web-panel/assets/{QrScannerModal-A0yoQ3-3.js → QrScannerModal-DtnCKlTm.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-DrFgFJNC.js → QuickAsk-sTbgwyNr.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend-KC8hF1g4.js → Recommend-Bzr14gSb.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-DGTPIk6u.js → RemoteSession-C_TF5IaJ.js} +2 -2
  65. package/src/assets/web-panel/assets/{Reputation-QmbwM7Yk.js → Reputation-GCAM4H2K.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-BxjJylia.js → Row-Dir0r6OQ.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-B7Wda1J6.js → RssFeed-CpGnlecX.js} +2 -2
  68. package/src/assets/web-panel/assets/{Search-_plQ_YSA.js → Search-DMMamC6u.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-CD2YJZfx.js → Security-yqay5yG-.js} +4 -4
  70. package/src/assets/web-panel/assets/{Services-qQE7NmwE.js → Services-C5i2wh9G.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-DgQqkFf7.js → Skeleton-vUqk35yj.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-C4C0oFFt.js → Skills-DzcSkhot.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-Px2N2B5c.js → Sla-CB6qbYNr.js} +1 -1
  74. package/src/assets/web-panel/assets/{SpeechSettings-DN6C3lQd.js → SpeechSettings-BHUI7cox.js} +1 -1
  75. package/src/assets/web-panel/assets/{SyncSettings-jm5aH_m7.js → SyncSettings-D-RrsxTJ.js} +2 -2
  76. package/src/assets/web-panel/assets/{Tasks-DlkJcv67.js → Tasks-DFxdOJiq.js} +1 -1
  77. package/src/assets/web-panel/assets/{Templates-DyrTHUBs.js → Templates-SKAob_Aq.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-mC434PtL.js → Tenant-BPfsfHQ-.js} +1 -1
  79. package/src/assets/web-panel/assets/{Terminal-o0_s3NgK.js → Terminal-8iw7FpUf.js} +2 -2
  80. package/src/assets/web-panel/assets/{TimelineRenderer-DAGlAXOw.js → TimelineRenderer-C4Gjj5Su.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-BnulS_bs.js → Tokens-COYhN18e.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-suQbVXYM.js → Trigger-B-JzXcf6.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-DbIJAPo5.js → Trust-BJ5bg0nI.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-CQNpbIHi.js → UkeySign-BG_ByRMf.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-D8aWCERk.js → VideoEditing-B3kOnSiU.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-CuLpYfZc.js → Wallet-CcoGFnK7.js} +2 -2
  87. package/src/assets/web-panel/assets/{WebAuthn-CsfG8ZMc.js → WebAuthn-DdT8vRC_.js} +4 -4
  88. package/src/assets/web-panel/assets/{WorkflowEditor-BYsEAZbd.js → WorkflowEditor-CZu3M9N8.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-FT4Um3-I.js → chat-DxJt3Qba.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-CKbS_Wlt.js → colors-DdYfwJaB.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-CFJtzuJM.js → compact-item-BG3SUzwj.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-B9kSRW6K.js → createContext-By51z2-1.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-DorRZcI9.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-DR-x0Xpi.js → hasIn-B0apZ3KJ.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-DjEP7WkH.js → index-3jWkIu5j.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-7jHr_A_k.js → index-B3rWuPMW.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-DcfxhKXR.js → index-B5rLiEo0.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-tqSEHPRT.js → index-BBPf3TpM.js} +1 -1
  99. package/src/assets/web-panel/assets/index-BETiL0a3.js +1 -0
  100. package/src/assets/web-panel/assets/{index-Cr2FLUsD.js → index-BIrJfqO4.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-Bt4fS2eL.js → index-BLIbGOLX.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-BwR7yc2h.js → index-BP94CrBV.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BVPU43b1.js → index-BWF8_mkx.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-DShSkww-.js → index-BYINoRLK.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-Bzz0C1BZ.js → index-BZ_0qm4g.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-KqDaCApw.js → index-BewKYrX9.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-BW-t9n-q.js → index-BfWYsB9t.js} +1 -1
  108. package/src/assets/web-panel/assets/index-BhAVHuW8.js +1 -0
  109. package/src/assets/web-panel/assets/{index-B7osrXqy.js → index-Bissefox.js} +3 -3
  110. package/src/assets/web-panel/assets/{index-DW4BWjTk.js → index-BkvcEo4p.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-DdkIhfi-.js → index-Bos5_aMV.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-DTxNy0ZU.js → index-C1C9i79A.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-QBSeNVO3.js → index-CAhHirVH.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-D4LfPvWA.js → index-CNIxXMmN.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-C_enk9I_.js → index-CW93tZDv.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-WE08gMJP.js → index-CWEuZWCK.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-r2VI1Ikk.js → index-Cp6e-hGw.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-Dap9c3eD.js → index-CpjZhgNd.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DWdqx7zI.js → index-CzmQElZy.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-BGbPnC5x.js → index-DCn8IcxV.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-DiNUEpSQ.js → index-DE76D-kA.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-DtkFqPVA.js → index-DaIz0NAW.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-CGaXUsIs.js → index-Da_WBdLX.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-B3ZX81mK.js → index-Dz49VOyQ.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-BK3TiKVq.js → index-Q2SCX-MI.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CJmIQ9XR.js → index-RD6O-0C6.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CvrCCqJt.js → index-SQqOlR3d.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-BI5hP_qy.js → index-ZFbps9po.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-DeSgw-WV.js → index-ZxtP8jG7.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-DMGmg497.js → index-bP_VlDb4.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-BfFCQHL3.js → index-kf57LJ93.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-OSzjTzGM.js → index-oxRrmFO9.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-C2JvmYRc.js → index-p1_8SbI1.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-Dd7n7VgI.js → initDefaultProps-BWJktcg8.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-BwxouRw1.js → motion-BEXBzUFV.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-DObN0PG9.js → move-BUKwn2sx.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-B3nOUQc7.js → mtc-parser-FTI7btqQ.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-o9WU2Nbl.js → omit-CsLtSPH3.js} +1 -1
  139. package/src/assets/web-panel/assets/parsers-YNLm7sQ0.js +4 -0
  140. package/src/assets/web-panel/assets/{pickAttrs-CL_vvfQ_.js → pickAttrs-DWZxsT_S.js} +1 -1
  141. package/src/assets/web-panel/assets/{placementArrow-CYrM2tyK.js → placementArrow-Bcfs43CX.js} +1 -1
  142. package/src/assets/web-panel/assets/{responsiveObserve-k_06cQ96.js → responsiveObserve-a9bcC1p-.js} +1 -1
  143. package/src/assets/web-panel/assets/{slide-CPKG0pxS.js → slide-BDTzgOXN.js} +1 -1
  144. package/src/assets/web-panel/assets/{statusUtils-BDDEeLTw.js → statusUtils-Iq1j_HUg.js} +1 -1
  145. package/src/assets/web-panel/assets/{styleChecker-Cmb7RTh7.js → styleChecker-DAZEYxeh.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFlexGapSupport-e2IedC4N.js → useFlexGapSupport-DVkjyDrh.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFs-CE_gxVnm.js → useFs-wXTpNTHt.js} +1 -1
  148. package/src/assets/web-panel/assets/{usePersonalDataHub-BkMIIKMz.js → usePersonalDataHub-CtQM_aZr.js} +1 -1
  149. package/src/assets/web-panel/assets/{vnode-DW886XV1.js → vnode-hjEoG85v.js} +1 -1
  150. package/src/assets/web-panel/assets/{zoom-Dwo_adaf.js → zoom-BHVpyKg_.js} +1 -1
  151. package/src/assets/web-panel/index.html +1 -1
  152. package/src/command-help-index.json +3 -3
  153. package/src/commands/agent.js +14 -2
  154. package/src/commands/artifacts.js +235 -0
  155. package/src/commands/background-session.js +100 -10
  156. package/src/commands/cowork.js +86 -57
  157. package/src/commands/mcp.js +5 -0
  158. package/src/commands/plugin.js +145 -29
  159. package/src/commands/remote-control.js +295 -110
  160. package/src/commands/session-location.js +20 -1
  161. package/src/commands/session-message.js +171 -0
  162. package/src/commands/session.js +75 -69
  163. package/src/data/changelog.json +29 -3
  164. package/src/gateways/ws/message-dispatcher.js +57 -0
  165. package/src/harness/mcp-client.js +141 -10
  166. package/src/lib/artifact-access-ledger.js +1 -0
  167. package/src/lib/artifact-deletion-ledger.js +1 -0
  168. package/src/lib/artifact-recovery.js +970 -0
  169. package/src/lib/artifact-workbench-projection.js +171 -0
  170. package/src/lib/background-session-transport.js +153 -27
  171. package/src/lib/dynamic-workflow-runtime.js +408 -1
  172. package/src/lib/execution-location-target.js +4 -2
  173. package/src/lib/mcp-client.js +2 -0
  174. package/src/lib/mcp-headers-helper.js +47 -5
  175. package/src/lib/mcp-oauth.js +55 -6
  176. package/src/lib/mcp-stdio-executable-identity.js +16 -0
  177. package/src/lib/mcp-stdio-native-code-policy.js +74 -0
  178. package/src/lib/mcp-stdio-package-materialization.js +12 -3
  179. package/src/lib/mcp-tls.js +230 -0
  180. package/src/lib/output-styles.js +12 -0
  181. package/src/lib/plugin-runtime/install.js +614 -71
  182. package/src/lib/plugin-runtime/marketplace-archive-source.js +331 -0
  183. package/src/lib/plugin-runtime/marketplace-catalog.js +52 -6
  184. package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +1 -0
  185. package/src/lib/plugin-runtime/marketplace-source-adapter.js +163 -0
  186. package/src/lib/plugin-runtime/marketplace-source-cache.js +11 -1
  187. package/src/lib/plugin-runtime/remote-source.js +435 -55
  188. package/src/lib/plugin-security.js +393 -41
  189. package/src/lib/plugin-source-identity.js +850 -0
  190. package/src/lib/process-execution-broker/index.js +112 -0
  191. package/src/lib/process-execution-broker/platform-sandbox.js +57 -3
  192. package/src/lib/process-execution-broker/workspace-transaction.js +26 -0
  193. package/src/lib/remote-approval-bridge.js +136 -46
  194. package/src/lib/remote-control.js +217 -31
  195. package/src/lib/session-message-fabric.js +1105 -0
  196. package/src/lib/session-projection.js +171 -12
  197. package/src/lib/session-runtime-retention.js +155 -0
  198. package/src/lib/settings-loader.cjs +29 -0
  199. package/src/repl/agent-repl.js +51 -14
  200. package/src/repl/permission-prompt.js +31 -8
  201. package/src/repl/repl-keybindings.js +55 -0
  202. package/src/runtime/agent-core.js +63 -2
  203. package/src/runtime/headless-runner.js +47 -66
  204. package/src/runtime/headless-stream.js +18 -24
  205. package/src/runtime/mcp-config.js +2 -0
  206. package/src/runtime/policies/agent-policy.js +2 -0
  207. package/src/assets/web-panel/assets/ChatBubbleRenderer-xijcWkJe.js +0 -1
  208. package/src/assets/web-panel/assets/MarkdownRenderer-hDpWdiBc.js +0 -1
  209. package/src/assets/web-panel/assets/Projects-BC9KSDM6.js +0 -1
  210. package/src/assets/web-panel/assets/Providers-Dz-CAYYU.js +0 -1
  211. package/src/assets/web-panel/assets/devWarning-DJZ0gAMu.js +0 -1
  212. package/src/assets/web-panel/assets/index-Bizb4hkw.js +0 -1
  213. package/src/assets/web-panel/assets/index-OHSl-xCh.js +0 -1
  214. package/src/assets/web-panel/assets/parsers-UEvh_ShA.js +0 -4
@@ -0,0 +1,171 @@
1
+ import { logger } from "../lib/logger.js";
2
+ import { SessionMessageFabric } from "../lib/session-message-fabric.js";
3
+
4
+ function output(value, options = {}) {
5
+ if (options.json) {
6
+ logger.log(JSON.stringify(value, null, 2));
7
+ return;
8
+ }
9
+ if (Array.isArray(value)) {
10
+ if (value.length === 0) {
11
+ logger.log("No session messages.");
12
+ return;
13
+ }
14
+ for (const item of value) logger.log(JSON.stringify(item));
15
+ return;
16
+ }
17
+ logger.log(JSON.stringify(value, null, 2));
18
+ }
19
+
20
+ function numericOption(value) {
21
+ if (value == null) return null;
22
+ const number = Number(value);
23
+ return Number.isSafeInteger(number) && number > 0 ? number : value;
24
+ }
25
+
26
+ function fabric() {
27
+ return new SessionMessageFabric();
28
+ }
29
+
30
+ export function registerSessionMessageCommands(session) {
31
+ const message = session
32
+ .command("message")
33
+ .description(
34
+ "Durable cross-session inbox, addressing, policy and receipts",
35
+ );
36
+
37
+ message
38
+ .command("register <session-id>")
39
+ .description("Register or reconnect a uniquely named session endpoint")
40
+ .option("--name <name>", "Unique @name (defaults to session id)")
41
+ .option("--machine <id>", "Stable machine identity", "local")
42
+ .option(
43
+ "--policy <policy>",
44
+ "Inbound policy: accept | hold | refuse",
45
+ "accept",
46
+ )
47
+ .option("--busy", "Register as busy instead of idle")
48
+ .option("--json", "Output as JSON")
49
+ .action((sessionId, options) => {
50
+ output(
51
+ fabric().register({
52
+ sessionId,
53
+ name: options.name || sessionId,
54
+ machineId: options.machine,
55
+ policy: options.policy,
56
+ idle: options.busy !== true,
57
+ }),
58
+ options,
59
+ );
60
+ });
61
+
62
+ message
63
+ .command("unregister <endpoint>")
64
+ .description("Retire an endpoint epoch without leaking its inbox to reuse")
65
+ .option("--json", "Output as JSON")
66
+ .action((endpoint, options) => {
67
+ output(
68
+ { unregistered: fabric().unregister(endpoint), endpoint },
69
+ options,
70
+ );
71
+ });
72
+
73
+ message
74
+ .command("send <from> <to> <body...>")
75
+ .description("Send one bounded, idempotent message and print its receipt")
76
+ .option("--subject <text>", "Optional bounded subject")
77
+ .option("--message-id <id>", "Stable idempotency key")
78
+ .option("--sequence <n>", "Per sender/recipient ordering sequence")
79
+ .option("--ttl-ms <n>", "Message expiry in milliseconds")
80
+ .option(
81
+ "--notify-when-idle",
82
+ "Emit one receipt update when target becomes idle",
83
+ )
84
+ .option("--json", "Output as JSON")
85
+ .action((from, to, body, options) => {
86
+ output(
87
+ fabric().send({
88
+ from,
89
+ to,
90
+ body: body.join(" "),
91
+ subject: options.subject,
92
+ messageId: options.messageId,
93
+ sequence: numericOption(options.sequence),
94
+ ttlMs: numericOption(options.ttlMs),
95
+ notifyWhenIdle: options.notifyWhenIdle === true,
96
+ }),
97
+ options,
98
+ );
99
+ });
100
+
101
+ message
102
+ .command("inbox <endpoint>")
103
+ .description("Read an endpoint inbox in sender sequence order")
104
+ .option("--ack", "Acknowledge and release returned live message bodies")
105
+ .option("--json", "Output as JSON")
106
+ .action((endpoint, options) => {
107
+ output(fabric().inbox(endpoint, { acknowledge: options.ack }), options);
108
+ });
109
+
110
+ message
111
+ .command("receipts <endpoint>")
112
+ .description("List durable delivered/refused/full/expired receipts")
113
+ .option("--json", "Output as JSON")
114
+ .action((endpoint, options) => {
115
+ output(fabric().receipts(endpoint), options);
116
+ });
117
+
118
+ message
119
+ .command("policy <endpoint> <policy>")
120
+ .description("Set accept, hold or refuse with optional revision CAS")
121
+ .option("--expected-revision <n>", "Reject a stale rendered policy action")
122
+ .option("--json", "Output as JSON")
123
+ .action((endpoint, policy, options) => {
124
+ output(
125
+ fabric().setPolicy(endpoint, policy, {
126
+ expectedRevision: numericOption(options.expectedRevision),
127
+ }),
128
+ options,
129
+ );
130
+ });
131
+
132
+ message
133
+ .command("idle <endpoint> <state>")
134
+ .description("Set idle/busy and deliver notify_when_idle exactly once")
135
+ .option("--expected-revision <n>", "Reject a stale rendered idle action")
136
+ .option("--json", "Output as JSON")
137
+ .action((endpoint, state, options) => {
138
+ const normalized = String(state).trim().toLowerCase();
139
+ if (!["idle", "busy", "true", "false"].includes(normalized)) {
140
+ const error = new Error("state must be idle, busy, true or false");
141
+ error.code = "SESSION_MESSAGE_INVALID_ARGUMENT";
142
+ throw error;
143
+ }
144
+ output(
145
+ fabric().setIdle(endpoint, ["idle", "true"].includes(normalized), {
146
+ expectedRevision: numericOption(options.expectedRevision),
147
+ }),
148
+ options,
149
+ );
150
+ });
151
+
152
+ for (const action of ["disconnect", "reconnect"]) {
153
+ message
154
+ .command(`${action} <endpoint>`)
155
+ .description(
156
+ action === "disconnect"
157
+ ? "Mark transport offline while retaining its durable inbox"
158
+ : "Mark a durable endpoint transport online again",
159
+ )
160
+ .option("--json", "Output as JSON")
161
+ .action((endpoint, options) => {
162
+ output({ endpoint, [action]: fabric()[action](endpoint) }, options);
163
+ });
164
+ }
165
+
166
+ message
167
+ .command("status")
168
+ .description("Emit the bounded CLI-owned message projection")
169
+ .option("--json", "Output as JSON")
170
+ .action((options) => output(fabric().projection(), options));
171
+ }
@@ -68,6 +68,7 @@ import { registerSessionShowSubcommand } from "./session-show.js";
68
68
  import { registerSessionObservabilitySubcommand } from "./session-observability.js";
69
69
  import { registerSessionLocationSubcommands } from "./session-location.js";
70
70
  import { registerSessionBudgetCommands } from "./session-budget.js";
71
+ import { registerSessionMessageCommands } from "./session-message.js";
71
72
 
72
73
  export const _deps = {
73
74
  execFileSync: (...args) => executionBroker.execFileSync(...args),
@@ -104,9 +105,8 @@ function _sessionEpoch(ts) {
104
105
  * @returns {{statusBar:string, autoMerge:{allow:boolean,reason:string,unmet:string[]}, lines:string[]}}
105
106
  */
106
107
  export async function renderPrStatus(signals = {}, opts = {}) {
107
- const { strictAutoMergeDecision, describePrStatusBar } = await import(
108
- "../lib/pr-automation-policy.js"
109
- );
108
+ const { strictAutoMergeDecision, describePrStatusBar } =
109
+ await import("../lib/pr-automation-policy.js");
110
110
  const autoMerge = strictAutoMergeDecision({
111
111
  enabled: opts.enabled === true,
112
112
  hasOpenPr: signals.hasOpenPr,
@@ -227,6 +227,7 @@ export function registerSessionCommand(program) {
227
227
  registerSessionMcpRecoveryCommands(session);
228
228
  registerSessionLocationSubcommands(session);
229
229
  registerSessionBudgetCommands(session);
230
+ registerSessionMessageCommands(session);
230
231
 
231
232
  // session list
232
233
  session
@@ -321,6 +322,8 @@ export function registerSessionCommand(program) {
321
322
  let remote = [];
322
323
  let team = [];
323
324
  let workflow = [];
325
+ let dynamicWorkflow = [];
326
+ let sessionMessageFabric = null;
324
327
  let artifacts = [];
325
328
  let prLinks = {};
326
329
 
@@ -350,25 +353,22 @@ export function registerSessionCommand(program) {
350
353
  sourceErrors.local = error?.message || String(error);
351
354
  }
352
355
  try {
353
- const { listBackgroundAgents } = await import(
354
- "../lib/background-agent-supervisor.js"
355
- );
356
+ const { listBackgroundAgents } =
357
+ await import("../lib/background-agent-supervisor.js");
356
358
  background = listBackgroundAgents({ all: true });
357
359
  } catch (error) {
358
360
  sourceErrors.background = error?.message || String(error);
359
361
  }
360
362
  try {
361
- const { readRemoteControlStates } = await import(
362
- "../lib/remote-control.js"
363
- );
363
+ const { readRemoteControlStates } =
364
+ await import("../lib/remote-control.js");
364
365
  remote = readRemoteControlStates();
365
366
  } catch (error) {
366
367
  sourceErrors.remote = error?.message || String(error);
367
368
  }
368
369
  try {
369
- const { listCollaborationRuns } = await import(
370
- "../lib/collaboration-run-store.js"
371
- );
370
+ const { listCollaborationRuns } =
371
+ await import("../lib/collaboration-run-store.js");
372
372
  team = listCollaborationRuns({ limit }).filter(
373
373
  (run) => run?.kind === "team",
374
374
  );
@@ -388,14 +388,29 @@ export function registerSessionCommand(program) {
388
388
  } catch (error) {
389
389
  sourceErrors.workflow = error?.message || String(error);
390
390
  }
391
+ try {
392
+ const { listDynamicWorkflowWorkbenchStates } =
393
+ await import("../lib/dynamic-workflow-runtime.js");
394
+ const discovered = listDynamicWorkflowWorkbenchStates(projectRoot, {
395
+ limit,
396
+ });
397
+ dynamicWorkflow = discovered.runs.map((item) => ({
398
+ ...item,
399
+ cwd: projectRoot,
400
+ }));
401
+ if (discovered.invalidCount > 0) {
402
+ sourceErrors.dynamicWorkflow = `${discovered.invalidCount} durable workflow state file(s) failed validation`;
403
+ }
404
+ } catch (error) {
405
+ sourceErrors.dynamicWorkflow = error?.message || String(error);
406
+ }
391
407
  try {
392
408
  // A file checkpoint is advertised only after the existing CLI git
393
409
  // engine proves that the exact worktree is supported. Copy-mode
394
410
  // checkpoints need explicit paths and therefore cannot truthfully be
395
411
  // offered as a one-click session action.
396
- const { isCheckpointAvailable } = await import(
397
- "../lib/checkpoint-store.js"
398
- );
412
+ const { isCheckpointAvailable } =
413
+ await import("../lib/checkpoint-store.js");
399
414
  const capability = new Map();
400
415
  const decorate = (items, pathFor, sessionFor) =>
401
416
  items.map((item) => {
@@ -438,9 +453,8 @@ export function registerSessionCommand(program) {
438
453
  // checkpoint action unavailable with its explicit reason.
439
454
  }
440
455
  try {
441
- const { ArtifactStore, publicArtifactMetadata } = await import(
442
- "../lib/artifact-store.js"
443
- );
456
+ const { ArtifactStore, publicArtifactMetadata } =
457
+ await import("../lib/artifact-store.js");
444
458
  artifacts = new ArtifactStore().list().map(publicArtifactMetadata);
445
459
  } catch {
446
460
  // Summaries are optional; absence never removes a session.
@@ -451,18 +465,26 @@ export function registerSessionCommand(program) {
451
465
  } catch {
452
466
  // Summaries are optional; absence never removes a session.
453
467
  }
468
+ try {
469
+ const { SessionMessageFabric } =
470
+ await import("../lib/session-message-fabric.js");
471
+ sessionMessageFabric = new SessionMessageFabric().projection();
472
+ } catch (error) {
473
+ sourceErrors.sessionMessageFabric = error?.message || String(error);
474
+ }
454
475
 
455
- const { buildSessionProjection } = await import(
456
- "../lib/session-projection.js"
457
- );
476
+ const { buildSessionProjection } =
477
+ await import("../lib/session-projection.js");
458
478
  const projection = buildSessionProjection({
459
479
  local,
460
480
  background,
461
481
  remote,
462
482
  team,
463
483
  workflow,
484
+ dynamicWorkflow,
464
485
  artifacts,
465
486
  prLinks,
487
+ sessionMessageFabric,
466
488
  sourceErrors,
467
489
  });
468
490
  if (options.json) {
@@ -478,9 +500,8 @@ export function registerSessionCommand(program) {
478
500
  }
479
501
  }
480
502
  } catch (error) {
481
- const { disconnectedSessionProjection } = await import(
482
- "../lib/session-projection.js"
483
- );
503
+ const { disconnectedSessionProjection } =
504
+ await import("../lib/session-projection.js");
484
505
  if (options.json) {
485
506
  jsonPayload = JSON.stringify(
486
507
  disconnectedSessionProjection(error?.message || String(error)),
@@ -530,9 +551,8 @@ export function registerSessionCommand(program) {
530
551
  } else {
531
552
  // Live path: resolve the session's linked PR and fetch via gh.
532
553
  const { getPrLinks } = await import("../lib/pr-link-ledger.js");
533
- const { getLastSessionId } = await import(
534
- "../harness/jsonl-session-store.js"
535
- );
554
+ const { getLastSessionId } =
555
+ await import("../harness/jsonl-session-store.js");
536
556
  const sid = !id || id === "last" ? getLastSessionId() : id;
537
557
  const links = sid ? getPrLinks(sid) : [];
538
558
  if (links.length === 0) {
@@ -610,9 +630,8 @@ export function registerSessionCommand(program) {
610
630
  // (single / non-TTY / Ctrl-C). Same helper as `cc agent --resume`.
611
631
  if (!id) {
612
632
  ctx = await bootstrap({ verbose: program.opts().verbose });
613
- const { pickRecentSession } = await import(
614
- "../lib/session-picker.js"
615
- );
633
+ const { pickRecentSession } =
634
+ await import("../lib/session-picker.js");
616
635
  const picked = await pickRecentSession(ctx);
617
636
  if (!picked.id) {
618
637
  logger.error(
@@ -642,9 +661,8 @@ export function registerSessionCommand(program) {
642
661
  if (jsonlId) {
643
662
  // Tamper gate: a broken hash chain means the transcript was edited
644
663
  // outside the store — never silently rebuild it as trusted context.
645
- const { verifySession } = await import(
646
- "../harness/jsonl-session-store.js"
647
- );
664
+ const { verifySession } =
665
+ await import("../harness/jsonl-session-store.js");
648
666
  const trust = verifySession(jsonlId);
649
667
  if (["missing", "conflict"].includes(trust.status)) {
650
668
  logger.error(
@@ -757,9 +775,8 @@ export function registerSessionCommand(program) {
757
775
  );
758
776
  }
759
777
  if (sid) {
760
- const { renderAgentSessionMarkdown } = await import(
761
- "../lib/agent-session-export.js"
762
- );
778
+ const { renderAgentSessionMarkdown } =
779
+ await import("../lib/agent-session-export.js");
763
780
  markdown = renderAgentSessionMarkdown(sid, store.readEvents(sid), {
764
781
  exportedAt: new Date().toISOString(),
765
782
  });
@@ -1012,9 +1029,8 @@ export function registerSessionCommand(program) {
1012
1029
  }
1013
1030
  let result;
1014
1031
  if (jsonlId) {
1015
- const { renameSession } = await import(
1016
- "../harness/jsonl-session-store.js"
1017
- );
1032
+ const { renameSession } =
1033
+ await import("../harness/jsonl-session-store.js");
1018
1034
  result = renameSession(jsonlId, normalized);
1019
1035
  } else {
1020
1036
  ctx = await bootstrap({ verbose: program.opts().verbose });
@@ -1053,9 +1069,8 @@ export function registerSessionCommand(program) {
1053
1069
  .option("--json", "Output as JSON")
1054
1070
  .action(async (options) => {
1055
1071
  try {
1056
- const { pruneJsonlSessions } = await import(
1057
- "../harness/jsonl-session-store.js"
1058
- );
1072
+ const { pruneJsonlSessions } =
1073
+ await import("../harness/jsonl-session-store.js");
1059
1074
  const result = pruneJsonlSessions({
1060
1075
  olderThanDays: Number(options.olderThan),
1061
1076
  keep: options.keep != null ? Number(options.keep) : undefined,
@@ -1433,9 +1448,8 @@ export function registerSessionCommand(program) {
1433
1448
  .option("--json", "Output as JSON")
1434
1449
  .action(async (id, options) => {
1435
1450
  try {
1436
- const { getApprovalGate } = await import(
1437
- "../lib/session-core-singletons.js"
1438
- );
1451
+ const { getApprovalGate } =
1452
+ await import("../lib/session-core-singletons.js");
1439
1453
  const gate = await getApprovalGate();
1440
1454
  if (options.set) {
1441
1455
  gate.setSessionPolicy(id, options.set);
@@ -1471,9 +1485,8 @@ export function registerSessionCommand(program) {
1471
1485
  .option("--json", "Output as JSON")
1472
1486
  .action(async (options) => {
1473
1487
  try {
1474
- const { getSessionManager } = await import(
1475
- "../lib/session-core-singletons.js"
1476
- );
1488
+ const { getSessionManager } =
1489
+ await import("../lib/session-core-singletons.js");
1477
1490
  const mgr = getSessionManager();
1478
1491
  const live = mgr.list({
1479
1492
  agentId: options.agent,
@@ -1517,9 +1530,8 @@ export function registerSessionCommand(program) {
1517
1530
  .argument("<id>", "Session ID")
1518
1531
  .action(async (id) => {
1519
1532
  try {
1520
- const { getSessionManager } = await import(
1521
- "../lib/session-core-singletons.js"
1522
- );
1533
+ const { getSessionManager } =
1534
+ await import("../lib/session-core-singletons.js");
1523
1535
  const mgr = getSessionManager();
1524
1536
  if (!mgr.has(id)) {
1525
1537
  logger.error(`Session ${id} is not active in this process`);
@@ -1544,9 +1556,8 @@ export function registerSessionCommand(program) {
1544
1556
  .argument("<id>", "Session ID")
1545
1557
  .action(async (id) => {
1546
1558
  try {
1547
- const { getSessionManager } = await import(
1548
- "../lib/session-core-singletons.js"
1549
- );
1559
+ const { getSessionManager } =
1560
+ await import("../lib/session-core-singletons.js");
1550
1561
  const mgr = getSessionManager();
1551
1562
  const ok = await mgr.resume(id);
1552
1563
  if (!ok) {
@@ -1575,14 +1586,12 @@ export function registerSessionCommand(program) {
1575
1586
  .option("--agent-id <id>", "Agent id for scope=agent")
1576
1587
  .action(async (id, options) => {
1577
1588
  try {
1578
- const { getSessionManager } = await import(
1579
- "../lib/session-core-singletons.js"
1580
- );
1589
+ const { getSessionManager } =
1590
+ await import("../lib/session-core-singletons.js");
1581
1591
  if (options.consolidate) {
1582
1592
  try {
1583
- const { consolidateJsonlSession } = await import(
1584
- "../lib/session-consolidator.js"
1585
- );
1593
+ const { consolidateJsonlSession } =
1594
+ await import("../lib/session-consolidator.js");
1586
1595
  const res = await consolidateJsonlSession(id, {
1587
1596
  scope: options.scope,
1588
1597
  scopeId: options.scopeId || null,
@@ -1801,9 +1810,8 @@ export function registerSessionCommand(program) {
1801
1810
  );
1802
1811
  process.exit(1);
1803
1812
  }
1804
- const { sessionUsage, allSessionsUsage } = await import(
1805
- "../lib/session-usage.js"
1806
- );
1813
+ const { sessionUsage, allSessionsUsage } =
1814
+ await import("../lib/session-usage.js");
1807
1815
  const result = id
1808
1816
  ? sessionUsage(id)
1809
1817
  : allSessionsUsage({ limit: parseInt(options.limit, 10) || 1000 });
@@ -1876,9 +1884,8 @@ export function registerSessionCommand(program) {
1876
1884
  .option("--json", "Machine-readable JSON output")
1877
1885
  .action(async (id) => {
1878
1886
  try {
1879
- const { getVerifiedSessionObservabilityAuthority } = await import(
1880
- "../harness/jsonl-session-store.js"
1881
- );
1887
+ const { getVerifiedSessionObservabilityAuthority } =
1888
+ await import("../harness/jsonl-session-store.js");
1882
1889
  const authority = getVerifiedSessionObservabilityAuthority(id);
1883
1890
  console.log(
1884
1891
  JSON.stringify(
@@ -2316,9 +2323,8 @@ async function mirrorPruneSessions() {
2316
2323
  * (`session.mirror.encryption`). Requires both to be configured.
2317
2324
  */
2318
2325
  async function mirrorRotateKey() {
2319
- const { createMirror, createMirrorCipher, rotateMirrorKey } = await import(
2320
- "../harness/session-mirror.js"
2321
- );
2326
+ const { createMirror, createMirrorCipher, rotateMirrorKey } =
2327
+ await import("../harness/session-mirror.js");
2322
2328
  const { cfg } = await loadConfiguredMirror();
2323
2329
  if (!cfg || !cfg.kind || cfg.kind === "none") {
2324
2330
  return { target: null };
@@ -1,6 +1,32 @@
1
1
  {
2
2
  "source": "CHANGELOG.md",
3
3
  "releases": [
4
+ {
5
+ "productVersion": null,
6
+ "cliVersion": "0.165.6",
7
+ "cliVersions": ["0.165.5", "0.165.6"],
8
+ "date": "2026-08-21",
9
+ "title": "",
10
+ "sections": [
11
+ {
12
+ "heading": "Added - cc CLI 0.165.6: safer remote sessions and governed plugin sources",
13
+ "body": "> `chainlesschain` **0.165.5 -> 0.165.6** (candidate; not yet published,\n> 2026-08-21).\n> CLI-only release; `@chainlesschain/personal-data-hub` remains **0.4.59**\n> and `@chainlesschain/agent-sdk` remains **0.1.7**.\n\n- **Remote Control safe defaults**: direct sessions bind to loopback by\n default. Trusted-LAN exposure requires explicit command authority, preserves\n the selected bind address, fails closed on relay/direct fallback, and keeps\n IDE pairing surfaces from presenting loopback endpoints as phone-ready QR\n links.\n- **Governed plugin source identity**: managed Marketplace policy now evaluates\n canonical Git, registry, file, alias, ref, path, host, port, principal, and\n registry-resolution identities before target I/O or process spawn. Clone\n execution is isolated from ambient Git/SSH configuration, and cache\n provenance remains bound to the approved source and registry document.\n- **Digest-pinned Marketplace archives**: registry install and update can\n materialize same-origin, catalog-bound `tgz`/`tar.gz` sources only after\n candidate preflight. SHA-256 verification and bounded extraction reject\n traversal, links, special entries, case collisions, and expansion bombs;\n archive and extracted-payload digest authority are revalidated for offline\n cache replay. Dynamic command and headers-helper sources remain disabled by\n product policy.\n- **Cross-platform policy enforcement**: Windows runner temporary roots are\n canonicalized without probing caller-controlled targets. Other existing 8.3\n spellings resolve to their long-path authority, while unresolved or forged\n aliases remain rejected. Linux, Windows, and macOS Marketplace campaigns\n exercise air-gapped cache, proxy, PAC, and private-registry boundaries.\n- **Durable session and MCP lifecycle**: cross-session messaging, bounded\n long-running live state, MCP reconnect subscription recovery, lifecycle\n compatibility, and structured headless observability now share explicit\n identity, cleanup, and backpressure contracts.\n- **Focused terminal ergonomics**: the `concise` output style and persisted\n `classic`/`readline` keybinding flavor extend interactive use without\n changing existing default behavior.\n- **Release status**: publication requires the final candidate commit to pass\n the complete Linux, Windows, and macOS `CLI CI` and `CLI Strict Sandbox`\n matrices. The immutable npm tag, provenance, and registry readback will be\n recorded only after those exact-SHA gates succeed."
14
+ }
15
+ ]
16
+ },
17
+ {
18
+ "productVersion": null,
19
+ "cliVersion": "0.165.5",
20
+ "cliVersions": ["0.165.4", "0.165.5"],
21
+ "date": "2026-08-21",
22
+ "title": "",
23
+ "sections": [
24
+ {
25
+ "heading": "Added - cc CLI 0.165.5: governed recovery and native add-on policy",
26
+ "body": "> `chainlesschain` **0.165.4 -> 0.165.5** (published from exact SHA\n> `11aef634aa3ab88994698eca0ce2f5cfa65faf48`, 2026-08-21).\n> CLI-only release; `@chainlesschain/personal-data-hub` remains **0.4.59**\n> and `@chainlesschain/agent-sdk` remains **0.1.7**.\n\n- **Recoverable Artifact workflows**: inspect and settle orphaned Artifact\n writes through a bounded CLI-owned recovery projection, retain exact\n access/deletion evidence, and surface workbench state without letting IDE\n clients derive storage mutations.\n- **Durable workflow recovery**: plan and resume interrupted workflow stages\n through persisted authority and checkpoint evidence, with tighter session\n and execution-location projections for CLI, WebSocket, and IDE consumers.\n- **Native MCP add-on policy**: admit only supported native loader shapes and\n validated executable/package identities. Unsupported or ambiguous native\n add-ons now return typed fail-closed rejections instead of crossing the\n strict process boundary.\n- **Release gates**: add cross-host Marketplace, accessibility,\n execution-location, context/permission, and live-provider campaigns while\n keeping CI dependency installation clean and deterministic.\n- **Published release evidence**: immutable tag `v-npm-0-165-5`, three-OS\n `CLI CI` (`32413582642`), `CLI Strict Sandbox` (`32413582490`), npm release\n (`32428314006`), and independent registry/provenance readback\n (`32429710720`) all bind exact SHA `11aef634aa`. npm reports\n `latest=0.165.5`; the public tarball SHA-1 is\n `c2cc7fb18ea572749d747de02355c6a0a5aef357`."
27
+ }
28
+ ]
29
+ },
4
30
  {
5
31
  "productVersion": null,
6
32
  "cliVersion": "0.165.4",
@@ -10,7 +36,7 @@
10
36
  "sections": [
11
37
  {
12
38
  "heading": "Fixed - cc CLI 0.165.4: first install without a native build toolchain",
13
- "body": "> `chainlesschain` **0.165.3 -> 0.165.4** (candidate; not yet published,\n> 2026-08-20).\n> CLI release includes `@chainlesschain/personal-data-hub` **0.4.59**;\n> `@chainlesschain/agent-sdk` remains **0.1.7**.\n\n- **Portable first install**: Personal Data Hub now declares\n `better-sqlite3-multiple-ciphers` as an optional dependency. If a prebuilt\n binary cannot be downloaded, npm may skip the failed `node-gyp` fallback\n instead of aborting `npm install -g chainlesschain`; the CLI remains usable\n through its bundled `sql.js` WASM fallback.\n- **No-toolchain install gate**: the Windows and Linux global-install smoke\n deliberately disables native prebuilds and points node-gyp at a nonexistent\n Python executable. The packed candidate must still install and both `cc` and\n `chainlesschain` must start without `--ignore-scripts`.\n- **Release status**: this is source-level candidate evidence only. Publication\n still requires the exact release commit to pass the complete Linux, Windows,\n and macOS `CLI CI` and `CLI Strict Sandbox` matrices before the coordinated\n PDH and CLI packages are published and independently read back."
39
+ "body": "> `chainlesschain` **0.165.3 -> 0.165.4** (published from exact SHA\n> `86abb5f65e39f0dd553040fbfce07277336dfeeb`, 2026-08-20).\n> CLI release includes `@chainlesschain/personal-data-hub` **0.4.59**;\n> `@chainlesschain/agent-sdk` remains **0.1.7**.\n\n- **Portable first install**: Personal Data Hub now declares\n `better-sqlite3-multiple-ciphers` as an optional dependency. If a prebuilt\n binary cannot be downloaded, npm may skip the failed `node-gyp` fallback\n instead of aborting `npm install -g chainlesschain`; the CLI remains usable\n through its bundled `sql.js` WASM fallback.\n- **No-toolchain install gate**: the Windows and Linux global-install smoke\n deliberately disables native prebuilds and points node-gyp at a nonexistent\n Python executable. The packed candidate must still install and both `cc` and\n `chainlesschain` must start without `--ignore-scripts`.\n- **Published release evidence**: immutable tag `v-npm-0-165-4`, three-OS\n `CLI CI` (`32375466808`), `CLI Strict Sandbox` (`32375466552`), npm release\n (`32375466545`), and independent registry readback (`32377326843`) all bind\n exact SHA `86abb5f65e`. npm reports `latest=0.165.4`; the public tarball\n SHA-1 is `69ad469872d4e51d1cc2af7223d81eb6fed1dc50`."
14
40
  }
15
41
  ]
16
42
  },
@@ -23,7 +49,7 @@
23
49
  "sections": [
24
50
  {
25
51
  "heading": "Fixed — cc CLI 0.165.3: durable background keeper retirement",
26
- "body": "> `chainlesschain` **0.165.2 -> 0.165.3** (candidate; not yet published,\n> 2026-08-19).\n> CLI-only candidate; `@chainlesschain/personal-data-hub` remains **0.4.58**\n> and `@chainlesschain/agent-sdk` remains **0.1.7**.\n\n- **Durable keeper retirement evidence**: a Worker accepts a lost keeper\n response only when the persisted retirement record matches the exact worker\n generation, turn attempt, process identities, start anchors, and cleanup\n confirmation. Ambiguous or partial records continue to fail closed.\n- **Bounded keeper health probes**: Windows process-identity checks are delayed\n until the application heartbeat is actually silent, avoiding synchronized\n helper-process storms while preserving an exact-identity backstop before\n cleanup.\n- **Recoverable lock publication**: a lock owned by a provably dead process can\n be reclaimed even when that owner published its release marker but crashed\n before removing its private staging path. Active or identity-mismatched\n owners remain fenced.\n- **Idempotent bootstrap release**: a matching bootstrap release can be replayed\n after READY, and the Worker retransmits it when READY is repeated. Nonce,\n generation, attempt, wrapper PID, and runtime PID mismatches remain rejected.\n- **Release status**: immutable tag, final source SHA, workflow run IDs, npm\n provenance, package digests, and registry readback remain intentionally\n absent until the exact `0.165.3` candidate passes complete `CLI CI`,\n `CLI Strict Sandbox`, and the dedicated cross-platform keeper soak, followed\n by the npm release and independent public readback workflows."
52
+ "body": "> `chainlesschain` **0.165.2 -> 0.165.3** (published from exact SHA\n> `7d3eb9ea8046330e2b264bf2309337ebbbbcbacc`, 2026-08-19).\n> CLI-only release; `@chainlesschain/personal-data-hub` remains **0.4.58**\n> and `@chainlesschain/agent-sdk` remains **0.1.7**.\n\n- **Durable keeper retirement evidence**: a Worker accepts a lost keeper\n response only when the persisted retirement record matches the exact worker\n generation, turn attempt, process identities, start anchors, and cleanup\n confirmation. Ambiguous or partial records continue to fail closed.\n- **Bounded keeper health probes**: Windows process-identity checks are delayed\n until the application heartbeat is actually silent, avoiding synchronized\n helper-process storms while preserving an exact-identity backstop before\n cleanup.\n- **Recoverable lock publication**: a lock owned by a provably dead process can\n be reclaimed even when that owner published its release marker but crashed\n before removing its private staging path. Active or identity-mismatched\n owners remain fenced.\n- **Idempotent bootstrap release**: a matching bootstrap release can be replayed\n after READY, and the Worker retransmits it when READY is repeated. Nonce,\n generation, attempt, wrapper PID, and runtime PID mismatches remain rejected.\n- **Release status**: immutable tag `v-npm-0-165-3` and the public npm package\n bind exact SHA `7d3eb9ea80`. Its push `CLI CI` (`32212502595`),\n `CLI Strict Sandbox` (`32212502463`), and npm release (`32212502480`) passed;\n it is now superseded by the fully read-back `0.165.4` production baseline."
27
53
  }
28
54
  ]
29
55
  },
@@ -36,7 +62,7 @@
36
62
  "sections": [
37
63
  {
38
64
  "heading": "Fixed — cc CLI 0.165.2: governed plugins and keeper handoff reliability",
39
- "body": "> `chainlesschain` **0.165.1 → 0.165.2** (candidate; not yet published,\n> 2026-08-18).\n> CLI-only candidate; `@chainlesschain/personal-data-hub` remains **0.4.58**\n> and `@chainlesschain/agent-sdk` remains **0.1.7**.\n\n- **Governed plugin transactions and provenance**: marketplace payload,\n activation, install, update, transaction recovery, and provenance decisions\n bind immutable source identities and digests. Registry cache entries are\n content-addressed, while corrupt, stale, or mismatched recovery evidence\n continues to fail closed.\n- **Strict plugin execution boundaries**: the remaining live plugin fixtures\n now execute in the strict Linux sandbox, MCP security soak provisions its\n required Bubblewrap boundary explicitly, and release fixtures exercise the\n production activation path instead of accepting inactive coverage.\n- **Durable workflow authority**: provider requests and settlements, nested and\n parallel tool effects, child and descendant calls, and timeout outcomes gain\n durable identity-bound receipts so retries cannot silently reuse ambiguous\n execution authority.\n- **Background keeper lock handoff**: an owner that durably publishes its exact\n release marker treats the marker as the logical handoff even when another\n contender wins physical cleanup. Wrong, corrupt, or active foreign claimants\n remain rejected, and POSIX/Windows process identity and cleanup races retain\n bounded fail-closed handling.\n- **Scheduler campaign continuity**: scheduled long-soak dispatches use a pinned\n campaign identity, refuse overlapping segments, and can auto-finalize only\n after the required cross-platform evidence window is complete.\n- **Cross-platform release stability**: generated command help stays in sync;\n POSIX fsync-failure fixtures match the actual read mode; registry cache tests\n follow immutable URL-plus-digest semantics; and macOS marketplace replay uses\n isolated local scope instead of leaking state through the runner user home.\n- **Release status**: immutable tag, final source SHA, workflow run IDs, npm\n provenance, package digests, and registry readback remain intentionally\n absent until the final `0.165.2` merge SHA passes complete `CLI CI` and\n `CLI Strict Sandbox` matrices on Linux, Windows, and macOS, followed by the\n dedicated npm release and independent public readback workflows. The active\n two-hour Keeper/reliability runs and the 72-hour scheduler campaign are not\n claimed as completed release evidence here."
65
+ "body": "> `chainlesschain` **0.165.1 → 0.165.2** (published from exact SHA\n> `775d5667bc7bdcf8fed3f834d3ba2eda43526128`, 2026-08-18).\n> CLI-only release; `@chainlesschain/personal-data-hub` remains **0.4.58**\n> and `@chainlesschain/agent-sdk` remains **0.1.7**.\n\n- **Governed plugin transactions and provenance**: marketplace payload,\n activation, install, update, transaction recovery, and provenance decisions\n bind immutable source identities and digests. Registry cache entries are\n content-addressed, while corrupt, stale, or mismatched recovery evidence\n continues to fail closed.\n- **Strict plugin execution boundaries**: the remaining live plugin fixtures\n now execute in the strict Linux sandbox, MCP security soak provisions its\n required Bubblewrap boundary explicitly, and release fixtures exercise the\n production activation path instead of accepting inactive coverage.\n- **Durable workflow authority**: provider requests and settlements, nested and\n parallel tool effects, child and descendant calls, and timeout outcomes gain\n durable identity-bound receipts so retries cannot silently reuse ambiguous\n execution authority.\n- **Background keeper lock handoff**: an owner that durably publishes its exact\n release marker treats the marker as the logical handoff even when another\n contender wins physical cleanup. Wrong, corrupt, or active foreign claimants\n remain rejected, and POSIX/Windows process identity and cleanup races retain\n bounded fail-closed handling.\n- **Scheduler campaign continuity**: scheduled long-soak dispatches use a pinned\n campaign identity, refuse overlapping segments, and can auto-finalize only\n after the required cross-platform evidence window is complete.\n- **Cross-platform release stability**: generated command help stays in sync;\n POSIX fsync-failure fixtures match the actual read mode; registry cache tests\n follow immutable URL-plus-digest semantics; and macOS marketplace replay uses\n isolated local scope instead of leaking state through the runner user home.\n- **Release status**: immutable tag `v-npm-0-165-2` and the public npm package\n bind exact SHA `775d5667bc`. Its `CLI CI` (`32110231013`),\n `CLI Strict Sandbox` (`32110230842`), and npm release (`32114134884`) passed.\n Later releases supersede it; the 72-hour scheduler campaign and signed native\n distribution remain separate evidence boundaries."
40
66
  }
41
67
  ]
42
68
  },
@@ -76,6 +76,61 @@ async function executeWithIdempotency(server, id, ws, message, stream) {
76
76
  return outcome;
77
77
  }
78
78
 
79
+ /**
80
+ * Persist a schema-declared secret received over the authenticated WS
81
+ * connection without ever placing it in a CLI command string or process argv.
82
+ *
83
+ * `server._setSecretConfigValue` is an injection seam for focused protocol
84
+ * tests. Production servers lazily load the same config manager used by
85
+ * `cc config set-secret`, so desktop web-shell and standalone `cc ui` share
86
+ * one storage implementation.
87
+ */
88
+ export async function handleConfigSetSecret(server, id, ws, message) {
89
+ const key = message?.key;
90
+ const value = message?.value;
91
+
92
+ if (typeof key !== "string" || !key) {
93
+ server._send(ws, {
94
+ id,
95
+ type: "error",
96
+ code: "CONFIG_SECRET_INVALID_KEY",
97
+ message: "A schema-declared secret key is required",
98
+ });
99
+ return;
100
+ }
101
+ if (typeof value !== "string" || value.length === 0) {
102
+ server._send(ws, {
103
+ id,
104
+ type: "error",
105
+ code: "CONFIG_SECRET_EMPTY",
106
+ message: "Secret input was empty; configuration was not changed",
107
+ });
108
+ return;
109
+ }
110
+
111
+ try {
112
+ const setSecretConfigValue =
113
+ server._setSecretConfigValue ||
114
+ (await import("../../lib/config-manager.js")).setSecretConfigValue;
115
+ const result = setSecretConfigValue(key, value, { storage: "auto" });
116
+ server._send(ws, {
117
+ id,
118
+ type: "config-set-secret-result",
119
+ success: true,
120
+ key,
121
+ storage: result.storage,
122
+ backend: result.backend ?? null,
123
+ });
124
+ } catch (error) {
125
+ server._send(ws, {
126
+ id,
127
+ type: "error",
128
+ code: error?.code || "CONFIG_SECRET_WRITE_FAILED",
129
+ message: error?.message || "Could not save configuration secret",
130
+ });
131
+ }
132
+ }
133
+
79
134
  export function createWsMessageDispatcher(server) {
80
135
  return {
81
136
  async dispatch(clientId, ws, message) {
@@ -123,6 +178,8 @@ export function createWsMessageDispatcher(server) {
123
178
  "permission-rules-get": () => server._handlePermissionRulesGet(id, ws),
124
179
  "permission-rules-set": () =>
125
180
  server._handlePermissionRulesSet(id, ws, message),
181
+ "config-set-secret": () =>
182
+ handleConfigSetSecret(server, id, ws, message),
126
183
  "slash-command": () => server._handleSlashCommand(id, ws, message),
127
184
  "session-answer": () => server._handleSessionAnswer(id, ws, message),
128
185
  "remote-session-create": () =>