chainlesschain 0.162.197 → 0.162.200

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 (233) hide show
  1. package/bin/chainlesschain.js +14 -6
  2. package/package.json +4 -1
  3. package/scripts/command-lifecycle-report.mjs +94 -0
  4. package/src/assets/web-panel/assets/{AIOps-D3Gu1a5d.js → AIOps-DcQ0bWKy.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-DrwAoKaz.js → ActionButton-GecwfFPt.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-C7Q-gd_3.js → Analytics-CD6iSt9v.js} +3 -3
  7. package/src/assets/web-panel/assets/{AppLayout-DgBtae-n.js → AppLayout-CDEtuEYf.js} +5 -5
  8. package/src/assets/web-panel/assets/{Artifacts-pQ6LcA-W.js → Artifacts-DS3jAjeW.js} +1 -1
  9. package/src/assets/web-panel/assets/{Audit-DK61tocB.js → Audit-CcSJA048.js} +1 -1
  10. package/src/assets/web-panel/assets/{BackgroundAgents-BOKgDFRh.js → BackgroundAgents-DRo9Morb.js} +1 -1
  11. package/src/assets/web-panel/assets/{Backup-Bo9G4vTP.js → Backup-Vw5MrWft.js} +1 -1
  12. package/src/assets/web-panel/assets/{BaseInput-Do_dE9_v.js → BaseInput-DNHIu823.js} +1 -1
  13. package/src/assets/web-panel/assets/{Chat-COVvZzOL.js → Chat-DvAsO8-b.js} +4 -4
  14. package/src/assets/web-panel/assets/ChatBubbleRenderer-9aDuObay.js +1 -0
  15. package/src/assets/web-panel/assets/{Checkbox-Z9MJMolt.js → Checkbox-CKCa7tvn.js} +1 -1
  16. package/src/assets/web-panel/assets/{Codegen-BVzWKVbf.js → Codegen-CIFvZdaT.js} +1 -1
  17. package/src/assets/web-panel/assets/{Col-C8MnYcbT.js → Col-C79yz7bK.js} +1 -1
  18. package/src/assets/web-panel/assets/{Community-DQxqw15l.js → Community-DVvZskLJ.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compact-BAUmrh3y.js → Compact-oaew61hV.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compliance-jPAkQ3zK.js → Compliance-DqA7wmRx.js} +1 -1
  21. package/src/assets/web-panel/assets/{Cowork-BBQyxbh8.js → Cowork-B-qGadxa.js} +3 -3
  22. package/src/assets/web-panel/assets/{Cron-W5koq8Z5.js → Cron-CUlCl4sS.js} +2 -2
  23. package/src/assets/web-panel/assets/{Crosschain-BQhnu5hS.js → Crosschain-CNOlr9DU.js} +1 -1
  24. package/src/assets/web-panel/assets/{DID-DD7PlI18.js → DID-DJqFCT_3.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dashboard-w_ILuwKI.js → Dashboard-CznGpphf.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dropdown-qiDUAyAo.js → Dropdown-_cJw218E.js} +1 -1
  27. package/src/assets/web-panel/assets/{EmailListRenderer-PDeBcI5H.js → EmailListRenderer-Dr-1BZ9C.js} +1 -1
  28. package/src/assets/web-panel/assets/{FamilyGuardDashboard-SuArscRM.js → FamilyGuardDashboard-Dxf4xtSk.js} +1 -1
  29. package/src/assets/web-panel/assets/{Federation-BCovZaUn.js → Federation-DOiG3i_1.js} +1 -1
  30. package/src/assets/web-panel/assets/{FormItemContext-DjlFdVFk.js → FormItemContext-BzbMcFB9.js} +1 -1
  31. package/src/assets/web-panel/assets/{GenericCardRenderer-DoEZ7fcS.js → GenericCardRenderer-VbBrYttP.js} +1 -1
  32. package/src/assets/web-panel/assets/{Git-CV0-6GPI.js → Git-CLG8E6ED.js} +2 -2
  33. package/src/assets/web-panel/assets/{Governance-B_SFN50w.js → Governance-LGJQfk_q.js} +1 -1
  34. package/src/assets/web-panel/assets/{Inference-heI0Eo6k.js → Inference-DlQKx9lF.js} +1 -1
  35. package/src/assets/web-panel/assets/{KnowledgeGraph-Cz5INS5p.js → KnowledgeGraph-DU8vEouV.js} +1 -1
  36. package/src/assets/web-panel/assets/{Logs-BSFxiHkg.js → Logs-FZIQOdln.js} +2 -2
  37. package/src/assets/web-panel/assets/MarkdownRenderer-BJNWIrbw.js +1 -0
  38. package/src/assets/web-panel/assets/{Marketplace-0TWTpE7k.js → Marketplace-C_xd-zZI.js} +1 -1
  39. package/src/assets/web-panel/assets/{McpTools-CV4-wBLm.js → McpTools-q-YktphS.js} +5 -5
  40. package/src/assets/web-panel/assets/{Memory-x5bH5rw5.js → Memory-Cq9OhDin.js} +2 -2
  41. package/src/assets/web-panel/assets/{MobileBridge-DaBmUu9G.js → MobileBridge-B03_R98T.js} +1 -1
  42. package/src/assets/web-panel/assets/MobileProjects-DZrk-qmF.js +1 -0
  43. package/src/assets/web-panel/assets/{Mtc-B_zKEBif.js → Mtc-BidCKW28.js} +5 -5
  44. package/src/assets/web-panel/assets/{MtcAudit-BCfKD2yg.js → MtcAudit-r-iaMVM7.js} +2 -2
  45. package/src/assets/web-panel/assets/{Multisig-DgYfj6c_.js → Multisig-CgTUFvff.js} +3 -3
  46. package/src/assets/web-panel/assets/{NLProgramming-Dz09lFUm.js → NLProgramming-B7NvzfAV.js} +1 -1
  47. package/src/assets/web-panel/assets/{Notes-Cuj6ugBE.js → Notes-80CWNqJI.js} +3 -3
  48. package/src/assets/web-panel/assets/{NotificationSettings-DK2WXjhg.js → NotificationSettings-0H6xdiY3.js} +1 -1
  49. package/src/assets/web-panel/assets/{OrderTableRenderer-D1IAOQoo.js → OrderTableRenderer-CKP4AFWy.js} +1 -1
  50. package/src/assets/web-panel/assets/{Organization-9fqnPvTw.js → Organization-B8sxCV_h.js} +4 -4
  51. package/src/assets/web-panel/assets/{Overflow-n5xHkhow.js → Overflow-CW9JBBhQ.js} +1 -1
  52. package/src/assets/web-panel/assets/{P2P-B5AUWwH-.js → P2P-bdSQV7oZ.js} +2 -2
  53. package/src/assets/web-panel/assets/{PdhVaultBrowser-CoUDV6dy.js → PdhVaultBrowser-DQad42nW.js} +4 -4
  54. package/src/assets/web-panel/assets/{Permissions-DPRmQf_H.js → Permissions-CueexxTR.js} +4 -4
  55. package/src/assets/web-panel/assets/{PersonalDataHub-B37bsbEN.js → PersonalDataHub-fqxflhR8.js} +6 -6
  56. package/src/assets/web-panel/assets/{Pipeline-CCAuPqu9.js → Pipeline-KFwwnIMC.js} +1 -1
  57. package/src/assets/web-panel/assets/{Privacy-B81msZdv.js → Privacy-ClnD9buY.js} +1 -1
  58. package/src/assets/web-panel/assets/{ProjectInit-B-Py2NbF.js → ProjectInit-CZEz6sm3.js} +2 -2
  59. package/src/assets/web-panel/assets/{ProjectSettings-CYsneiRB.js → ProjectSettings-B6NzpmOI.js} +2 -2
  60. package/src/assets/web-panel/assets/{Projects-Y975Mh6R.js → Projects-DYyuwPCs.js} +1 -1
  61. package/src/assets/web-panel/assets/Providers-C3tz_jdh.js +1 -0
  62. package/src/assets/web-panel/assets/{QrScannerModal-Bj_6gJ0l.js → QrScannerModal-BzuOBbqB.js} +1 -1
  63. package/src/assets/web-panel/assets/{QuickAsk-BgpBCMPE.js → QuickAsk-CmNO9qSj.js} +1 -1
  64. package/src/assets/web-panel/assets/{Recommend-DhUW3YUA.js → Recommend-VJNj3_NF.js} +1 -1
  65. package/src/assets/web-panel/assets/{RemoteSession-DdeyfbkA.js → RemoteSession-CrbdbSBF.js} +2 -2
  66. package/src/assets/web-panel/assets/{Reputation-fxW421xd.js → Reputation-DTyMd45j.js} +1 -1
  67. package/src/assets/web-panel/assets/{Row-De73w1og.js → Row-DHrQ-Icz.js} +1 -1
  68. package/src/assets/web-panel/assets/{RssFeed-3US_Q_lj.js → RssFeed-DqWxY9c5.js} +2 -2
  69. package/src/assets/web-panel/assets/{Search-DbZ_DU74.js → Search-ctF1Ks3J.js} +1 -1
  70. package/src/assets/web-panel/assets/{Security-DoIU1vMF.js → Security-BrQz8uo5.js} +4 -4
  71. package/src/assets/web-panel/assets/{Services-DB_RGqpc.js → Services-D4scVFar.js} +2 -2
  72. package/src/assets/web-panel/assets/{Skeleton-DnzLaayC.js → Skeleton-oUScaOjv.js} +1 -1
  73. package/src/assets/web-panel/assets/{Skills-VzVXHENF.js → Skills-CL-y0eLt.js} +1 -1
  74. package/src/assets/web-panel/assets/{Sla-DMfvjCAI.js → Sla-DQExhwXj.js} +1 -1
  75. package/src/assets/web-panel/assets/{SpeechSettings-DQQOYWbF.js → SpeechSettings-iNp_I7kN.js} +1 -1
  76. package/src/assets/web-panel/assets/{SyncSettings-Bmx3FG1P.js → SyncSettings-CTDlMo0A.js} +2 -2
  77. package/src/assets/web-panel/assets/{Tasks-DOQyfb-2.js → Tasks-4kb8l3sc.js} +1 -1
  78. package/src/assets/web-panel/assets/{Templates-D6hTRT7c.js → Templates-BXcL9oXW.js} +1 -1
  79. package/src/assets/web-panel/assets/{Tenant-CTPQZAzs.js → Tenant-DLE8eS0D.js} +1 -1
  80. package/src/assets/web-panel/assets/{Terminal-B7vII3oH.js → Terminal-DGpUZPPK.js} +2 -2
  81. package/src/assets/web-panel/assets/{TimelineRenderer-BkiFJeXV.js → TimelineRenderer-C1pWXGPC.js} +1 -1
  82. package/src/assets/web-panel/assets/{Tokens-BPPdQMNo.js → Tokens-BYfbfqhZ.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trigger-BxG8JAEI.js → Trigger-K9YfLOCw.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trust-DHD7nMpM.js → Trust-Ctkq77Hy.js} +1 -1
  85. package/src/assets/web-panel/assets/{UkeySign-B4BJpU47.js → UkeySign-C6_CSe9J.js} +1 -1
  86. package/src/assets/web-panel/assets/{VideoEditing-CRiGpFx2.js → VideoEditing-Be3rpOWs.js} +1 -1
  87. package/src/assets/web-panel/assets/{Wallet-BSDSNiem.js → Wallet-D0UIplxk.js} +4 -4
  88. package/src/assets/web-panel/assets/{WebAuthn-DLTUh5Zv.js → WebAuthn-CF9bM9I3.js} +5 -5
  89. package/src/assets/web-panel/assets/{WorkflowEditor-tW2MwjhD.js → WorkflowEditor-D0H1XVPY.js} +1 -1
  90. package/src/assets/web-panel/assets/{chat-SgsLQ3FC.js → chat-Cgzzbe0o.js} +1 -1
  91. package/src/assets/web-panel/assets/{colors-BHjjLIKO.js → colors-BwNxEVS0.js} +1 -1
  92. package/src/assets/web-panel/assets/{compact-item-VceErdKq.js → compact-item-D60Z4Hhs.js} +1 -1
  93. package/src/assets/web-panel/assets/{createContext-BZ332MYl.js → createContext-MFk58XB0.js} +1 -1
  94. package/src/assets/web-panel/assets/devWarning-BJiw369i.js +1 -0
  95. package/src/assets/web-panel/assets/{hasIn-CBTjJOjn.js → hasIn-CRj2SvGO.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-DaCCy6lq.js → index--s45_1cb.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-CMVvxIS8.js → index--tquQ2ZG.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-BhXZEUAc.js → index-1T1rhokn.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BQSmZGgs.js → index-B-M82_rx.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BeiqkxJG.js → index-BE_el1Zs.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-29wVzi-k.js → index-BhRkR7IO.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-iYQNU9za.js → index-Bo0y96-K.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BRWhLbWF.js → index-CJgu5JUK.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-BPXFLYdW.js → index-CLWwdebO.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-Cr4rjlW5.js → index-CNAK5QG_.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-CaIS_TNX.js → index-CQjJjPRD.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-1n7xjKDU.js → index-CTDbAfae.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-BETEjuNr.js → index-CVI_9sRK.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-By5jBtkV.js → index-CY14oMQK.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-DgPvuIn2.js → index-CbiTJkZf.js} +1 -1
  111. package/src/assets/web-panel/assets/index-CiMouosn.js +1 -0
  112. package/src/assets/web-panel/assets/{index-CawpdGTW.js → index-CqWpxMqx.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-_PHrIO4O.js → index-CvB8lYUR.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BOtvPdHt.js → index-D51XwtCY.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-CrUgDQkf.js → index-D6HvK_1O.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-BY1wexYG.js → index-D9jVIwLJ.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-C_B9rFQE.js → index-DA4tE98u.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-B5KAGxNo.js → index-DBwOtXw0.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-BC1xuQgX.js → index-DKdNzTIb.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-B2u26AS3.js → index-DRySdmvN.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-DePOeMDM.js → index-DWzyTev7.js} +1 -1
  122. package/src/assets/web-panel/assets/index-DXcKlwy7.js +1 -0
  123. package/src/assets/web-panel/assets/{index-BTlc-Bve.js → index-DYjs7jAP.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-CLc19alH.js → index-DbROzMBp.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-fU7wNHDB.js → index-DhFtk5PR.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-D_SePDWj.js → index-Di2AbMLg.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-vIXOpcjD.js → index-DvmocQsM.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-BcUenmCX.js → index-Dw-o0zEF.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-DUkVN794.js → index-DysPoP38.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-CtjLcCNU.js → index-LX9pJxm_.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-B40dQn0G.js → index-OI_fXWx0.js} +3 -3
  132. package/src/assets/web-panel/assets/{index-FJ3zC9LK.js → index-eDTOX8Xj.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-DdefYBSw.js → index-gWKDsTzF.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-CpumS98o.js → index-q_GDUVAA.js} +1 -1
  135. package/src/assets/web-panel/assets/{initDefaultProps-D1oZNz0D.js → initDefaultProps-C61kZqEd.js} +1 -1
  136. package/src/assets/web-panel/assets/{motion-C8k6doMO.js → motion-DZnT5U1L.js} +1 -1
  137. package/src/assets/web-panel/assets/{move-DJ4qSbYt.js → move-L8wzwbel.js} +1 -1
  138. package/src/assets/web-panel/assets/{mtc-parser-CdpJD85j.js → mtc-parser-DLdYSejc.js} +1 -1
  139. package/src/assets/web-panel/assets/{omit-B0V4slKA.js → omit-D53cbS59.js} +1 -1
  140. package/src/assets/web-panel/assets/{pickAttrs-Di5NiW1F.js → pickAttrs-Bbc5HPtu.js} +1 -1
  141. package/src/assets/web-panel/assets/{placementArrow-B5OMHgEM.js → placementArrow-BkvmO860.js} +1 -1
  142. package/src/assets/web-panel/assets/{responsiveObserve-C6U9IWql.js → responsiveObserve-u2y1ryS1.js} +1 -1
  143. package/src/assets/web-panel/assets/{slide-BMyTH3rN.js → slide-BBqj7svU.js} +1 -1
  144. package/src/assets/web-panel/assets/{statusUtils-C7d6BG7Z.js → statusUtils-GN0mqu2d.js} +1 -1
  145. package/src/assets/web-panel/assets/{styleChecker-CR50QnQy.js → styleChecker-BvwPKoBT.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFlexGapSupport-DBEeoMb8.js → useFlexGapSupport-CCt8tnfY.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFs-3r099cjv.js → useFs-DXAxl2SV.js} +1 -1
  148. package/src/assets/web-panel/assets/{usePersonalDataHub-C5IYNdTK.js → usePersonalDataHub-DihlR2dj.js} +1 -1
  149. package/src/assets/web-panel/assets/{vnode-DmEOLRHf.js → vnode-D7BOX2gi.js} +1 -1
  150. package/src/assets/web-panel/assets/{zoom-DnpUiVCB.js → zoom-CVbO-nL7.js} +1 -1
  151. package/src/assets/web-panel/index.html +1 -1
  152. package/src/command-help-index.json +4 -4
  153. package/src/commands/agent.js +3 -3
  154. package/src/commands/background-session.js +145 -0
  155. package/src/commands/mcp.js +244 -7
  156. package/src/commands/serve.js +1 -1
  157. package/src/commands/session-show.js +129 -0
  158. package/src/commands/session.js +97 -145
  159. package/src/commands/skill.js +87 -50
  160. package/src/data/changelog.json +40 -1
  161. package/src/gateways/ws/session-protocol.js +14 -4
  162. package/src/gateways/ws/ws-agent-handler.js +39 -1
  163. package/src/harness/jsonl-session-store.js +1547 -127
  164. package/src/harness/mcp-client.js +2690 -409
  165. package/src/harness/session-index.js +80 -80
  166. package/src/harness/session-list-index.js +210 -7
  167. package/src/lazy-dispatch.js +76 -8
  168. package/src/lib/abort-utils.js +68 -0
  169. package/src/lib/agent-core.js +1 -59
  170. package/src/lib/background-interaction-journal.js +2 -2
  171. package/src/lib/chat-core.js +24 -6
  172. package/src/lib/command-lifecycle-report.js +516 -0
  173. package/src/lib/cowork-mcp-tools.js +47 -2
  174. package/src/lib/cowork-task-runner.js +11 -3
  175. package/src/lib/doctor-checkup.js +9 -7
  176. package/src/lib/learning/skill-improver.js +21 -2
  177. package/src/lib/mcp-call-ledger-store.js +116 -3
  178. package/src/lib/mcp-call-ledger.js +59 -14
  179. package/src/lib/mcp-client.js +1 -0
  180. package/src/lib/mcp-stdio-environment.js +48 -0
  181. package/src/lib/mcp-stdio-executable-identity.js +1133 -0
  182. package/src/lib/mcp-stdio-execution-authority.js +363 -0
  183. package/src/lib/mcp-stdio-package-materialization.js +1424 -0
  184. package/src/lib/mcp-tool-metadata.js +436 -0
  185. package/src/lib/mcp-tool-result.js +367 -0
  186. package/src/lib/observability/index.js +71 -0
  187. package/src/lib/packer/native-update-state.js +979 -1
  188. package/src/lib/packer/pack-update-applier.js +1050 -125
  189. package/src/lib/packer/pkg-config-generator.js +1 -0
  190. package/src/lib/paths.js +53 -0
  191. package/src/lib/pr-link-ledger.js +8 -27
  192. package/src/lib/pr-link-store.js +26 -0
  193. package/src/lib/process-execution-broker/index.js +192 -35
  194. package/src/lib/process-execution-broker/platform-sandbox.js +291 -24
  195. package/src/lib/process-tree-termination.js +253 -0
  196. package/src/lib/recent-session.js +17 -17
  197. package/src/lib/secure-file-identity.js +47 -0
  198. package/src/lib/secure-fs.js +21 -2
  199. package/src/lib/session-anti-rollback-anchor.js +766 -0
  200. package/src/lib/session-host-lease.js +492 -0
  201. package/src/lib/session-host-snapshot.js +9 -5
  202. package/src/lib/session-persistence-failure.js +109 -0
  203. package/src/lib/session-picker.js +26 -3
  204. package/src/lib/session-projection.js +5 -1
  205. package/src/lib/session-search.js +25 -11
  206. package/src/lib/session-tail.js +31 -1
  207. package/src/lib/side-effect-ledger-store.js +2 -2
  208. package/src/lib/skill-budget.js +222 -0
  209. package/src/lib/skill-execution-authority.js +385 -0
  210. package/src/lib/skill-execution-identity.js +39 -2
  211. package/src/lib/skill-loader.js +322 -86
  212. package/src/lib/skill-mcp.js +43 -1
  213. package/src/lib/turn-binding-store.js +2 -2
  214. package/src/repl/agent-repl.js +483 -77
  215. package/src/repl/bg-dashboard.js +81 -28
  216. package/src/repl/chat-repl.js +77 -12
  217. package/src/runtime/agent-core.js +428 -113
  218. package/src/runtime/agent-runtime.js +26 -3
  219. package/src/runtime/cleanup-deadline.js +143 -0
  220. package/src/runtime/headless-runner.js +494 -149
  221. package/src/runtime/headless-stream.js +504 -75
  222. package/src/runtime/mcp-config.js +157 -10
  223. package/src/runtime/mcp-tool-search.js +0 -0
  224. package/src/runtime/output-backpressure.js +419 -0
  225. package/src/runtime/pipe-safety.js +56 -21
  226. package/src/assets/web-panel/assets/ChatBubbleRenderer-BUUyJ5QO.js +0 -1
  227. package/src/assets/web-panel/assets/MarkdownRenderer-1mNozZ8v.js +0 -1
  228. package/src/assets/web-panel/assets/MobileProjects-DqnoFPgR.js +0 -1
  229. package/src/assets/web-panel/assets/Providers-uO-10aP1.js +0 -1
  230. package/src/assets/web-panel/assets/devWarning-DosMaL-k.js +0 -1
  231. package/src/assets/web-panel/assets/index-0O5ePnUq.js +0 -1
  232. package/src/assets/web-panel/assets/index-ChAzPigF.js +0 -1
  233. package/src/lib/skill-process-broker.js +0 -85
