chainlesschain 0.163.3 → 0.163.4

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 (198) hide show
  1. package/package.json +3 -2
  2. package/scripts/command-lifecycle-report.mjs +330 -38
  3. package/src/assets/web-panel/assets/{AIOps-DIY6KxV-.js → AIOps-DB5X7qqV.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-BXH0muPt.js → ActionButton-DxHRtKLk.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-D39w8vmg.js → Analytics-DIH5QrxT.js} +2 -2
  6. package/src/assets/web-panel/assets/{AppLayout-CUU1zvLs.js → AppLayout-uu0oxVz7.js} +4 -4
  7. package/src/assets/web-panel/assets/{Artifacts-D8azHO3T.js → Artifacts-BNSMiW9Y.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-D0tAwXTg.js → Audit-DcAzB4_x.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-C29mhJll.js → BackgroundAgents-ClSsvjIc.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-D6Aa1Gro.js → Backup-BMciY0js.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-B1uoHbPQ.js → BaseInput-Hn3b57Sh.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-Bs4DLOR5.js → Chat-CoSlC53V.js} +5 -5
  13. package/src/assets/web-panel/assets/{ChatBubbleRenderer-DUYIBSle.js → ChatBubbleRenderer-CFevJ3So.js} +1 -1
  14. package/src/assets/web-panel/assets/{Checkbox-CNcBPEa4.js → Checkbox-B4L4Eu4w.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-CIY89763.js → Codegen-C77FgRxF.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-CsPYFmgo.js → Col-BrLtJLH3.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-BBocEge4.js → Community-Be7pXXhA.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-TQ8Ux0Lf.js → Compact-DuGPecjo.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-DfBsZTft.js → Compliance-CzS66mjP.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-Cg-I6FVH.js → Cowork-CEhjCoyK.js} +2 -2
  21. package/src/assets/web-panel/assets/{Cron-DTQzfRTp.js → Cron-D7ir8Vja.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-DGxEKGpR.js → Crosschain-BcXmuLxf.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-DLZ1RDSr.js → DID-Cto1dtBy.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-XneICKNI.js → Dashboard-B7KjgwOX.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-BRU00J1-.js → Dropdown-COMqxijg.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-BzCbJuAy.js → EmailListRenderer-BZrya-nf.js} +1 -1
  27. package/src/assets/web-panel/assets/{FamilyGuardDashboard-D7BRyNBG.js → FamilyGuardDashboard-AmVeMq0J.js} +1 -1
  28. package/src/assets/web-panel/assets/{Federation-D9DeFIhW.js → Federation-kZU8c-27.js} +1 -1
  29. package/src/assets/web-panel/assets/{FormItemContext-6rAtA9Ko.js → FormItemContext-sOV22v2-.js} +1 -1
  30. package/src/assets/web-panel/assets/{GenericCardRenderer-8Hqy80pU.js → GenericCardRenderer-BUuLtGCz.js} +1 -1
  31. package/src/assets/web-panel/assets/{Git-Cmvkj1rt.js → Git-K-ZxsLsH.js} +2 -2
  32. package/src/assets/web-panel/assets/{Governance-BRiQUjjw.js → Governance-D3OEnawI.js} +1 -1
  33. package/src/assets/web-panel/assets/{Inference-CKN_EzVf.js → Inference-Bll0gRmP.js} +1 -1
  34. package/src/assets/web-panel/assets/{KnowledgeGraph-BCDHwpwQ.js → KnowledgeGraph-DBXwjr53.js} +1 -1
  35. package/src/assets/web-panel/assets/{Logs-DK9ovhaB.js → Logs-CEzPwEfP.js} +2 -2
  36. package/src/assets/web-panel/assets/MarkdownRenderer-CLmCbHx6.js +1 -0
  37. package/src/assets/web-panel/assets/{Marketplace-BILPGakp.js → Marketplace-BYyRyOPz.js} +1 -1
  38. package/src/assets/web-panel/assets/{McpTools-DTVCOr9-.js → McpTools-DVu8w_rM.js} +3 -3
  39. package/src/assets/web-panel/assets/{Memory-Hzc1iow4.js → Memory-tenuZ_hO.js} +2 -2
  40. package/src/assets/web-panel/assets/{MobileBridge-GXfgnGYV.js → MobileBridge-Bxgy4ozS.js} +1 -1
  41. package/src/assets/web-panel/assets/{MobileProjects-B-3TJWsS.js → MobileProjects-Dgx1D6sc.js} +1 -1
  42. package/src/assets/web-panel/assets/{Mtc-DwSJMWtK.js → Mtc-CRfJ8r8j.js} +4 -4
  43. package/src/assets/web-panel/assets/{MtcAudit-D2uxf-DA.js → MtcAudit-BBJq4Aiz.js} +4 -4
  44. package/src/assets/web-panel/assets/{Multisig-DG6kbKK0.js → Multisig-B3ii9lai.js} +3 -3
  45. package/src/assets/web-panel/assets/{NLProgramming-f5p49EDU.js → NLProgramming-FIi-Cubv.js} +1 -1
  46. package/src/assets/web-panel/assets/{Notes-FUgHyzSD.js → Notes-DIq8MPf1.js} +3 -3
  47. package/src/assets/web-panel/assets/{NotificationSettings-DCHGee7e.js → NotificationSettings-BFOD9eGd.js} +1 -1
  48. package/src/assets/web-panel/assets/{OrderTableRenderer-Dm6LlIoa.js → OrderTableRenderer--41u7vre.js} +1 -1
  49. package/src/assets/web-panel/assets/{Organization-BawA7qAg.js → Organization-B_0AWztW.js} +4 -4
  50. package/src/assets/web-panel/assets/{Overflow-D6a5wZU1.js → Overflow-B6I7TuXv.js} +1 -1
  51. package/src/assets/web-panel/assets/{P2P-K8WavwnA.js → P2P-Cdf6qens.js} +2 -2
  52. package/src/assets/web-panel/assets/{PdhVaultBrowser-4JAJYaqx.js → PdhVaultBrowser-B_0FcQJY.js} +3 -3
  53. package/src/assets/web-panel/assets/{Permissions-BDWvi8PD.js → Permissions-6nFBjsQp.js} +3 -3
  54. package/src/assets/web-panel/assets/{PersonalDataHub-DF_K4E9i.js → PersonalDataHub-nQYV7xpn.js} +3 -3
  55. package/src/assets/web-panel/assets/{Pipeline-BYeZlesI.js → Pipeline-CBVod5jm.js} +1 -1
  56. package/src/assets/web-panel/assets/{Privacy-BIHlgnIc.js → Privacy-D52jW1Nt.js} +1 -1
  57. package/src/assets/web-panel/assets/{ProjectInit-Cvf-6B5P.js → ProjectInit-Bdx3BYhf.js} +2 -2
  58. package/src/assets/web-panel/assets/{ProjectSettings-CnwfJrRz.js → ProjectSettings-b7xr4DUa.js} +2 -2
  59. package/src/assets/web-panel/assets/{Projects-b-jPXzF4.js → Projects-DhfifCKx.js} +1 -1
  60. package/src/assets/web-panel/assets/Providers-Dy_PgDMr.js +1 -0
  61. package/src/assets/web-panel/assets/{QrScannerModal-VLf3gAfL.js → QrScannerModal-FQKSmc3e.js} +1 -1
  62. package/src/assets/web-panel/assets/{QuickAsk-B5vGjRiF.js → QuickAsk-CSTrhzcF.js} +1 -1
  63. package/src/assets/web-panel/assets/{Recommend--UW4iYs-.js → Recommend-CxMABOUh.js} +1 -1
  64. package/src/assets/web-panel/assets/{RemoteSession-DMSPcfKR.js → RemoteSession-Cv2T8yRa.js} +2 -2
  65. package/src/assets/web-panel/assets/{Reputation-kQXlEHmj.js → Reputation-CE1k4Vvu.js} +1 -1
  66. package/src/assets/web-panel/assets/{Row-CxGu3pit.js → Row-BNgNcAV_.js} +1 -1
  67. package/src/assets/web-panel/assets/{RssFeed-Bi5lo8MZ.js → RssFeed-5ZiBZ3ph.js} +3 -3
  68. package/src/assets/web-panel/assets/{Search-Cq_H5RTh.js → Search-mDOIF1UV.js} +1 -1
  69. package/src/assets/web-panel/assets/{Security-YFbmkaQS.js → Security-CtuCTC-e.js} +3 -3
  70. package/src/assets/web-panel/assets/{Services-DLOGdaLm.js → Services-DxFO2Zg7.js} +2 -2
  71. package/src/assets/web-panel/assets/{Skeleton-CteIxb3D.js → Skeleton-CKmKkH9y.js} +1 -1
  72. package/src/assets/web-panel/assets/{Skills-CccopaIZ.js → Skills-Bmzl9qkk.js} +1 -1
  73. package/src/assets/web-panel/assets/{Sla-AzfEQKX1.js → Sla-9RqaWHOC.js} +1 -1
  74. package/src/assets/web-panel/assets/{SpeechSettings-ekGo5l77.js → SpeechSettings-CGdzFIYw.js} +1 -1
  75. package/src/assets/web-panel/assets/{SyncSettings-BmZmAgYH.js → SyncSettings-CvNuCeBT.js} +2 -2
  76. package/src/assets/web-panel/assets/{Tasks-D7q3Z4uL.js → Tasks-B_sLdcnw.js} +1 -1
  77. package/src/assets/web-panel/assets/{Templates-CX1Tgeka.js → Templates-D9_YijdK.js} +1 -1
  78. package/src/assets/web-panel/assets/{Tenant-Zc59jF4i.js → Tenant-Cuc7BUSP.js} +1 -1
  79. package/src/assets/web-panel/assets/{Terminal-CXOD7y83.js → Terminal-6VYRnJgd.js} +2 -2
  80. package/src/assets/web-panel/assets/{TimelineRenderer-B1aBHPBo.js → TimelineRenderer-GtK8xd8Y.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tokens-zALlOq_U.js → Tokens-BZ94Lt5W.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trigger-CQfJMXaq.js → Trigger-DEcZgDaX.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trust-BU0RcM-w.js → Trust-CC3z9THe.js} +1 -1
  84. package/src/assets/web-panel/assets/{UkeySign-IFZ3HsbH.js → UkeySign-Cvtw8cV3.js} +1 -1
  85. package/src/assets/web-panel/assets/{VideoEditing-BzslgW0v.js → VideoEditing-CL4e6Bn3.js} +1 -1
  86. package/src/assets/web-panel/assets/{Wallet-BZAcQNS6.js → Wallet-ycEemP27.js} +2 -2
  87. package/src/assets/web-panel/assets/{WebAuthn-CBK1DMi0.js → WebAuthn-DgZ4X_aw.js} +5 -5
  88. package/src/assets/web-panel/assets/{WorkflowEditor-BlMTPzO-.js → WorkflowEditor-D0qMhSv7.js} +1 -1
  89. package/src/assets/web-panel/assets/{chat-B51-8QVn.js → chat-DsAg01Zn.js} +1 -1
  90. package/src/assets/web-panel/assets/{colors-504RTByU.js → colors-B0oqAhrQ.js} +1 -1
  91. package/src/assets/web-panel/assets/{compact-item-C-GP6IQM.js → compact-item-CmX0Rabz.js} +1 -1
  92. package/src/assets/web-panel/assets/{createContext-DOkIj7ID.js → createContext-Be4cn1Ub.js} +1 -1
  93. package/src/assets/web-panel/assets/devWarning-CP2qzG6D.js +1 -0
  94. package/src/assets/web-panel/assets/{hasIn-DN7V-_FW.js → hasIn-D5v12kVq.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-kt_5rfcZ.js → index-0eWLkQKT.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-CUhQpiYv.js → index-301ogenv.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-f4Bo4KXm.js → index-5LGY0JbG.js} +1 -1
  98. package/src/assets/web-panel/assets/{index--n-ZciV3.js → index-7VKDn-t1.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-D1phyca8.js → index-8WvYGnON.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-7jIqHbzw.js → index-B1YGjOWC.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-DEMPUVa3.js → index-B3mUHuVc.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-Bkxhaeta.js → index-BA4oulaP.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-CYopNjcJ.js → index-BBREnn1V.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-P2mfY27Z.js → index-BBvyHguy.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-DA2f1UV3.js → index-BKmsS2jj.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-CP2A226L.js → index-BRIqLy1m.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-CfiEM64n.js → index-BXGSbelg.js} +3 -3
  108. package/src/assets/web-panel/assets/{index-B2-x9bS8.js → index-BaE0Ui07.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-CySTJKeq.js → index-BoAIAZ5C.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-kAqQXfP6.js → index-BqltWojQ.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-DAOpQvl_.js → index-CGiIyTZw.js} +1 -1
  112. package/src/assets/web-panel/assets/index-CKB0vbJU.js +1 -0
  113. package/src/assets/web-panel/assets/{index-C4DV_5uA.js → index-CZ2wUEgr.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-yYTQZypF.js → index-CZpfzcuy.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-et5JIPHO.js → index-Ckrk3pIV.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-DaA__-q1.js → index-CqoCZ5vR.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-By6u5IV1.js → index-CyWBir7N.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CKTfZyfU.js → index-CyyGTMKd.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-B_vGU-Js.js → index-D0BSkxYQ.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-Cao5DZy7.js → index-D5YVopyr.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-C3TSohzc.js → index-DKUBj36_.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-BFIFJ5Dr.js → index-DM724NgU.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-ConjaJro.js → index-DQRsQen0.js} +1 -1
  124. package/src/assets/web-panel/assets/index-DgoXmwqB.js +1 -0
  125. package/src/assets/web-panel/assets/{index-C9_48OzU.js → index-DikJ0Qqe.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-C0k_Nqg9.js → index-Dn2dSdXx.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-DE-hmI2l.js → index-DyUaFWEk.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-so8eIIxF.js → index-Hfe_dEGx.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-FcV8J_Qz.js → index-_JjRLSD0.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-D9LyiN-L.js → index-frSojpHj.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-CX78k-qf.js → index-jK3ax6Z6.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-C8UltbXK.js → index-qMuZ-NRR.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-CqcLo5WV.js → index-q_fQ94SE.js} +1 -1
  134. package/src/assets/web-panel/assets/{initDefaultProps-CPYEIdpV.js → initDefaultProps-D4VdhJ9_.js} +1 -1
  135. package/src/assets/web-panel/assets/{motion-Cjim9pxs.js → motion-CZJA0MQW.js} +1 -1
  136. package/src/assets/web-panel/assets/{move-DuU-cgz3.js → move-BqEs7Sb1.js} +1 -1
  137. package/src/assets/web-panel/assets/{mtc-parser-DJHNAkta.js → mtc-parser-BpHEtsu1.js} +1 -1
  138. package/src/assets/web-panel/assets/{omit-DSQBgdBj.js → omit-BW94tY9W.js} +1 -1
  139. package/src/assets/web-panel/assets/{pickAttrs-CTmT_j5m.js → pickAttrs-BnBjPWP9.js} +1 -1
  140. package/src/assets/web-panel/assets/{placementArrow-Lfm6v-r4.js → placementArrow-uUkjQ_hu.js} +1 -1
  141. package/src/assets/web-panel/assets/{responsiveObserve-CgrcPcDi.js → responsiveObserve-B-klUqXK.js} +1 -1
  142. package/src/assets/web-panel/assets/{slide-CuE3110i.js → slide-CvY1cNAs.js} +1 -1
  143. package/src/assets/web-panel/assets/{statusUtils-DiK5nbpf.js → statusUtils-Ix5sEDT2.js} +1 -1
  144. package/src/assets/web-panel/assets/{styleChecker-DPEJdQaZ.js → styleChecker-C8qcXOne.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFlexGapSupport-CnnodGmp.js → useFlexGapSupport-KNF6Kj8f.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFs-DWF84Yav.js → useFs-DGJr345n.js} +1 -1
  147. package/src/assets/web-panel/assets/{usePersonalDataHub-a5b5Dw2f.js → usePersonalDataHub-BboN99rI.js} +1 -1
  148. package/src/assets/web-panel/assets/{vnode-DAluzXOq.js → vnode-Bgt8Vgte.js} +1 -1
  149. package/src/assets/web-panel/assets/{zoom-Dokg7uAZ.js → zoom-BhJtErgt.js} +1 -1
  150. package/src/assets/web-panel/index.html +1 -1
  151. package/src/command-help-index.json +1 -1
  152. package/src/commands/artifacts.js +98 -0
  153. package/src/commands/mcp.js +1 -1
  154. package/src/commands/review.js +221 -22
  155. package/src/commands/session-mcp-recovery.js +5 -5
  156. package/src/data/changelog.json +14 -1
  157. package/src/gateways/ws/ws-agent-handler.js +492 -14
  158. package/src/harness/jsonl-session-store.js +39 -1
  159. package/src/harness/mcp-client.js +172 -29
  160. package/src/harness/prompt-compressor.js +24 -0
  161. package/src/harness/provider-backed-compaction.js +205 -0
  162. package/src/lib/app-preview.js +3 -0
  163. package/src/lib/command-lifecycle-report.js +1340 -145
  164. package/src/lib/delivery-coordinator.js +30 -5
  165. package/src/lib/delivery-production-adapter.js +1777 -0
  166. package/src/lib/delivery-production-runner.js +240 -0
  167. package/src/lib/durable-security-store.js +29 -17
  168. package/src/lib/execution-trace/trace-context.cjs +179 -0
  169. package/src/lib/execution-trace/trace-context.js +8 -175
  170. package/src/lib/mcp-call-ledger-store.js +58 -6
  171. package/src/lib/mcp-host-recovery-runtime.js +2 -0
  172. package/src/lib/mcp-ledger-recovery-admission.js +39 -3
  173. package/src/lib/mcp-recovery-adjudication.js +256 -19
  174. package/src/lib/mcp-sandbox-policy.js +29 -0
  175. package/src/lib/mcp-stdio-capsule-builder-worker.cjs +495 -0
  176. package/src/lib/mcp-stdio-executable-identity.js +33 -2
  177. package/src/lib/mcp-stdio-immutable-vfs-resolver.cjs +830 -0
  178. package/src/lib/mcp-stdio-package-materialization.js +721 -333
  179. package/src/lib/observability/index.js +2 -0
  180. package/src/lib/observability/otlp-exporter.js +2 -2
  181. package/src/lib/packer/pack-update-applier.js +8 -1
  182. package/src/lib/packer/pkg-config-generator.js +34 -0
  183. package/src/lib/process-execution-broker/index.js +34 -5
  184. package/src/lib/process-execution-broker/platform-sandbox.js +82 -1
  185. package/src/lib/scheduler-kernel/contract.js +315 -0
  186. package/src/lib/scheduler-kernel/store.js +1345 -0
  187. package/src/lib/session-host-lease.js +403 -30
  188. package/src/lib/session-persistence-failure.js +4 -1
  189. package/src/lib/sub-agent-context.js +8 -0
  190. package/src/repl/agent-repl.js +285 -38
  191. package/src/runtime/agent-core.js +1044 -90
  192. package/src/runtime/headless-runner.js +260 -166
  193. package/src/runtime/headless-stream.js +254 -25
  194. package/src/assets/web-panel/assets/MarkdownRenderer-D53pHiHy.js +0 -1
  195. package/src/assets/web-panel/assets/Providers-CxC7JuYv.js +0 -1
  196. package/src/assets/web-panel/assets/devWarning-kB0nCNwN.js +0 -1
  197. package/src/assets/web-panel/assets/index-Bya64sZE.js +0 -1
  198. package/src/assets/web-panel/assets/index-D_FWpDZM.js +0 -1