@@ -21,8 +21,8 @@ import { existsSync, readdirSync, statSync } from "node:fs";
21
21
  import { join, basename } from "node:path";
22
22
  import { createRequire } from "node:module";
23
23
  import { getHomeDir } from "../lib/paths.js";
24
- import { iterateFileLinesSync } from "../lib/file-lines.js";
25
24
  import { ensurePrivateDirectory, ensurePrivateFile } from "../lib/secure-fs.js";
25
+ import { readVerifiedProjection } from "./jsonl-session-store.js";
26
26
 
27
27
  const requireCjs = createRequire(import.meta.url);
28
28
 
@@ -98,84 +98,74 @@ function toIsoSafe(value) {
98
98
  return Number.isNaN(date.getTime()) ? "" : date.toISOString();
99
99
  }
100
100
 
101
- function summarizeSessionFile(id, filePath) {
102
- let startEvent = null;
103
- let lastEvent = null;
104
- let renamedTitle = null;
105
- let messageCount = 0;
106
- let eventCount = 0;
107
- let chainHash = "";
108
- const parts = [];
109
- let used = 0;
110
- for (const { line } of iterateFileLinesSync(filePath)) {
111
- let event;
112
- try {
113
- event = JSON.parse(line);
114
- } catch {
115
- continue;
116
- }
117
- eventCount += 1;
118
- lastEvent = event;
119
- if (!startEvent && event.type === "session_start") startEvent = event;
120
- if (event.type === "session_rename" && event.data?.title) {
121
- renamedTitle = String(event.data.title);
122
- }
123
- if (event.type === "user_message" || event.type === "assistant_message") {
124
- messageCount += 1;
125
- if (used < CONTENT_CAP) {
126
- const content = event.data?.content;
127
- const text =
128
- typeof content === "string"
129
- ? content
130
- : content == null
131
- ? ""
132
- : JSON.stringify(content);
133
- if (text) {
134
- const bounded = text.slice(0, CONTENT_CAP - used);
135
- parts.push(bounded);
136
- used += bounded.length;
101
+ function summarizeVerifiedSession(id) {
102
+ return readVerifiedProjection(id, () => {
103
+ let startEvent = null;
104
+ let lastEvent = null;
105
+ let renamedTitle = null;
106
+ let messageCount = 0;
107
+ let eventCount = 0;
108
+ let chainHash = "";
109
+ const parts = [];
110
+ let used = 0;
111
+ const acceptContent = (content) => {
112
+ if (used >= CONTENT_CAP) return;
113
+ const text =
114
+ typeof content === "string"
115
+ ? content
116
+ : content == null
117
+ ? ""
118
+ : JSON.stringify(content);
119
+ if (!text) return;
120
+ const bounded = text.slice(0, CONTENT_CAP - used);
121
+ parts.push(bounded);
122
+ used += bounded.length;
123
+ };
124
+ return {
125
+ accept(event) {
126
+ eventCount += 1;
127
+ lastEvent = event;
128
+ if (!startEvent && event.type === "session_start") startEvent = event;
129
+ if (event.type === "session_rename" && event.data?.title) {
130
+ renamedTitle = String(event.data.title);
137
131
  }
138
- }
139
- } else if (
140
- event.type === "ws_turn" &&
141
- event.data?.schemaVersion === 1 &&
142
- event.data?.outcome === "completed" &&
143
- event.data?.user?.role === "user" &&
144
- event.data?.assistant?.role === "assistant"
145
- ) {
146
- messageCount += 2;
147
- for (const message of [event.data?.user, event.data?.assistant]) {
148
- if (used >= CONTENT_CAP) break;
149
- const content = message?.content;
150
- const text =
151
- typeof content === "string"
152
- ? content
153
- : content == null
154
- ? ""
155
- : JSON.stringify(content);
156
- if (text) {
157
- const bounded = text.slice(0, CONTENT_CAP - used);
158
- parts.push(bounded);
159
- used += bounded.length;
132
+ if (
133
+ event.type === "user_message" ||
134
+ event.type === "assistant_message"
135
+ ) {
136
+ messageCount += 1;
137
+ acceptContent(event.data?.content);
138
+ } else if (
139
+ event.type === "ws_turn" &&
140
+ event.data?.schemaVersion === 1 &&
141
+ event.data?.outcome === "completed" &&
142
+ event.data?.user?.role === "user" &&
143
+ event.data?.assistant?.role === "assistant"
144
+ ) {
145
+ messageCount += 2;
146
+ acceptContent(event.data.user.content);
147
+ acceptContent(event.data.assistant.content);
160
148
  }
161
- }
162
- }
163
- if (typeof event.hash === "string") chainHash = event.hash;
164
- }
165
- if (!lastEvent) return null;
166
- return {
167
- id,
168
- title: renamedTitle || startEvent?.data?.title || "Untitled",
169
- provider: startEvent?.data?.provider || "",
170
- model: startEvent?.data?.model || "",
171
- message_count: messageCount,
172
- event_count: eventCount,
173
- created_at: toIsoSafe(startEvent?.timestamp),
174
- updated_at: toIsoSafe(lastEvent?.timestamp),
175
- last_ts: lastEvent?.timestamp || 0,
176
- content: parts.join("\n").slice(0, CONTENT_CAP),
177
- chain_hash: chainHash,
178
- };
149
+ if (typeof event.hash === "string") chainHash = event.hash;
150
+ },
151
+ finish() {
152
+ if (!lastEvent) return null;
153
+ return {
154
+ id,
155
+ title: renamedTitle || startEvent?.data?.title || "Untitled",
156
+ provider: startEvent?.data?.provider || "",
157
+ model: startEvent?.data?.model || "",
158
+ message_count: messageCount,
159
+ event_count: eventCount,
160
+ created_at: toIsoSafe(startEvent?.timestamp),
161
+ updated_at: toIsoSafe(lastEvent?.timestamp),
162
+ last_ts: lastEvent?.timestamp || 0,
163
+ content: parts.join("\n").slice(0, CONTENT_CAP),
164
+ chain_hash: chainHash,
165
+ };
166
+ },
167
+ };
168
+ });
179
169
  }
180
170
 
181
171
  const UPSERT_SESSION = `
@@ -195,7 +185,7 @@ ON CONFLICT(id) DO UPDATE SET
195
185
  export function indexOneSession(db, id, { mtimeMs = 0, sizeBytes = 0 } = {}) {
196
186
  const filePath = join(sessionsDir(), `${id}.jsonl`);
197
187
  if (!existsSync(filePath)) return false;
198
- const s = summarizeSessionFile(id, filePath);
188
+ const s = summarizeVerifiedSession(id);
199
189
  if (!s) return false;
200
190
  db.prepare(UPSERT_SESSION).run({
201
191
  id: s.id,
@@ -228,6 +218,7 @@ export function syncIndex(db, { force = false } = {}) {
228
218
  let scanned = 0;
229
219
  let updated = 0;
230
220
  let removed = 0;
221
+ let rejected = 0;
231
222
  const seen = new Set();
232
223
 
233
224
  if (existsSync(dir)) {
@@ -251,7 +242,16 @@ export function syncIndex(db, { force = false } = {}) {
251
242
  ) {
252
243
  continue; // unchanged
253
244
  }
254
- if (indexOneSession(db, id, { mtimeMs, sizeBytes: size })) updated++;
245
+ try {
246
+ if (indexOneSession(db, id, { mtimeMs, sizeBytes: size })) updated++;
247
+ } catch {
248
+ // The index is disposable. A damaged canonical source invalidates any
249
+ // older cached content immediately and is reported without exposing
250
+ // transcript text or local paths.
251
+ db.prepare("DELETE FROM sessions WHERE id=?").run(id);
252
+ db.prepare("DELETE FROM session_content WHERE id=?").run(id);
253
+ rejected++;
254
+ }
255
255
  }
256
256
  });
257
257
  const entries = [];
@@ -278,7 +278,7 @@ export function syncIndex(db, { force = false } = {}) {
278
278
  }
279
279
 
280
280
  const total = db.prepare("SELECT COUNT(*) c FROM sessions").get().c;
281
- return { scanned, updated, removed, total };
281
+ return { scanned, updated, removed, rejected, total };
282
282
  }
283
283
 
284
284
  const LIST_COLUMNS =
@@ -11,6 +11,7 @@ import {
11
11
  appendFileSync,
12
12
  existsSync,
13
13
  readFileSync,
14
+ rmSync,
14
15
  writeFileSync,
15
16
  } from "node:fs";
16
17
  import { join } from "node:path";
@@ -19,6 +20,12 @@ import { ensurePrivateFile } from "../lib/secure-fs.js";
19
20
 
20
21
  export const SESSION_INDEX_SCHEMA = 2;
21
22
  export const SESSION_INDEX_FILE = ".sessions-index-v2.ndjson";
23
+ export const SESSION_TOMBSTONE_MARKER_SUFFIX = ".tombstone";
24
+ export const SESSION_TOMBSTONE_MARKER_SCHEMA =
25
+ "chainlesschain.session-tombstone/v1";
26
+ export const SESSION_GENERATION_AUTHORITY_FIELD = "_sessionGeneration";
27
+ export const SESSION_GENERATION_AUTHORITY_SCHEMA =
28
+ "chainlesschain.session-generation-authority/v1";
22
29
 
23
30
  // Used only by an opted-in child in the independent session-scale crash gate.
24
31
  // Keeping the injection immediately around the production sidecar/journal
@@ -41,6 +48,10 @@ export function sessionIndexPath(dir) {
41
48
  return join(dir, SESSION_INDEX_FILE);
42
49
  }
43
50
 
51
+ export function sessionTombstoneMarkerPath(dir, sessionId) {
52
+ return join(dir, `${sessionId}${SESSION_TOMBSTONE_MARKER_SUFFIX}`);
53
+ }
54
+
44
55
  export function emptySessionMeta(sessionId) {
45
56
  return {
46
57
  schema: SESSION_INDEX_SCHEMA,
@@ -53,10 +64,67 @@ export function emptySessionMeta(sessionId) {
53
64
  created_at_ms: 0,
54
65
  updated_at_ms: 0,
55
66
  last_hash: null,
67
+ transcript: null,
68
+ generation: null,
69
+ deleted_at_ms: null,
56
70
  deleted: false,
57
71
  };
58
72
  }
59
73
 
74
+ export function normalizeSessionGenerationAuthority(value) {
75
+ if (
76
+ !value ||
77
+ typeof value !== "object" ||
78
+ Array.isArray(value) ||
79
+ value.schema !== SESSION_GENERATION_AUTHORITY_SCHEMA ||
80
+ typeof value.sessionId !== "string" ||
81
+ value.sessionId.length === 0 ||
82
+ typeof value.generationId !== "string" ||
83
+ !/^generation-[0-9a-f-]{32,36}$/.test(value.generationId) ||
84
+ !Number.isSafeInteger(value.ordinal) ||
85
+ value.ordinal < 1
86
+ ) {
87
+ return null;
88
+ }
89
+ let predecessor = null;
90
+ if (value.predecessor !== null) {
91
+ const previous = value.predecessor;
92
+ if (
93
+ !previous ||
94
+ typeof previous !== "object" ||
95
+ Array.isArray(previous) ||
96
+ !["tombstone", "legacy-tombstone"].includes(previous.kind) ||
97
+ (previous.generationId !== null &&
98
+ (typeof previous.generationId !== "string" ||
99
+ !/^generation-[0-9a-f-]{32,36}$/.test(previous.generationId))) ||
100
+ (previous.headHash !== null &&
101
+ (typeof previous.headHash !== "string" ||
102
+ !/^[0-9a-f]{64}$/.test(previous.headHash))) ||
103
+ !Number.isSafeInteger(previous.eventCount) ||
104
+ previous.eventCount < 0 ||
105
+ (previous.tombstonedAtMs !== null &&
106
+ (!Number.isSafeInteger(previous.tombstonedAtMs) ||
107
+ previous.tombstonedAtMs < 0))
108
+ ) {
109
+ return null;
110
+ }
111
+ predecessor = {
112
+ kind: previous.kind,
113
+ generationId: previous.generationId,
114
+ headHash: previous.headHash,
115
+ eventCount: previous.eventCount,
116
+ tombstonedAtMs: previous.tombstonedAtMs,
117
+ };
118
+ }
119
+ return {
120
+ schema: SESSION_GENERATION_AUTHORITY_SCHEMA,
121
+ sessionId: value.sessionId,
122
+ generationId: value.generationId,
123
+ ordinal: value.ordinal,
124
+ predecessor,
125
+ };
126
+ }
127
+
60
128
  export function readSessionMeta(dir, sessionId) {
61
129
  const filePath = sessionMetaPath(dir, sessionId);
62
130
  if (!existsSync(filePath)) return null;
@@ -102,12 +170,48 @@ export function applyEventToSessionMeta(meta, event, lastHash) {
102
170
  ) {
103
171
  next.message_count = Math.max(0, Number(next.message_count) || 0) + 2;
104
172
  }
173
+ const generation = normalizeSessionGenerationAuthority(
174
+ event?.data?.[SESSION_GENERATION_AUTHORITY_FIELD],
175
+ );
176
+ if (generation?.sessionId === next.id) next.generation = generation;
177
+ next.deleted_at_ms = null;
105
178
  next.last_hash = typeof lastHash === "string" ? lastHash : null;
106
179
  return next;
107
180
  }
108
181
 
109
182
  function writeMetaSnapshot(dir, meta) {
110
183
  const filePath = sessionMetaPath(dir, meta.id);
184
+ const tombstoneMarker = sessionTombstoneMarkerPath(dir, meta.id);
185
+ // The marker is the durable per-session namespace witness that makes a
186
+ // tombstoned identity discoverable without reading every live sidecar on
187
+ // `--continue`; the meta snapshot remains the content/status authority.
188
+ // Publish the marker before the tombstone snapshot, and fail the delete if
189
+ // that publication fails. Remove it only after a live generation snapshot
190
+ // commits, so crashes can cause an extra candidate read but never hide a
191
+ // successfully committed tombstone.
192
+ if (meta.deleted === true) {
193
+ const generation = normalizeSessionGenerationAuthority(meta.generation);
194
+ const marker = {
195
+ schema: SESSION_TOMBSTONE_MARKER_SCHEMA,
196
+ id: meta.id,
197
+ generation: generation?.sessionId === meta.id ? generation : null,
198
+ last_hash:
199
+ typeof meta.last_hash === "string" &&
200
+ /^[0-9a-f]{64}$/.test(meta.last_hash)
201
+ ? meta.last_hash
202
+ : null,
203
+ event_count: Math.max(0, Number(meta.event_count) || 0),
204
+ deleted_at_ms: Math.max(
205
+ 0,
206
+ Number(meta.deleted_at_ms || meta.updated_at_ms) || 0,
207
+ ),
208
+ };
209
+ writeFileSync(tombstoneMarker, `${JSON.stringify(marker)}\n`, {
210
+ encoding: "utf8",
211
+ mode: 0o600,
212
+ });
213
+ ensurePrivateFile(tombstoneMarker);
214
+ }
111
215
  // The owning transcript lock serializes this derived snapshot. It need not
112
216
  // use a second temp+rename protocol: interruption can only corrupt a cache,
113
217
  // which readSessionMeta rejects and rebuildSessionMeta regenerates.
@@ -116,6 +220,40 @@ function writeMetaSnapshot(dir, meta) {
116
220
  mode: 0o600,
117
221
  });
118
222
  ensurePrivateFile(filePath);
223
+ if (meta.deleted !== true) rmSync(tombstoneMarker, { force: true });
224
+ }
225
+
226
+ /**
227
+ * Read the durable namespace marker. Legacy empty/invalid markers still count
228
+ * as deletion evidence, but deliberately expose no predecessor authority.
229
+ */
230
+ export function readSessionTombstoneMarker(dir, sessionId) {
231
+ const filePath = sessionTombstoneMarkerPath(dir, sessionId);
232
+ if (!existsSync(filePath)) return null;
233
+ try {
234
+ const value = JSON.parse(readFileSync(filePath, "utf8"));
235
+ if (
236
+ value?.schema !== SESSION_TOMBSTONE_MARKER_SCHEMA ||
237
+ value?.id !== sessionId
238
+ ) {
239
+ return { id: sessionId, legacy: true };
240
+ }
241
+ const generation = normalizeSessionGenerationAuthority(value.generation);
242
+ return {
243
+ schema: SESSION_TOMBSTONE_MARKER_SCHEMA,
244
+ id: sessionId,
245
+ generation: generation?.sessionId === sessionId ? generation : null,
246
+ last_hash:
247
+ typeof value.last_hash === "string" &&
248
+ /^[0-9a-f]{64}$/.test(value.last_hash)
249
+ ? value.last_hash
250
+ : null,
251
+ event_count: Math.max(0, Number(value.event_count) || 0),
252
+ deleted_at_ms: Math.max(0, Number(value.deleted_at_ms) || 0),
253
+ };
254
+ } catch {
255
+ return { id: sessionId, legacy: true };
256
+ }
119
257
  }
120
258
 
121
259
  function appendActivity(dir, meta) {
@@ -135,11 +273,46 @@ function appendActivity(dir, meta) {
135
273
  }
136
274
 
137
275
  /** Called while the owning transcript lock is held. */
138
- export function recordSessionEvent(dir, sessionId, event, lastHash) {
139
- const current =
140
- readSessionMeta(dir, sessionId) || emptySessionMeta(sessionId);
276
+ export function recordSessionEvent(
277
+ dir,
278
+ sessionId,
279
+ event,
280
+ lastHash,
281
+ { resetGeneration = false, transcriptState = null } = {},
282
+ ) {
283
+ const existing = readSessionMeta(dir, sessionId);
284
+ // Only the transcript writer may authorize a new generation after checking
285
+ // the tombstone and physical file under its lock. The index cannot infer
286
+ // that authority from an attacker-controlled genesis-shaped event alone.
287
+ const current = resetGeneration
288
+ ? emptySessionMeta(sessionId)
289
+ : existing || emptySessionMeta(sessionId);
141
290
  current.id = sessionId;
142
291
  const next = applyEventToSessionMeta(current, event, lastHash);
292
+ next.transcript = transcriptState
293
+ ? {
294
+ dev: String(transcriptState.dev),
295
+ ino: String(transcriptState.ino),
296
+ size: Number(transcriptState.size),
297
+ mtimeMs: Number(transcriptState.mtimeMs),
298
+ ctimeMs: Number(transcriptState.ctimeMs),
299
+ ...(transcriptState.devExact != null
300
+ ? { devExact: String(transcriptState.devExact) }
301
+ : {}),
302
+ ...(transcriptState.inoExact != null
303
+ ? { inoExact: String(transcriptState.inoExact) }
304
+ : {}),
305
+ ...(transcriptState.sizeExact != null
306
+ ? { sizeExact: String(transcriptState.sizeExact) }
307
+ : {}),
308
+ ...(transcriptState.mtimeNs != null
309
+ ? { mtimeNs: String(transcriptState.mtimeNs) }
310
+ : {}),
311
+ ...(transcriptState.ctimeNs != null
312
+ ? { ctimeNs: String(transcriptState.ctimeNs) }
313
+ : {}),
314
+ }
315
+ : null;
143
316
  writeMetaSnapshot(dir, next);
144
317
  runSessionScaleFaultHook("afterMetaSnapshot", {
145
318
  dir,
@@ -171,7 +344,9 @@ export function recordSessionDeleted(dir, sessionId, timestamp = Date.now()) {
171
344
  const tombstone = {
172
345
  ...current,
173
346
  updated_at_ms: timestamp,
347
+ deleted_at_ms: timestamp,
174
348
  deleted: true,
349
+ transcript: null,
175
350
  };
176
351
  writeMetaSnapshot(dir, tombstone);
177
352
  appendActivity(dir, tombstone);
@@ -224,13 +399,29 @@ export function publicSessionMeta(meta) {
224
399
  */
225
400
  export function listIndexedSessions(
226
401
  dir,
227
- { limit = 20, hasSession = () => true } = {},
402
+ {
403
+ limit = 20,
404
+ hasSession = () => true,
405
+ includeDeleted = () => false,
406
+ onScanComplete = null,
407
+ } = {},
228
408
  ) {
229
409
  const filePath = sessionIndexPath(dir);
230
- if (!existsSync(filePath)) return [];
410
+ if (!existsSync(filePath)) {
411
+ if (typeof onScanComplete === "function") {
412
+ onScanComplete({
413
+ exhausted: true,
414
+ seenSessionIds: new Set(),
415
+ latestBySessionId: new Map(),
416
+ });
417
+ }
418
+ return [];
419
+ }
231
420
  const wanted = Math.max(0, Number(limit) || 0);
232
421
  const seen = new Set();
422
+ const latestBySessionId = new Map();
233
423
  const result = [];
424
+ let exhausted = true;
234
425
  for (const { line } of iterateFileLinesReverseSync(filePath)) {
235
426
  let meta;
236
427
  try {
@@ -246,9 +437,21 @@ export function listIndexedSessions(
246
437
  continue;
247
438
  }
248
439
  seen.add(meta.id);
249
- if (meta.deleted || !hasSession(meta.id)) continue;
440
+ latestBySessionId.set(meta.id, meta);
441
+ if (
442
+ (meta.deleted && !includeDeleted(meta.id, meta)) ||
443
+ !hasSession(meta.id)
444
+ ) {
445
+ continue;
446
+ }
250
447
  result.push(publicSessionMeta(meta));
251
- if (wanted > 0 && result.length >= wanted) break;
448
+ if (wanted > 0 && result.length >= wanted) {
449
+ exhausted = false;
450
+ break;
451
+ }
452
+ }
453
+ if (typeof onScanComplete === "function") {
454
+ onScanComplete({ exhausted, seenSessionIds: seen, latestBySessionId });
252
455
  }
253
456
  return result;
254
457
  }
@@ -337,6 +337,43 @@ export function resolveCommandLifecycleInvocation(
337
337
  };
338
338
  }
339
339
 
340
+ /**
341
+ * Build the bounded, content-free lifecycle usage dimensions for a migrated
342
+ * command. The original argv is inspected only to distinguish the retained
343
+ * top-level spelling from its virtual namespace replacement; arguments and
344
+ * nested command names are never copied into telemetry.
345
+ */
346
+ export function resolveCommandLifecycleTelemetry(
347
+ argv,
348
+ manifestData = manifest,
349
+ ) {
350
+ const invocation = resolveCommandLifecycleInvocation(argv, manifestData);
351
+ let entry = null;
352
+ let route = null;
353
+ if (invocation.kind === "namespace-rewrite") {
354
+ entry = invocation.entry;
355
+ route = "replacement";
356
+ } else if (invocation.kind === "passthrough") {
357
+ const commandName = resolveCommandToken(argv);
358
+ entry = findManifestEntry(commandName, manifestData);
359
+ route = "legacy";
360
+ }
361
+ if (
362
+ entry?.lifecycle?.state !== "deprecated" ||
363
+ typeof entry.name !== "string" ||
364
+ !entry.replacement
365
+ ) {
366
+ return null;
367
+ }
368
+ return Object.freeze({
369
+ command: entry.name,
370
+ route,
371
+ version: packageMetadata.version,
372
+ deprecatedSince: entry.lifecycle.deprecatedSince,
373
+ removalNotBefore: entry.lifecycle.removalNotBefore,
374
+ });
375
+ }
376
+
340
377
  export function formatCommandDeprecationWarning(entry, invokedName) {
341
378
  const lifecycle = entry?.lifecycle;
342
379
  if (lifecycle?.state !== "deprecated" || !entry.replacement) return null;
@@ -691,7 +728,7 @@ export async function dispatchCli(
691
728
  { manifestData = manifest, ...dispatchOptions } = {},
692
729
  ) {
693
730
  const commandName = resolveCommandToken(argv);
694
- const entry = findManifestEntry(commandName, manifestData);
731
+ let entry = findManifestEntry(commandName, manifestData);
695
732
  if (!entry) {
696
733
  const program = await (
697
734
  dispatchOptions.loadFullProgram || defaultLoadFullProgram
@@ -699,20 +736,35 @@ export async function dispatchCli(
699
736
  await program.parseAsync(argv);
700
737
  return;
701
738
  }
739
+ const commandLocation = findCommandTokenLocation(argv);
740
+ if (entry.name === "session" && argv[commandLocation?.index + 1] === "show") {
741
+ entry = {
742
+ ...entry,
743
+ module: "./commands/session-show.js",
744
+ register: "registerSessionShowCommand",
745
+ };
746
+ }
702
747
  await dispatchManifestEntry(argv, entry, dispatchOptions);
703
748
  }
704
749
 
705
750
  export function isFastReadOnlyInvocation(argv, env = process.env) {
706
751
  const args = argv.slice(2);
707
- return (
752
+ const explicitOtlp =
753
+ args.includes("--otlp-endpoint") ||
754
+ args.some((token) => token.startsWith("--otlp-endpoint=")) ||
755
+ env.OTEL_EXPORTER_OTLP_ENDPOINT ||
756
+ env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||
757
+ env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT;
758
+ const quickStatus =
708
759
  resolveCommandToken(argv) === "status" &&
709
760
  !args.includes("--deep") &&
710
- !args.includes("--otlp-endpoint") &&
711
- !args.some((token) => token.startsWith("--otlp-endpoint=")) &&
712
- !env.OTEL_EXPORTER_OTLP_ENDPOINT &&
713
- !env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT &&
714
- !env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
715
- );
761
+ !explicitOtlp;
762
+ const commandLocation = findCommandTokenLocation(argv);
763
+ const sessionShow =
764
+ commandLocation?.token === "session" &&
765
+ argv[commandLocation.index + 1] === "show" &&
766
+ !explicitOtlp;
767
+ return quickStatus || sessionShow;
716
768
  }
717
769
 
718
770
  let processHandlersInstalled = false;
@@ -767,6 +819,10 @@ async function withInvocationOutputContext(argv, task) {
767
819
  }
768
820
 
769
821
  export async function runCli(argv, options = {}) {
822
+ const lifecycleTelemetry = resolveCommandLifecycleTelemetry(
823
+ argv,
824
+ options.manifestData || manifest,
825
+ );
770
826
  const prepared = await prepareInvocation(argv, options);
771
827
  if (prepared.handled) {
772
828
  if (prepared.exitCode) {
@@ -799,12 +855,24 @@ export async function runCli(argv, options = {}) {
799
855
  }
800
856
 
801
857
  const observability = await initializeCommandRuntime(dispatchArgv);
858
+ const lifecycleStartedAt = performance.now();
859
+ let lifecycleOutcome = "completed";
802
860
  try {
803
861
  return await withDefaultEventRuntimeLifecycle(
804
862
  () => dispatchCli(dispatchArgv, options),
805
863
  options,
806
864
  );
865
+ } catch (error) {
866
+ lifecycleOutcome = "error";
867
+ throw error;
807
868
  } finally {
869
+ if (lifecycleTelemetry) {
870
+ observability.exportCommandLifecycleInvocation({
871
+ ...lifecycleTelemetry,
872
+ outcome: lifecycleOutcome,
873
+ durationMs: performance.now() - lifecycleStartedAt,
874
+ });
875
+ }
808
876
  await observability.shutdown().catch(() => {});
809
877
  }
810
878
  });