@@ -1,6 +1,19 @@
1
1
  {
2
2
  "source": "CHANGELOG.md",
3
3
  "releases": [
4
+ {
5
+ "productVersion": null,
6
+ "cliVersion": "0.163.4",
7
+ "cliVersions": ["0.163.3", "0.163.4"],
8
+ "date": "2026-08-11",
9
+ "title": "",
10
+ "sections": [
11
+ {
12
+ "heading": "Added — cc CLI 0.163.4: immutable MCP capsules and durable scheduler storage",
13
+ "body": "> `chainlesschain` **0.163.3 → 0.163.4** (candidate; not yet published,\n> 2026-08-11).\n> CLI-only candidate; `@chainlesschain/personal-data-hub` remains **0.4.57**\n> and `@chainlesschain/agent-sdk` remains **0.1.7**.\n\n- **Immutable MCP capsule build inputs**: the capsule builder now executes in a\n bounded worker against an in-memory WASM virtual filesystem populated from\n verified bytes. Package sources and native builder assets are canonicalized,\n identity-bound, and no longer reopened from mutable host paths during the\n build.\n- **Platform-bound live capsule evidence**: materialized stdio MCP capsules are\n exercised through the production Process Broker and child contract on Linux,\n Windows, and macOS. Framed reports, exact asset identity, deferred host-path\n resolution, and shared CJS/ESM trace context prevent warning or path-alias\n drift from weakening the evidence chain.\n- **Bounded failure behavior**: worker memory, output, timeout, and cleanup are\n bounded; partial or malformed child evidence, post-verification replacement,\n unapproved effects, and unsupported strict boundaries fail closed.\n- **Command lifecycle evidence and alias decision**: report v2 binds exact\n coverage, approval, scope, and repository evidence and summarizes command\n telemetry without silently accepting zero-data input. All 25 deprecated\n aliases remain retained until representative opt-in telemetry exists and the\n documented `0.164.0` removal floor is reached.\n- **Scheduler kernel storage foundation**: a versioned SQLite store adds strict\n schema verification, expected-revision CAS, logical-occurrence deduplication,\n durable claims, and two-handle race coverage. This is the first P2-4 storage\n milestone, not completion of the scheduling kernel or orchestration runtime.\n- **Delivery and recovery hardening**: production delivery adapters, durable\n provider-backed compaction, MCP recovery admission, session ownership fences,\n and exact Windows write checks close additional internal consistency gaps.\n- **Native release readback hardening**: release evidence now verifies public\n bytes, checksums, manifests, signatures, and provenance contracts more\n strictly. Signed native distribution is still blocked until real signed\n artifacts and public package-manager readback are available.\n- **Known residuals**: full P2-4 scheduling orchestration, signed native\n distribution, representative alias telemetry, and the remaining documented\n long-soak/host-boundary follow-ups are not claimed by this release.\n- **Release status**: final tag, exact source SHA, workflow run IDs, package\n digest, provenance, and public registry readback are intentionally omitted\n until the exact `0.163.4` release commit passes the Linux, Windows, and macOS\n `CLI CI` and `CLI Strict Sandbox` gates and the npm release/readback workflows\n complete successfully."
14
+ }
15
+ ]
16
+ },
4
17
  {
5
18
  "productVersion": null,
6
19
  "cliVersion": "0.163.3",
@@ -10,7 +23,7 @@
10
23
  "sections": [
11
24
  {
12
25
  "heading": "Added — cc CLI 0.163.3: isolated background agents and policy-bound runtimes",
13
- "body": "> `chainlesschain` **0.163.2 → 0.163.3** (candidate; not yet published,\n> 2026-08-10).\n> CLI-only candidate; `@chainlesschain/personal-data-hub` remains **0.4.57**\n> and `@chainlesschain/agent-sdk` remains **0.1.7**.\n\n- **Git background isolation by default**: `cc agent --bg` runs started from a\n clean Git checkout and not using `--input-format stream-json` now create a\n worktree at committed `HEAD`; `--worktree` requests the same path and only\n `--no-worktree` opts into the shared checkout. Foreground runs, runs using\n `--input-format stream-json`, and non-Git runs retain their prior behavior,\n while a dirty Git source is rejected instead of silently omitting uncommitted\n changes.\n- **Generation- and token-fenced ownership**: locked atomic state, immutable\n worktree/profile identity, worker-generation claims, terminal-absorbing\n updates, durable turn intents, and stop/cleanup fences prevent stale\n cooperative workers from reviving or deleting live work. Versioned,\n secret-free launch profiles preserve compatible resume settings.\n- **Grammar-safe detached arguments**: new background launches preserve option\n values and `--` literals, pass prompts as one `--print=<text>` token,\n canonicalize resume/continue/fork to one session, and remap repository\n `--add-dir` roots into the worktree. Canonical external roots remain shared\n and produce a warning.\n- **Policy-bearing stdio MCP sources**: explicit `--mcp-config`, managed and\n registered local/project/user sources, trusted project configuration, Skill,\n and Cowork definitions propagate normalized `filesystem`/`network`\n requirements plus separately validated working-directory/workspace authority\n to the Process Broker. Unprovable requirements fail closed, and invalid named\n higher-precedence entries do not fall through to a weaker source.\n- **Sealed Linux plugin file sets**: strict direct Plugin Node and supported\n narrow native ELF launches snapshot every pinned regular plugin file into\n sealed anonymous data-bind mounts. Dynamic native evidence covers only\n `PT_INTERP` and direct `DT_NEEDED`; tree attestation remains per-file rather\n than one atomic filesystem snapshot.\n- **Contained Windows adapter artifacts**: helper, cache, and test artifacts use\n an attested non-reparse local temporary root, identity/content rechecks,\n randomized materialization, and bounded retirement. Unknown or unverifiable\n leftovers are preserved and make cleanup fail closed.\n- **Fail-closed CI routing**: the generic selector routes the defined Windows\n helper-support paths to their CLI contract tests, supports multi-suite\n execution, and cannot turn selected-test or primary-run failure into a\n fallback/diagnostic pass. Full-suite workflows provision their required\n dependencies explicitly; this routing does not replace the exact-SHA release\n matrices.\n- **Known residuals**: non-Git, `--input-format stream-json`, `--no-worktree`,\n and external `add-dir` roots are not worktree-isolated. Spawn-to-PID\n hard-crash recovery and long-soak closure remain open; Linux native\n dependency evidence is non-transitive and has no `dlopen` closure; Windows\n path operations are\n re-attested but not handle-atomic. macOS atomic runtime execution, arbitrary\n shared-library closure, remote revocation, signed native distribution, and\n alias telemetry/removal remain out of scope, so this release does not claim\n complete P1-2 closure.\n- **Release status**: final tag, exact source SHA, workflow run IDs, package\n digest, provenance, and public registry readback are intentionally omitted\n until the exact `0.163.3` release commit passes the required Linux, Windows,\n and macOS `CLI CI` and `CLI Strict Sandbox` gates and the npm release/readback\n workflows complete successfully."
26
+ "body": "> `chainlesschain` **0.163.2 → 0.163.3** (published from exact SHA\n> `17fcf6aa7917dd0fcc83b3ab5204c196bbb81758`, 2026-08-10).\n> CLI-only release; `@chainlesschain/personal-data-hub` remains **0.4.57**\n> and `@chainlesschain/agent-sdk` remains **0.1.7**.\n\n- **Git background isolation by default**: `cc agent --bg` runs started from a\n clean Git checkout and not using `--input-format stream-json` now create a\n worktree at committed `HEAD`; `--worktree` requests the same path and only\n `--no-worktree` opts into the shared checkout. Foreground runs, runs using\n `--input-format stream-json`, and non-Git runs retain their prior behavior,\n while a dirty Git source is rejected instead of silently omitting uncommitted\n changes.\n- **Generation- and token-fenced ownership**: locked atomic state, immutable\n worktree/profile identity, worker-generation claims, terminal-absorbing\n updates, durable turn intents, and stop/cleanup fences prevent stale\n cooperative workers from reviving or deleting live work. Versioned,\n secret-free launch profiles preserve compatible resume settings.\n- **Grammar-safe detached arguments**: new background launches preserve option\n values and `--` literals, pass prompts as one `--print=<text>` token,\n canonicalize resume/continue/fork to one session, and remap repository\n `--add-dir` roots into the worktree. Canonical external roots remain shared\n and produce a warning.\n- **Policy-bearing stdio MCP sources**: explicit `--mcp-config`, managed and\n registered local/project/user sources, trusted project configuration, Skill,\n and Cowork definitions propagate normalized `filesystem`/`network`\n requirements plus separately validated working-directory/workspace authority\n to the Process Broker. Unprovable requirements fail closed, and invalid named\n higher-precedence entries do not fall through to a weaker source.\n- **Sealed Linux plugin file sets**: strict direct Plugin Node and supported\n narrow native ELF launches snapshot every pinned regular plugin file into\n sealed anonymous data-bind mounts. Dynamic native evidence covers only\n `PT_INTERP` and direct `DT_NEEDED`; tree attestation remains per-file rather\n than one atomic filesystem snapshot.\n- **Contained Windows adapter artifacts**: helper, cache, and test artifacts use\n an attested non-reparse local temporary root, identity/content rechecks,\n randomized materialization, and bounded retirement. Unknown or unverifiable\n leftovers are preserved and make cleanup fail closed.\n- **Fail-closed CI routing**: the generic selector routes the defined Windows\n helper-support paths to their CLI contract tests, supports multi-suite\n execution, and cannot turn selected-test or primary-run failure into a\n fallback/diagnostic pass. Full-suite workflows provision their required\n dependencies explicitly; this routing does not replace the exact-SHA release\n matrices.\n- **Known residuals**: non-Git, `--input-format stream-json`, `--no-worktree`,\n and external `add-dir` roots are not worktree-isolated. Spawn-to-PID\n hard-crash recovery and long-soak closure remain open; Linux native\n dependency evidence is non-transitive and has no `dlopen` closure; Windows\n path operations are\n re-attested but not handle-atomic. macOS atomic runtime execution, arbitrary\n shared-library closure, remote revocation, signed native distribution, and\n alias telemetry/removal remain out of scope, so this release does not claim\n complete P1-2 closure.\n- **Published release evidence**: immutable tag `v-npm-0-163-3` resolves to\n exact source commit `17fcf6aa7917dd0fcc83b3ab5204c196bbb81758`.\n Its Linux, Windows, and macOS `CLI CI` (`31329476135`) and `CLI Strict\nSandbox` (`31329476020`) matrices passed; the formal two-hour\n reliability/malicious-MCP soak (`31329539092`) completed 7/7 jobs with 300\n host cycles, 900 unapproved effects, 100 Linux races, 100 macOS fail-closed\n probes, and zero escapes. The npm release (`31335579227`) and independent\n public readback (`31336362525`) completed the exact-SHA gate, immutable\n tarball/CycloneDX SBOM, Trusted Publishing, SLSA/Sigstore provenance,\n registry byte comparison, and npmmirror synchronization. The public tarball\n SHA-256 is\n `68396c418029fc314403c9882c92fb9bef5ec6e9a61bb186333209884d410a92`."
14
27
  }
15
28
  ]
16
29
  },
@@ -34,12 +34,17 @@ import {
34
34
  import { createWsApprovalGate } from "./ws-approval-gate.js";
35
35
  import { createSessionMcpLedgerSink } from "../../lib/mcp-call-ledger-store.js";
36
36
  import { createMcpHostRecoveryRuntime } from "../../lib/mcp-host-recovery-runtime.js";
37
+ import { compactConversationWithProvider } from "../../harness/provider-backed-compaction.js";
38
+ import { projectCanonicalResumeMessages } from "../../lib/session-message-provenance.js";
39
+ import { feature } from "../../lib/feature-flags.js";
37
40
  import {
41
+ appendCompactEventIfMessagesMatch,
38
42
  claimWsTurnIfHead,
39
43
  computeWsTurnInputDigest,
40
44
  createWsTurnClaimId,
41
45
  normalizeWsTurnRequestId,
42
46
  readVerifiedWsTurnState,
47
+ readVerifiedMessages,
43
48
  settleWsTurnClaim,
44
49
  } from "../../harness/jsonl-session-store.js";
45
50
 
@@ -78,6 +83,8 @@ export class WSAgentHandler {
78
83
  db,
79
84
  approvalGate,
80
85
  agentLoop: runAgentLoop,
86
+ compactionLlmQuery,
87
+ compactionChatFn,
81
88
  canonicalSessionStore,
82
89
  sessionHostLease = null,
83
90
  }) {
@@ -122,12 +129,22 @@ export class WSAgentHandler {
122
129
  this._mcpRecoveryRevision = null;
123
130
  this._mcpRecoveryClient = null;
124
131
  this._agentLoop = runAgentLoop || agentLoop;
132
+ this._compactionLlmQuery = compactionLlmQuery || null;
133
+ this._compactionSettlementBlock = null;
134
+ this._compactionChatFn =
135
+ compactionChatFn ||
136
+ (async (...args) => {
137
+ const { chatWithTools } = await import("../../runtime/agent-core.js");
138
+ return chatWithTools(...args);
139
+ });
125
140
  this._canonicalSessionStore = {
141
+ appendCompactEventIfMessagesMatch,
126
142
  claimWsTurnIfHead,
127
143
  computeWsTurnInputDigest,
128
144
  createWsTurnClaimId,
129
145
  normalizeWsTurnRequestId,
130
146
  readVerifiedWsTurnState,
147
+ readVerifiedMessages,
131
148
  settleWsTurnClaim,
132
149
  ...(canonicalSessionStore || {}),
133
150
  };
@@ -171,9 +188,56 @@ export class WSAgentHandler {
171
188
  return this.session.messages;
172
189
  }
173
190
 
191
+ _latchCompactionSettlement({
192
+ code,
193
+ reason,
194
+ commitState = "unknown",
195
+ usageOutcome = null,
196
+ }) {
197
+ this._compactionSettlementBlock = Object.freeze({
198
+ code: code || "CC_COMPACTION_SETTLEMENT_UNKNOWN",
199
+ reason: reason || "canonical_compaction_settlement_failed",
200
+ commitState,
201
+ ...(usageOutcome ? { usageOutcome } : {}),
202
+ });
203
+ return this._compactionSettlementBlock;
204
+ }
205
+
206
+ _reconcileCompactionSettlementBlock() {
207
+ if (
208
+ this._compactionSettlementBlock?.commitState !== "provider-usage-unknown"
209
+ ) {
210
+ this._compactionSettlementBlock = null;
211
+ }
212
+ }
213
+
214
+ _emitCompactionUsage(requestId, usageEvent) {
215
+ if (!usageEvent) return;
216
+ this.interaction.emit("token-usage", {
217
+ requestId,
218
+ ...usageEvent,
219
+ });
220
+ }
221
+
222
+ _emitCompactionUsageUnknown(requestId, usageUnknownEvent) {
223
+ const block = this._latchCompactionSettlement({
224
+ code: "CC_COMPACTION_USAGE_UNKNOWN",
225
+ reason: usageUnknownEvent?.reason || "provider_transport_outcome_unknown",
226
+ commitState: "provider-usage-unknown",
227
+ usageOutcome: "unknown",
228
+ });
229
+ this.interaction.emit("compaction-usage-unknown", {
230
+ requestId,
231
+ ...usageUnknownEvent,
232
+ code: block.code,
233
+ });
234
+ return block;
235
+ }
236
+
174
237
  _canonicalTurnFromAuthority(state, requestId, userMessage, inputDigest) {
175
238
  const status = state?.status || (state?.turn ? "completed" : "none");
176
239
  this._applyCanonicalMessages(state?.messages || []);
240
+ this._reconcileCompactionSettlementBlock();
177
241
  if (status === "completed" && state.turn) {
178
242
  return {
179
243
  requestId,
@@ -210,6 +274,193 @@ export class WSAgentHandler {
210
274
  return null;
211
275
  }
212
276
 
277
+ async _compactCanonicalHistoryBeforeClaim(requestId) {
278
+ const { session } = this;
279
+ if (
280
+ session.autoCompact === false ||
281
+ !feature("PROMPT_COMPRESSOR") ||
282
+ this._compactionSettlementBlock?.commitState === "provider-usage-unknown"
283
+ ) {
284
+ return true;
285
+ }
286
+
287
+ const before = session.messages.length;
288
+ const expectedMessages = [...session.messages];
289
+ let result;
290
+ try {
291
+ this._sessionHostLease?.assert?.();
292
+ result = await compactConversationWithProvider(session.messages, {
293
+ provider: session.provider,
294
+ model: session.model,
295
+ baseUrl: session.baseUrl,
296
+ apiKey: session.apiKey,
297
+ signal: this._sessionHostLease?.signal,
298
+ onlyIfNeeded: true,
299
+ preserveCompletedExchange: true,
300
+ llmQuery: this._compactionLlmQuery,
301
+ chatFn: this._compactionChatFn,
302
+ chatOptions: {
303
+ cwd: session.projectRoot,
304
+ sessionId: session.id,
305
+ },
306
+ maxMessages: session.compactionMaxMessages,
307
+ maxTokens: session.compactionMaxTokens,
308
+ maxOutputTokens: session.compactionMaxOutputTokens,
309
+ summaryInputMaxChars: session.compactionInputMaxChars,
310
+ });
311
+ this._sessionHostLease?.assert?.();
312
+ } catch (error) {
313
+ if (isAbortError(error) || this._sessionHostLease?.signal?.aborted) {
314
+ throw error;
315
+ }
316
+ const block = this._latchCompactionSettlement({
317
+ code: error?.code || "CC_COMPACTION_FAILED",
318
+ reason: `compaction_failed:${String(error?.message || error).slice(0, 240)}`,
319
+ commitState: "provider-outcome-unknown",
320
+ });
321
+ this.interaction.emit("compaction-degraded", {
322
+ requestId,
323
+ reason: block.reason,
324
+ summaryMode: "none",
325
+ code: block.code,
326
+ });
327
+ this.interaction.emit("error", {
328
+ requestId,
329
+ code: block.code,
330
+ message: "Canonical history could not be compacted before turn claim",
331
+ });
332
+ return false;
333
+ }
334
+
335
+ const {
336
+ messages: compacted,
337
+ stats,
338
+ degradedEvent,
339
+ usageEvent,
340
+ usageUnknownEvent,
341
+ } = result;
342
+ if (degradedEvent) {
343
+ this.interaction.emit("compaction-degraded", {
344
+ requestId,
345
+ ...degradedEvent,
346
+ });
347
+ }
348
+ if (usageUnknownEvent) {
349
+ const block = this._emitCompactionUsageUnknown(
350
+ requestId,
351
+ usageUnknownEvent,
352
+ );
353
+ this.interaction.emit("error", {
354
+ requestId,
355
+ code: block.code,
356
+ message:
357
+ "Compaction provider usage is unknown; the paid compaction is not retried",
358
+ });
359
+ return false;
360
+ }
361
+
362
+ const messagesChanged =
363
+ session.messages.length !== expectedMessages.length ||
364
+ session.messages.some(
365
+ (message, index) => message !== expectedMessages[index],
366
+ );
367
+ const shouldSettle = stats?.strategy !== "none" && stats?.saved > 0;
368
+ let settlementError = null;
369
+ if (!messagesChanged && shouldSettle) {
370
+ try {
371
+ const settlement =
372
+ this._canonicalSessionStore.appendCompactEventIfMessagesMatch(
373
+ session.id,
374
+ {
375
+ ...stats,
376
+ trigger: "auto",
377
+ messages: projectCanonicalResumeMessages(compacted, {
378
+ strict: true,
379
+ }),
380
+ },
381
+ expectedMessages,
382
+ );
383
+ if (settlement && typeof settlement.then === "function") {
384
+ void Promise.resolve(settlement).catch(() => {});
385
+ const error = new TypeError(
386
+ "Canonical compact settlement must be synchronous",
387
+ );
388
+ error.code = "CC_COMPACTION_SETTLEMENT_ASYNC";
389
+ throw error;
390
+ }
391
+ } catch (error) {
392
+ settlementError = error;
393
+ }
394
+ }
395
+
396
+ this._emitCompactionUsage(requestId, usageEvent);
397
+ if (messagesChanged || settlementError) {
398
+ const stale = settlementError?.code === "SESSION_REVISION_STALE";
399
+ let reconciled = false;
400
+ if (stale) {
401
+ try {
402
+ const authoritativeMessages =
403
+ this._canonicalSessionStore.readVerifiedMessages(session.id);
404
+ if (!Array.isArray(authoritativeMessages)) {
405
+ throw new TypeError(
406
+ "Canonical message refresh must be synchronous",
407
+ );
408
+ }
409
+ this._applyCanonicalMessages(authoritativeMessages);
410
+ this._reconcileCompactionSettlementBlock();
411
+ reconciled = true;
412
+ } catch {
413
+ // Latch below until a later verified canonical refresh succeeds.
414
+ }
415
+ }
416
+ const block =
417
+ reconciled && stale
418
+ ? {
419
+ code: "CC_COMPACTION_REVISION_STALE",
420
+ reason: "session_messages_changed_during_compaction",
421
+ commitState: "reconciled-stale",
422
+ }
423
+ : this._latchCompactionSettlement({
424
+ code:
425
+ settlementError?.code ||
426
+ (messagesChanged
427
+ ? "CC_COMPACTION_LOCAL_STATE_CHANGED"
428
+ : "CC_COMPACTION_SETTLEMENT_UNKNOWN"),
429
+ reason:
430
+ messagesChanged || stale
431
+ ? "session_messages_changed_during_compaction"
432
+ : "canonical_compaction_settlement_failed",
433
+ commitState: "unknown",
434
+ });
435
+ this.interaction.emit("compaction-degraded", {
436
+ requestId,
437
+ reason: block.reason,
438
+ summaryMode: "none",
439
+ code: block.code,
440
+ });
441
+ this.interaction.emit("error", {
442
+ requestId,
443
+ code: block.code,
444
+ message:
445
+ "Canonical compaction did not settle; the paid compaction is not retried",
446
+ });
447
+ return false;
448
+ }
449
+
450
+ if (shouldSettle) {
451
+ session.messages.length = 0;
452
+ session.messages.push(...compacted);
453
+ this.interaction.emit("compaction", {
454
+ requestId,
455
+ stats,
456
+ trigger: "auto",
457
+ messagesBefore: before,
458
+ messagesAfter: session.messages.length,
459
+ });
460
+ }
461
+ return true;
462
+ }
463
+
213
464
  _claimCanonicalTurn(userMessage, requestId) {
214
465
  const inputDigest =
215
466
  this._canonicalSessionStore.computeWsTurnInputDigest(userMessage);
@@ -396,6 +647,7 @@ export class WSAgentHandler {
396
647
  sink: this._mcpRecoverySink,
397
648
  recovery: session.mcpLedgerRecovery || null,
398
649
  controller,
650
+ dispatchAdmission: this._sessionHostLease?.admitMcpDispatch || null,
399
651
  });
400
652
  this._mcpRecoveryClient = rawClient;
401
653
  this._mcpRecoveryRevision = revision;
@@ -509,7 +761,26 @@ export class WSAgentHandler {
509
761
  this._sessionHostLease?.assert?.();
510
762
 
511
763
  if (session.canonicalJsonlSession === true) {
512
- canonicalTurn = this._claimCanonicalTurn(userMessage, requestId);
764
+ const inputDigest =
765
+ this._canonicalSessionStore.computeWsTurnInputDigest(userMessage);
766
+ const preflightState =
767
+ this._canonicalSessionStore.readVerifiedWsTurnState(
768
+ session.id,
769
+ requestId,
770
+ { inputDigest },
771
+ );
772
+ canonicalTurn = this._canonicalTurnFromAuthority(
773
+ preflightState,
774
+ requestId,
775
+ userMessage,
776
+ inputDigest,
777
+ );
778
+ if (!canonicalTurn) {
779
+ const compacted =
780
+ await this._compactCanonicalHistoryBeforeClaim(requestId);
781
+ if (!compacted) return;
782
+ }
783
+ canonicalTurn ||= this._claimCanonicalTurn(userMessage, requestId);
513
784
  if (canonicalTurn.status === "completed") {
514
785
  this.interaction.emit("response-complete", {
515
786
  requestId,
@@ -601,6 +872,7 @@ export class WSAgentHandler {
601
872
  // headless and REPL sessions. For unknown/write/destructive effects a
602
873
  // failed prewrite blocks the network call inside agent-core.
603
874
  mcpCallLedger: mcpRecoveryRuntime.ledger,
875
+ mcpDispatchAdmission: this._sessionHostLease?.admitMcpDispatch || null,
604
876
  shellPolicyOverrides: session.shellPolicyOverrides || null,
605
877
  slotFiller,
606
878
  interaction: this.interaction,
@@ -608,6 +880,12 @@ export class WSAgentHandler {
608
880
  // P0 authority: null unless opted in (byte-identical default — agent
609
881
  // core already defaults `options.approvalGate || null`).
610
882
  approvalGate: await this._ensureApprovalGate(),
883
+ // Canonical WS history is compacted before ws_turn_prepare. Compaction
884
+ // inside agent-core would include the staged pending user, which is not
885
+ // part of the canonical message projection until turn settlement.
886
+ ...(session.canonicalJsonlSession === true
887
+ ? { autoCompact: false }
888
+ : {}),
611
889
  };
612
890
 
613
891
  // P0-2: crash-safe side-effect ledger for the IDE/bridge path — mirrors
@@ -718,6 +996,37 @@ export class WSAgentHandler {
718
996
  }
719
997
  break;
720
998
 
999
+ case "compaction-degraded":
1000
+ this.interaction.emit("compaction-degraded", {
1001
+ requestId,
1002
+ reason: event.reason,
1003
+ summaryMode: event.summaryMode,
1004
+ ...(event.code ? { code: event.code } : {}),
1005
+ stats: event.stats,
1006
+ });
1007
+ break;
1008
+
1009
+ case "compaction-usage-unknown":
1010
+ this._emitCompactionUsageUnknown(requestId, event);
1011
+ break;
1012
+
1013
+ case "compaction":
1014
+ this.interaction.emit("compaction", {
1015
+ requestId,
1016
+ stats: event.stats,
1017
+ });
1018
+ break;
1019
+
1020
+ case "token-usage":
1021
+ this.interaction.emit("token-usage", {
1022
+ requestId,
1023
+ provider: event.provider,
1024
+ model: event.model,
1025
+ usage: event.usage,
1026
+ ...(event.source ? { source: event.source } : {}),
1027
+ });
1028
+ break;
1029
+
721
1030
  case "response-complete":
722
1031
  if (session.canonicalJsonlSession === true) {
723
1032
  const settled = this._settleCanonicalSuccess(
@@ -983,25 +1292,194 @@ export class WSAgentHandler {
983
1292
  });
984
1293
  break;
985
1294
 
986
- case "/compact":
987
- if (session.contextEngine && session.messages.length > 5) {
988
- const compacted = session.contextEngine.smartCompact(
989
- session.messages,
990
- );
991
- session.messages.length = 0;
992
- session.messages.push(...compacted);
993
- } else if (session.messages.length > 5) {
994
- const systemMsg = session.messages[0];
995
- const recent = session.messages.slice(-4);
996
- session.messages.length = 0;
997
- session.messages.push(systemMsg, ...recent);
1295
+ case "/compact": {
1296
+ if (this._compactionSettlementBlock) {
1297
+ const block = this._compactionSettlementBlock;
1298
+ this.interaction.emit("compaction-degraded", {
1299
+ requestId,
1300
+ reason: block.reason,
1301
+ summaryMode: "none",
1302
+ code: block.code,
1303
+ });
1304
+ this.interaction.emit("command-response", {
1305
+ requestId,
1306
+ command: cmd,
1307
+ result: {
1308
+ messageCount: session.messages.length,
1309
+ error: block,
1310
+ },
1311
+ });
1312
+ break;
1313
+ }
1314
+
1315
+ const before = session.messages.length;
1316
+ const expectedMessages = [...session.messages];
1317
+ let result = null;
1318
+ let commandError = null;
1319
+ try {
1320
+ this._sessionHostLease?.assert?.();
1321
+ result = await compactConversationWithProvider(session.messages, {
1322
+ provider: session.provider,
1323
+ model: session.model,
1324
+ baseUrl: session.baseUrl,
1325
+ apiKey: session.apiKey,
1326
+ signal: this._sessionHostLease?.signal,
1327
+ force: true,
1328
+ preserveCompletedExchange: true,
1329
+ llmQuery: this._compactionLlmQuery,
1330
+ chatFn: this._compactionChatFn,
1331
+ chatOptions: {
1332
+ cwd: session.projectRoot,
1333
+ sessionId: session.id,
1334
+ },
1335
+ maxOutputTokens: session.compactionMaxOutputTokens,
1336
+ summaryInputMaxChars: session.compactionInputMaxChars,
1337
+ });
1338
+ this._sessionHostLease?.assert?.();
1339
+ } catch (error) {
1340
+ if (isAbortError(error) || this._sessionHostLease?.signal?.aborted) {
1341
+ throw error;
1342
+ }
1343
+ commandError = this._latchCompactionSettlement({
1344
+ code: error?.code || "CC_COMPACTION_FAILED",
1345
+ reason: `compaction_failed:${String(error?.message || error).slice(0, 240)}`,
1346
+ commitState: "provider-outcome-unknown",
1347
+ });
1348
+ this.interaction.emit("compaction-degraded", {
1349
+ requestId,
1350
+ reason: commandError.reason,
1351
+ summaryMode: "none",
1352
+ code: commandError.code,
1353
+ });
1354
+ }
1355
+ if (result) {
1356
+ const {
1357
+ messages,
1358
+ stats,
1359
+ degradedEvent,
1360
+ usageEvent,
1361
+ usageUnknownEvent,
1362
+ } = result;
1363
+ if (degradedEvent) {
1364
+ this.interaction.emit("compaction-degraded", {
1365
+ requestId,
1366
+ ...degradedEvent,
1367
+ });
1368
+ }
1369
+ if (usageUnknownEvent) {
1370
+ commandError = this._emitCompactionUsageUnknown(
1371
+ requestId,
1372
+ usageUnknownEvent,
1373
+ );
1374
+ }
1375
+ const messagesChanged =
1376
+ session.messages.length !== expectedMessages.length ||
1377
+ session.messages.some(
1378
+ (message, index) => message !== expectedMessages[index],
1379
+ );
1380
+ let settlementError = null;
1381
+ if (
1382
+ !commandError &&
1383
+ !messagesChanged &&
1384
+ session.canonicalJsonlSession === true
1385
+ ) {
1386
+ if (stats?.strategy !== "none") {
1387
+ try {
1388
+ const settlement =
1389
+ this._canonicalSessionStore.appendCompactEventIfMessagesMatch(
1390
+ session.id,
1391
+ {
1392
+ ...stats,
1393
+ trigger: "manual",
1394
+ messages: projectCanonicalResumeMessages(messages, {
1395
+ strict: true,
1396
+ }),
1397
+ },
1398
+ expectedMessages,
1399
+ );
1400
+ if (settlement && typeof settlement.then === "function") {
1401
+ void Promise.resolve(settlement).catch(() => {});
1402
+ const error = new TypeError(
1403
+ "Canonical compact settlement must be synchronous",
1404
+ );
1405
+ error.code = "CC_COMPACTION_SETTLEMENT_ASYNC";
1406
+ throw error;
1407
+ }
1408
+ } catch (error) {
1409
+ settlementError = error;
1410
+ }
1411
+ }
1412
+ }
1413
+
1414
+ if (!commandError && !messagesChanged && !settlementError) {
1415
+ session.messages.length = 0;
1416
+ session.messages.push(...messages);
1417
+ this.interaction.emit("compaction", {
1418
+ requestId,
1419
+ stats,
1420
+ messagesBefore: before,
1421
+ messagesAfter: session.messages.length,
1422
+ });
1423
+ } else if (!commandError) {
1424
+ const stale = settlementError?.code === "SESSION_REVISION_STALE";
1425
+ let reconciled = false;
1426
+ if (stale) {
1427
+ try {
1428
+ const authoritativeMessages =
1429
+ this._canonicalSessionStore.readVerifiedMessages(session.id);
1430
+ if (!Array.isArray(authoritativeMessages)) {
1431
+ throw new TypeError(
1432
+ "Canonical message refresh must be synchronous",
1433
+ );
1434
+ }
1435
+ this._applyCanonicalMessages(authoritativeMessages);
1436
+ this._reconcileCompactionSettlementBlock();
1437
+ reconciled = true;
1438
+ } catch {
1439
+ // Latch below until a later verified canonical refresh.
1440
+ }
1441
+ }
1442
+ commandError =
1443
+ reconciled && stale
1444
+ ? {
1445
+ code: "CC_COMPACTION_REVISION_STALE",
1446
+ reason: "session_messages_changed_during_compaction",
1447
+ commitState: "reconciled-stale",
1448
+ }
1449
+ : this._latchCompactionSettlement({
1450
+ code:
1451
+ settlementError?.code ||
1452
+ (messagesChanged
1453
+ ? "CC_COMPACTION_LOCAL_STATE_CHANGED"
1454
+ : "CC_COMPACTION_SETTLEMENT_UNKNOWN"),
1455
+ reason:
1456
+ messagesChanged || stale
1457
+ ? "session_messages_changed_during_compaction"
1458
+ : "canonical_compaction_settlement_failed",
1459
+ commitState: "unknown",
1460
+ });
1461
+ this.interaction.emit("compaction-degraded", {
1462
+ requestId,
1463
+ reason: commandError.reason,
1464
+ summaryMode: "none",
1465
+ code: commandError.code,
1466
+ });
1467
+ }
1468
+ // Provider usage is emitted exactly once even when the message CAS
1469
+ // rejects the candidate; the paid request already happened and is
1470
+ // never retried by this command.
1471
+ this._emitCompactionUsage(requestId, usageEvent);
998
1472
  }
999
1473
  this.interaction.emit("command-response", {
1000
1474
  requestId,
1001
1475
  command: cmd,
1002
- result: { messageCount: session.messages.length },
1476
+ result: {
1477
+ messageCount: session.messages.length,
1478
+ ...(commandError ? { error: commandError } : {}),
1479
+ },
1003
1480
  });
1004
1481
  break;
1482
+ }
1005
1483
 
1006
1484
  case "/task":
1007
1485
  if (arg === "clear") {