chainlesschain 0.162.162 → 0.162.164

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 (237) hide show
  1. package/package.json +3 -1
  2. package/src/assets/web-panel/assets/{AIOps-ClI2ALgv.js → AIOps-BqRkaHGb.js} +1 -1
  3. package/src/assets/web-panel/assets/{ActionButton-BDjRcJaK.js → ActionButton-DWO7OZLC.js} +1 -1
  4. package/src/assets/web-panel/assets/{Analytics-DikSRsaT.js → Analytics-C5oaVezM.js} +3 -3
  5. package/src/assets/web-panel/assets/{AppLayout-9mLhMFmz.js → AppLayout-CsUESDoZ.js} +3 -3
  6. package/src/assets/web-panel/assets/{Artifacts-BSr88BrH.js → Artifacts-Dragqu5k.js} +1 -1
  7. package/src/assets/web-panel/assets/{Audit-CdvyimOF.js → Audit-CQsaHctY.js} +1 -1
  8. package/src/assets/web-panel/assets/{BackgroundAgents-D3_hCedh.js → BackgroundAgents-DdG1jNSM.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-Cyvv9RHf.js → Backup-DN6sjK4z.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-BZM14kt8.js → BaseInput-Cxm_ZTCl.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-DrQSokVz.js → Chat-DVXGmA56.js} +6 -6
  12. package/src/assets/web-panel/assets/{ChatBubbleRenderer-HwJR-C6B.js → ChatBubbleRenderer-BdaCL_iE.js} +1 -1
  13. package/src/assets/web-panel/assets/{Checkbox-bFLYeWMV.js → Checkbox-DEc4vD_A.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-7mN7xJXT.js → Codegen-CKiTcv36.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-DAB5ZWm7.js → Col-Br9UUNN0.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-B_1TymaK.js → Community-NeUH_70T.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-Bq1uSWLJ.js → Compact-BqR-z2Df.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-CyiE1jEe.js → Compliance-DcWB_SgZ.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-Cpk0D7vm.js → Cowork-BfhgcudF.js} +2 -2
  20. package/src/assets/web-panel/assets/{Cron-d_Lv3rdB.js → Cron-LaU29LgD.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-DMqhHjMR.js → Crosschain-B2ZB9uwW.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-Br-oPuBw.js → DID-BuHl38A2.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-CfLW_RaP.js → Dashboard-m627yqvZ.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-DZnTOExV.js → Dropdown-C7bxF8F5.js} +1 -1
  25. package/src/assets/web-panel/assets/{EmailListRenderer-DHIUHDv1.js → EmailListRenderer-DPLPQzLp.js} +1 -1
  26. package/src/assets/web-panel/assets/{FamilyGuardDashboard-Bw3t3myu.js → FamilyGuardDashboard-cOiH6ike.js} +1 -1
  27. package/src/assets/web-panel/assets/{Federation-D9cpQPAY.js → Federation-Bvkzg88z.js} +1 -1
  28. package/src/assets/web-panel/assets/{FormItemContext-Jdczr9Mr.js → FormItemContext-BTsiA7h_.js} +1 -1
  29. package/src/assets/web-panel/assets/{GenericCardRenderer-BT8ZMpC5.js → GenericCardRenderer-BGnVE5qu.js} +1 -1
  30. package/src/assets/web-panel/assets/{Git-DjARip2b.js → Git-DS_j6r25.js} +2 -2
  31. package/src/assets/web-panel/assets/{Governance-BgWbSRcj.js → Governance-CKRG3Rsl.js} +1 -1
  32. package/src/assets/web-panel/assets/{Inference-CfouJciM.js → Inference-DW8INoNQ.js} +1 -1
  33. package/src/assets/web-panel/assets/{KnowledgeGraph-50l7mrAr.js → KnowledgeGraph-BhEYeFhC.js} +1 -1
  34. package/src/assets/web-panel/assets/{Logs-rq50H84B.js → Logs-wqi0uxuR.js} +2 -2
  35. package/src/assets/web-panel/assets/{MarkdownRenderer-DUPIEdQH.js → MarkdownRenderer-DS8dE8ty.js} +1 -1
  36. package/src/assets/web-panel/assets/{Marketplace-BYgPDmHU.js → Marketplace-CMlTuPLT.js} +1 -1
  37. package/src/assets/web-panel/assets/{McpTools-5DVgcFdx.js → McpTools-CSx4m5JJ.js} +3 -3
  38. package/src/assets/web-panel/assets/{Memory-B70LPk7f.js → Memory-vnQCUy-_.js} +2 -2
  39. package/src/assets/web-panel/assets/{MobileBridge-De8ssA5Y.js → MobileBridge-BV2NA742.js} +1 -1
  40. package/src/assets/web-panel/assets/MobileProjects-Bw0k8e1B.js +1 -0
  41. package/src/assets/web-panel/assets/{Mtc-RJsOTsIA.js → Mtc-CzK_FPB1.js} +2 -2
  42. package/src/assets/web-panel/assets/{MtcAudit-Crh-6BEK.js → MtcAudit-Cb7G9oL3.js} +5 -5
  43. package/src/assets/web-panel/assets/{Multisig-wuoR5l3x.js → Multisig-qJxlUyzr.js} +3 -3
  44. package/src/assets/web-panel/assets/{NLProgramming-U2Mji4fZ.js → NLProgramming-DqaBJ7Te.js} +1 -1
  45. package/src/assets/web-panel/assets/{Notes-CdTZAyDH.js → Notes-CwhTJkRi.js} +3 -3
  46. package/src/assets/web-panel/assets/{NotificationSettings-C-FucWE7.js → NotificationSettings-YDs4Fal4.js} +1 -1
  47. package/src/assets/web-panel/assets/{OrderTableRenderer-DCYFTeaI.js → OrderTableRenderer-CvEALpq7.js} +1 -1
  48. package/src/assets/web-panel/assets/{Organization-an3OF85L.js → Organization-CEmQm9n8.js} +4 -4
  49. package/src/assets/web-panel/assets/{Overflow-C-1vmYFe.js → Overflow-zby_P_LA.js} +1 -1
  50. package/src/assets/web-panel/assets/{P2P-Cwh47xKg.js → P2P-DsmDNFNT.js} +2 -2
  51. package/src/assets/web-panel/assets/{PdhVaultBrowser-Dm38GT0k.js → PdhVaultBrowser-FWwFlZGF.js} +3 -3
  52. package/src/assets/web-panel/assets/{Permissions-DS2Y8awD.js → Permissions-DuzQ6me5.js} +4 -4
  53. package/src/assets/web-panel/assets/{PersonalDataHub-BQNziA0I.js → PersonalDataHub-DZbeN613.js} +3 -3
  54. package/src/assets/web-panel/assets/{Pipeline-DF85L1ue.js → Pipeline-CoNSVAUS.js} +1 -1
  55. package/src/assets/web-panel/assets/{Privacy-BuLornF-.js → Privacy-OYJEAaMC.js} +1 -1
  56. package/src/assets/web-panel/assets/{ProjectInit-C3Y31IwX.js → ProjectInit-CWIapV--.js} +2 -2
  57. package/src/assets/web-panel/assets/{ProjectSettings-BCPiI8aD.js → ProjectSettings-CX8xMxZn.js} +2 -2
  58. package/src/assets/web-panel/assets/{Projects-BZ6s4k6g.js → Projects-BLCN8YyY.js} +1 -1
  59. package/src/assets/web-panel/assets/{Providers-D3Wp022X.js → Providers-BV_sxp75.js} +1 -1
  60. package/src/assets/web-panel/assets/{QrScannerModal-CUJfQkH4.js → QrScannerModal-BTnRrHRp.js} +1 -1
  61. package/src/assets/web-panel/assets/{QuickAsk-UAc0EO8l.js → QuickAsk-D1KZg018.js} +1 -1
  62. package/src/assets/web-panel/assets/{Recommend-BaxKupcs.js → Recommend-COm5cuNg.js} +1 -1
  63. package/src/assets/web-panel/assets/{RemoteSession-C75NNnXZ.js → RemoteSession-0saWEkYI.js} +2 -2
  64. package/src/assets/web-panel/assets/{Reputation-BVXynZAk.js → Reputation-Dr7iKLS2.js} +1 -1
  65. package/src/assets/web-panel/assets/{Row-C5MRZ0bi.js → Row-C1vpPBcr.js} +1 -1
  66. package/src/assets/web-panel/assets/{RssFeed-DAKkEYka.js → RssFeed-CxlWrtNj.js} +3 -3
  67. package/src/assets/web-panel/assets/{Search-DvWv9YOA.js → Search-BT2V8dPN.js} +1 -1
  68. package/src/assets/web-panel/assets/{Security-B5peafW1.js → Security-bm9V3c5k.js} +4 -4
  69. package/src/assets/web-panel/assets/{Services-UQmvPEaG.js → Services-CocH1yyX.js} +2 -2
  70. package/src/assets/web-panel/assets/{Skeleton-C3bhWpuF.js → Skeleton-DHItlMdd.js} +1 -1
  71. package/src/assets/web-panel/assets/{Skills-DfkKf9_H.js → Skills-C59sLc4w.js} +1 -1
  72. package/src/assets/web-panel/assets/{Sla-DqMSjlBM.js → Sla-Crj4BMc8.js} +1 -1
  73. package/src/assets/web-panel/assets/{SpeechSettings-C-WbxWUX.js → SpeechSettings-DX4KFceY.js} +1 -1
  74. package/src/assets/web-panel/assets/{SyncSettings-CYuHZ4N2.js → SyncSettings-BD_iwQLr.js} +2 -2
  75. package/src/assets/web-panel/assets/{Tasks-CyeAyB9d.js → Tasks-BmCTzYsH.js} +1 -1
  76. package/src/assets/web-panel/assets/{Templates-BTCeQnpq.js → Templates-BGUaxZYl.js} +1 -1
  77. package/src/assets/web-panel/assets/{Tenant-BifQuA9Y.js → Tenant-BS0tJx2O.js} +1 -1
  78. package/src/assets/web-panel/assets/{Terminal-Bx_9Bocf.js → Terminal--tHSAsld.js} +2 -2
  79. package/src/assets/web-panel/assets/{TimelineRenderer-BX0RFCOm.js → TimelineRenderer-D9-MFxS4.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tokens-CGHrCmUS.js → Tokens-CiCB485f.js} +1 -1
  81. package/src/assets/web-panel/assets/{Trigger-DlqaY4SO.js → Trigger-SmCFuW_l.js} +1 -1
  82. package/src/assets/web-panel/assets/{Trust-DfOmj-ay.js → Trust-DkK3Rqe0.js} +1 -1
  83. package/src/assets/web-panel/assets/{UkeySign-B72jH5fE.js → UkeySign-CDM4LGdB.js} +1 -1
  84. package/src/assets/web-panel/assets/{VideoEditing-BT-63fqv.js → VideoEditing-IDB7DJXt.js} +1 -1
  85. package/src/assets/web-panel/assets/{Wallet-Dsul3sHr.js → Wallet-Bikj5cmt.js} +4 -4
  86. package/src/assets/web-panel/assets/{WebAuthn-Izkwwdgy.js → WebAuthn-C9abWlAw.js} +2 -2
  87. package/src/assets/web-panel/assets/{WorkflowEditor-D3FHSiH1.js → WorkflowEditor-DrbRKVky.js} +1 -1
  88. package/src/assets/web-panel/assets/{chat-CmVz5z3U.js → chat-CccCSDQf.js} +1 -1
  89. package/src/assets/web-panel/assets/{colors-CuLgyJBp.js → colors-CXObXLhb.js} +1 -1
  90. package/src/assets/web-panel/assets/{compact-item-Ml1YkXpw.js → compact-item-B5kfYAxC.js} +1 -1
  91. package/src/assets/web-panel/assets/{createContext-BvjJ48bs.js → createContext-DmiPBfip.js} +1 -1
  92. package/src/assets/web-panel/assets/devWarning-CvKrADNa.js +1 -0
  93. package/src/assets/web-panel/assets/{hasIn-DVC0157C.js → hasIn-Q6lYteAc.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-C229ABfy.js → index-25Wlqps4.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-Ck_52dz_.js → index-33U29UNV.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-QXzlT9KD.js → index-4oXBDczR.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-4SBta3d7.js → index-BGYXvMc5.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-B0S8NzO6.js → index-BJCCa0s_.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-DJyN28Et.js → index-BJJ5DhKI.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-DC_OI9H2.js → index-BLOzViJ6.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-C_XuRgGn.js → index-BRrbUMoG.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-wvb_FtaV.js → index-BUFpT17Q.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-KMqhcF7l.js → index-BkRDiqGc.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-vG4XSJ1d.js → index-BsfvW6my.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-DYXHFr4r.js → index-By-kfPED.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DuGszaWY.js → index-BzFTcQsc.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-CXkJH-lK.js → index-C2FXdboq.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-Dt5KMjwJ.js → index-C5XOlTHN.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-4wcgvPoF.js → index-CLhBDS2w.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-C_H_S-DY.js → index-CMq7UeoT.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-BydjdZnl.js → index-CVMTWNKl.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-BjHBpRYZ.js → index-Caghi-yL.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-Bzr0rB5T.js → index-CdB6FuSH.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-BbPtzB8M.js → index-CoK8-kWQ.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-BUt8kTIB.js → index-CsO3GUAY.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-C_vRgTl9.js → index-CwZBa20Z.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-DukDVXCv.js → index-D-kASucw.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-BbepULSc.js → index-D8eBw7vW.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-BfuKP4qe.js → index-D9wgifk4.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-BiC6dQZG.js → index-DAYCTc07.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-CmFNvNLZ.js → index-DF6Q8l2h.js} +1 -1
  122. package/src/assets/web-panel/assets/index-DTdFUWc_.js +1 -0
  123. package/src/assets/web-panel/assets/{index-KjgKdZe-.js → index-DgTLApS9.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-BpFJHiTv.js → index-DgxVJ8pg.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-Cw0Rjy87.js → index-DlJvIqoR.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-CFYVQMvu.js → index-Dw4eHfsG.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CudmwNBV.js → index-Rh-ytwow.js} +3 -3
  128. package/src/assets/web-panel/assets/{index-DDGaOWBV.js → index-StAEt2pq.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-D3lD5qap.js → index-bzfw951k.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-BzG-x9p4.js → index-fSUMbMvv.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-B_EvG_GW.js → index-tFHy5Wol.js} +1 -1
  132. package/src/assets/web-panel/assets/index-zQ0M_kz-.js +1 -0
  133. package/src/assets/web-panel/assets/{initDefaultProps-BDgd2YZ8.js → initDefaultProps-BNq7X72N.js} +1 -1
  134. package/src/assets/web-panel/assets/{motion-ErtrXdYe.js → motion-DOf9viTc.js} +1 -1
  135. package/src/assets/web-panel/assets/{move-_GPPNCgs.js → move-CRHTcW4x.js} +1 -1
  136. package/src/assets/web-panel/assets/{mtc-parser-DRLL-8V2.js → mtc-parser-Cyoozgm2.js} +1 -1
  137. package/src/assets/web-panel/assets/{omit-p86sl023.js → omit-6-TjFNru.js} +1 -1
  138. package/src/assets/web-panel/assets/{pickAttrs-BTu7cMLH.js → pickAttrs-DlUmO1zi.js} +1 -1
  139. package/src/assets/web-panel/assets/{placementArrow-BEKz6Isr.js → placementArrow-CFOL8mIR.js} +1 -1
  140. package/src/assets/web-panel/assets/{responsiveObserve-Ck42c9MP.js → responsiveObserve-BtaFK5zd.js} +1 -1
  141. package/src/assets/web-panel/assets/{slide-1CEvuPsB.js → slide-BIbc2bur.js} +1 -1
  142. package/src/assets/web-panel/assets/{statusUtils-BDfdx1GJ.js → statusUtils-BXX9d6-w.js} +1 -1
  143. package/src/assets/web-panel/assets/{styleChecker-B4K46m5w.js → styleChecker-BGv10Bpn.js} +1 -1
  144. package/src/assets/web-panel/assets/{useFlexGapSupport-DoIVpJNq.js → useFlexGapSupport-bKnKT8tw.js} +1 -1
  145. package/src/assets/web-panel/assets/{useFs-DdAWi-ln.js → useFs-FY4IL4jn.js} +1 -1
  146. package/src/assets/web-panel/assets/{usePersonalDataHub-iUu6k8dx.js → usePersonalDataHub-Bwl9TEgu.js} +1 -1
  147. package/src/assets/web-panel/assets/{vnode-DZz4R6Tw.js → vnode-BM3OHxAT.js} +1 -1
  148. package/src/assets/web-panel/assets/{zoom-DXlf9sA3.js → zoom-D1fbFiHB.js} +1 -1
  149. package/src/assets/web-panel/index.html +1 -1
  150. package/src/commands/agenda.js +320 -32
  151. package/src/commands/agent.js +105 -11
  152. package/src/commands/context.js +125 -14
  153. package/src/commands/doctor.js +85 -1
  154. package/src/commands/hook.js +181 -7
  155. package/src/commands/plugin.js +456 -1
  156. package/src/commands/review.js +363 -2
  157. package/src/commands/session.js +191 -0
  158. package/src/commands/team.js +19 -1
  159. package/src/data/changelog.json +10 -4
  160. package/src/gateways/ws/remote-session-protocol.js +39 -0
  161. package/src/gateways/ws/session-protocol.js +55 -2
  162. package/src/gateways/ws/ws-agent-handler.js +50 -0
  163. package/src/harness/jsonl-session-store.js +60 -0
  164. package/src/harness/worktree-isolator.js +140 -5
  165. package/src/lib/agent-schedule-store.js +318 -10
  166. package/src/lib/agent-team/team-worktree.js +37 -2
  167. package/src/lib/agent-tool-admission.js +125 -0
  168. package/src/lib/app-preview.js +360 -0
  169. package/src/lib/async-hook-supervisor.cjs +54 -0
  170. package/src/lib/capability-manifest.js +319 -0
  171. package/src/lib/capability-negotiation.js +23 -12
  172. package/src/lib/channels/channel-manager.js +54 -2
  173. package/src/lib/cli-context-engineering.js +9 -2
  174. package/src/lib/context-breakdown.js +116 -0
  175. package/src/lib/diagnostic-bundle.js +230 -0
  176. package/src/lib/doctor-checkup.js +275 -4
  177. package/src/lib/execution-location.js +286 -0
  178. package/src/lib/headless-manifest.js +13 -40
  179. package/src/lib/hook-event-log.cjs +193 -0
  180. package/src/lib/hook-stats-store.cjs +197 -0
  181. package/src/lib/idempotency.js +109 -0
  182. package/src/lib/interaction-adapter.js +34 -4
  183. package/src/lib/json-schema-output.js +46 -12
  184. package/src/lib/json-schema-validate.js +143 -3
  185. package/src/lib/jsonl-session-store.js +1 -0
  186. package/src/lib/lsp/__tests__/lsp-manager.test.js +58 -0
  187. package/src/lib/lsp/lsp-manager.js +56 -0
  188. package/src/lib/monitor-event.js +290 -0
  189. package/src/lib/operation-fingerprint.js +217 -0
  190. package/src/lib/plugin-runtime/bin.js +37 -0
  191. package/src/lib/plugin-runtime/capabilities.js +19 -0
  192. package/src/lib/plugin-runtime/capability-consent.js +203 -0
  193. package/src/lib/plugin-runtime/hooks.js +37 -0
  194. package/src/lib/plugin-runtime/lsp.js +38 -0
  195. package/src/lib/plugin-runtime/mcp.js +40 -0
  196. package/src/lib/plugin-runtime/monitors.js +37 -0
  197. package/src/lib/plugin-runtime/plugin-options.js +151 -0
  198. package/src/lib/plugin-runtime/policy.js +62 -0
  199. package/src/lib/plugin-runtime/scopes.js +20 -4
  200. package/src/lib/pr-automation-policy.js +224 -0
  201. package/src/lib/project-instructions.js +128 -0
  202. package/src/lib/remote-approval-bridge.js +66 -13
  203. package/src/lib/repl-goal.js +132 -0
  204. package/src/lib/repl-rewind.js +153 -0
  205. package/src/lib/review-comment-anchor.js +241 -0
  206. package/src/lib/review-pipeline.js +46 -7
  207. package/src/lib/runtime-checkup.js +221 -0
  208. package/src/lib/schedule-planner.js +17 -1
  209. package/src/lib/secret-scan.js +409 -0
  210. package/src/lib/session-branch.js +0 -0
  211. package/src/lib/settings-hook-events.cjs +13 -0
  212. package/src/lib/settings-loader.cjs +42 -0
  213. package/src/lib/side-effect-ledger-store.js +88 -0
  214. package/src/lib/side-effect-ledger.js +401 -0
  215. package/src/lib/skill-loader.js +32 -0
  216. package/src/lib/skill-path-scope.js +63 -0
  217. package/src/lib/sub-agent-context.js +110 -9
  218. package/src/lib/sub-agent-registry.js +19 -0
  219. package/src/lib/subagent-inheritance.js +112 -0
  220. package/src/lib/telemetry/span-recorder.js +17 -4
  221. package/src/lib/terminal-context.js +195 -0
  222. package/src/lib/turn-binding-store.js +119 -0
  223. package/src/lib/unattended-action-policy.js +182 -0
  224. package/src/lib/worktree-cleanup-safety.js +138 -0
  225. package/src/lib/worktree-isolator.js +8 -0
  226. package/src/lib/worktree-sparse.js +131 -0
  227. package/src/repl/agent-repl.js +280 -30
  228. package/src/repl/permission-tier.js +28 -0
  229. package/src/runtime/agent-core.js +565 -21
  230. package/src/runtime/coding-agent-contract-shared.cjs +60 -1
  231. package/src/runtime/diagnostics.js +60 -0
  232. package/src/runtime/headless-runner.js +393 -1
  233. package/src/runtime/headless-stream.js +60 -1
  234. package/src/assets/web-panel/assets/MobileProjects-D10VISps.js +0 -1
  235. package/src/assets/web-panel/assets/devWarning-DhiGrbsh.js +0 -1
  236. package/src/assets/web-panel/assets/index-B7a1TrU6.js +0 -1
  237. package/src/assets/web-panel/assets/index-C2B1KRja.js +0 -1
@@ -0,0 +1,319 @@
1
+ /**
2
+ * Canonical capability manifest — the single source the CLI capability output,
3
+ * the VS Code / JetBrains negotiation, the protocol docs, the compatibility
4
+ * fixture, the behavior matrix and the release-notes capability diff all project
5
+ * from (P1-9 "Capability Manifest 与脱敏诊断包" of
6
+ * CLAUDE_CODE_IDE_INCREMENTAL_GAP_ANALYSIS_2026-07-13.md).
7
+ *
8
+ * Today the wire-protocol capability surface is hand-authored in THREE places
9
+ * that can silently drift:
10
+ * - [[capability-negotiation.js]]: `PROTOCOL_FEATURES`, `FEATURE_MIN_VERSION`,
11
+ * and the private `FEATURE_TO_FIELD` map.
12
+ * - [[headless-manifest.js]]: `buildAgentCapabilities().features` (the
13
+ * `cc agent --capabilities` output).
14
+ * - the Java twin + the shared negotiation fixture.
15
+ * A new v2 field added to one list but not the others parses wrong on the peer
16
+ * that missed it. This module is the ONE definition; every other shape is a pure
17
+ * projection of it, and a drift-guard test asserts the live hand-authored
18
+ * constants still equal the projection (see capability-manifest.test.js).
19
+ *
20
+ * Pure: no fs / process / clock. Projections are deterministic so a caller can
21
+ * regenerate docs/fixtures and diff them against the checked-in copies in CI.
22
+ */
23
+
24
+ import { createHash } from "node:crypto";
25
+
26
+ /**
27
+ * THE canonical manifest. `wireFeatures` is the negotiable additive per-line
28
+ * field set (order mirrors capability-negotiation.js `PROTOCOL_FEATURES`);
29
+ * `runtimeFeatures` are the boolean capability flags that change what the CLI
30
+ * can DO (not the shape of a line the client must parse) and are NOT negotiated.
31
+ */
32
+ export const CAPABILITY_MANIFEST = Object.freeze({
33
+ name: "chainlesschain-cli",
34
+ protocolVersion: 1,
35
+ minProtocolVersion: 1,
36
+
37
+ wireFeatures: Object.freeze([
38
+ Object.freeze({
39
+ key: "event_seq",
40
+ field: "seq",
41
+ minVersion: 1,
42
+ description:
43
+ "every stream-json stdout line carries a monotonic per-run `seq`",
44
+ }),
45
+ Object.freeze({
46
+ key: "tool_use_id",
47
+ field: "tool_use_id",
48
+ minVersion: 1,
49
+ description:
50
+ 'tool_use / tool_result lines carry a pairing `id` ("tu-<n>")',
51
+ }),
52
+ Object.freeze({
53
+ key: "trace_id",
54
+ field: "trace_id",
55
+ minVersion: 1,
56
+ description:
57
+ "each line carries a run-scoped, caller-injectable `trace_id` for IDE ↔ CLI correlation",
58
+ }),
59
+ ]),
60
+
61
+ // Boolean capability flags (buildAgentCapabilities().features truthy keys).
62
+ runtimeFeatures: Object.freeze([
63
+ "bare",
64
+ "safe_mode",
65
+ "ephemeral",
66
+ "background",
67
+ "worktree",
68
+ "checkpoint",
69
+ "json_schema_output",
70
+ "partial_messages",
71
+ "interactive_approvals",
72
+ "permission_prompt_tool",
73
+ "remote_control",
74
+ ]),
75
+
76
+ mcpFeatures: Object.freeze([
77
+ "config_file",
78
+ "registry",
79
+ "tool_search",
80
+ "oauth",
81
+ "managed_allowlist",
82
+ ]),
83
+ sandboxEngines: Object.freeze(["docker", "bubblewrap"]),
84
+
85
+ permissionModes: Object.freeze([
86
+ "default",
87
+ "manual",
88
+ "auto",
89
+ "dontAsk",
90
+ "plan",
91
+ "acceptEdits",
92
+ "bypassPermissions",
93
+ ]),
94
+ outputFormats: Object.freeze(["text", "json", "stream-json"]),
95
+ inputFormats: Object.freeze(["text", "stream-json"]),
96
+ });
97
+
98
+ const manifestOr = (m) =>
99
+ m && typeof m === "object" ? m : CAPABILITY_MANIFEST;
100
+ const wireFeaturesOf = (m) =>
101
+ Array.isArray(manifestOr(m).wireFeatures) ? manifestOr(m).wireFeatures : [];
102
+
103
+ /**
104
+ * The negotiable wire feature keys, in canonical declared order — the value
105
+ * capability-negotiation.js `PROTOCOL_FEATURES` must equal.
106
+ * @returns {string[]}
107
+ */
108
+ export function toProtocolFeatures(m = CAPABILITY_MANIFEST) {
109
+ return wireFeaturesOf(m).map((f) => f.key);
110
+ }
111
+
112
+ /**
113
+ * Feature → minimum protocol version, ONLY for features gated above the base
114
+ * version (a v1-additive field is absent, matching an empty
115
+ * `FEATURE_MIN_VERSION` today). Adding a v2 feature here flows the gate to the
116
+ * negotiator automatically.
117
+ * @returns {Record<string, number>}
118
+ */
119
+ export function toFeatureMinVersion(m = CAPABILITY_MANIFEST) {
120
+ const out = {};
121
+ for (const f of wireFeaturesOf(m)) {
122
+ if (Number(f.minVersion) > 1) out[f.key] = Number(f.minVersion);
123
+ }
124
+ return out;
125
+ }
126
+
127
+ /**
128
+ * Feature → the stream line field it gates (the value of the private
129
+ * `FEATURE_TO_FIELD` map in capability-negotiation.js).
130
+ * @returns {Record<string, string>}
131
+ */
132
+ export function toFieldGate(m = CAPABILITY_MANIFEST) {
133
+ const out = {};
134
+ for (const f of wireFeaturesOf(m)) out[f.key] = f.field;
135
+ return out;
136
+ }
137
+
138
+ /**
139
+ * The server negotiation offer shape consumed by
140
+ * capability-negotiation.js `negotiateProtocol(server, …)`.
141
+ * @returns {{protocolVersion:number, minProtocolVersion:number, features:string[]}}
142
+ */
143
+ export function toServerOffer(m = CAPABILITY_MANIFEST) {
144
+ const mm = manifestOr(m);
145
+ return {
146
+ protocolVersion: Number(mm.protocolVersion) || 1,
147
+ minProtocolVersion: Number(mm.minProtocolVersion) || 1,
148
+ features: toProtocolFeatures(mm),
149
+ };
150
+ }
151
+
152
+ /**
153
+ * The `features` object of `cc agent --capabilities`
154
+ * (buildAgentCapabilities().features): every runtime flag true, every wire
155
+ * feature true, plus the nested `mcp` object and `sandbox_engines` list. A test
156
+ * asserts the live buildAgentCapabilities().features deep-equals this.
157
+ * @returns {object}
158
+ */
159
+ export function toAgentFeatureFlags(m = CAPABILITY_MANIFEST) {
160
+ const mm = manifestOr(m);
161
+ const flags = {};
162
+ for (const key of mm.runtimeFeatures || []) flags[key] = true;
163
+ for (const f of wireFeaturesOf(mm)) flags[f.key] = true;
164
+ flags.mcp = {};
165
+ for (const key of mm.mcpFeatures || []) flags.mcp[key] = true;
166
+ flags.sandbox_engines = [...(mm.sandboxEngines || [])];
167
+ return flags;
168
+ }
169
+
170
+ /**
171
+ * A deterministic capability fixture the VS Code / JetBrains twins can pin and
172
+ * assert against (the "Compatibility Fixture" the gap doc asks for). Order- and
173
+ * clock-independent; a `digest` lets a peer detect any change in one compare.
174
+ * @returns {object}
175
+ */
176
+ export function buildCompatFixture(m = CAPABILITY_MANIFEST) {
177
+ const mm = manifestOr(m);
178
+ const body = {
179
+ protocolVersion: Number(mm.protocolVersion) || 1,
180
+ minProtocolVersion: Number(mm.minProtocolVersion) || 1,
181
+ features: toProtocolFeatures(mm),
182
+ featureFields: toFieldGate(mm),
183
+ featureMinVersion: toFeatureMinVersion(mm),
184
+ permissionModes: [...(mm.permissionModes || [])],
185
+ outputFormats: [...(mm.outputFormats || [])],
186
+ inputFormats: [...(mm.inputFormats || [])],
187
+ };
188
+ return { ...body, digest: capabilityDigest(mm) };
189
+ }
190
+
191
+ /**
192
+ * A stable digest of the whole capability surface (no RNG/clock) — one string
193
+ * that changes iff any projected capability changed. Handy as a CI drift check.
194
+ * @returns {string} 16-hex-char sha256 prefix
195
+ */
196
+ export function capabilityDigest(m = CAPABILITY_MANIFEST) {
197
+ const mm = manifestOr(m);
198
+ const canonical = {
199
+ protocolVersion: Number(mm.protocolVersion) || 1,
200
+ minProtocolVersion: Number(mm.minProtocolVersion) || 1,
201
+ wire: wireFeaturesOf(mm)
202
+ .map((f) => [f.key, f.field, Number(f.minVersion) || 1])
203
+ .sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0)),
204
+ runtime: [...(mm.runtimeFeatures || [])].sort(),
205
+ mcp: [...(mm.mcpFeatures || [])].sort(),
206
+ sandbox: [...(mm.sandboxEngines || [])].sort(),
207
+ permissionModes: [...(mm.permissionModes || [])].sort(),
208
+ outputFormats: [...(mm.outputFormats || [])].sort(),
209
+ inputFormats: [...(mm.inputFormats || [])].sort(),
210
+ };
211
+ return createHash("sha256")
212
+ .update(JSON.stringify(canonical))
213
+ .digest("hex")
214
+ .slice(0, 16);
215
+ }
216
+
217
+ /**
218
+ * A behavior matrix row per wire feature — feature × min version × gated field ×
219
+ * negotiable × description. Consumed by renderProtocolDoc and by a test that a
220
+ * doc table matches the code.
221
+ * @returns {Array<{feature:string, minVersion:number, field:string, negotiable:boolean, description:string}>}
222
+ */
223
+ export function renderBehaviorMatrix(m = CAPABILITY_MANIFEST) {
224
+ return wireFeaturesOf(m).map((f) => ({
225
+ feature: f.key,
226
+ minVersion: Number(f.minVersion) || 1,
227
+ field: f.field,
228
+ negotiable: true,
229
+ description: String(f.description || ""),
230
+ }));
231
+ }
232
+
233
+ /**
234
+ * Render the protocol capability section as Markdown (a generated doc a CI job
235
+ * diffs against the checked-in copy). Deterministic; ends with a trailing
236
+ * newline so a byte compare is stable.
237
+ * @returns {string}
238
+ */
239
+ export function renderProtocolDoc(m = CAPABILITY_MANIFEST) {
240
+ const mm = manifestOr(m);
241
+ const lines = [];
242
+ lines.push("# Agent Protocol Capability Manifest (generated)");
243
+ lines.push("");
244
+ lines.push(
245
+ `Protocol version **${mm.protocolVersion}** (negotiates down to **${mm.minProtocolVersion}**).`,
246
+ );
247
+ lines.push("");
248
+ lines.push("## Negotiable wire features");
249
+ lines.push("");
250
+ lines.push("| Feature | Min version | Line field | Description |");
251
+ lines.push("| ------- | ----------- | ---------- | ----------- |");
252
+ for (const row of renderBehaviorMatrix(mm)) {
253
+ lines.push(
254
+ `| \`${row.feature}\` | ${row.minVersion} | \`${row.field}\` | ${row.description} |`,
255
+ );
256
+ }
257
+ lines.push("");
258
+ lines.push("## Permission modes");
259
+ lines.push("");
260
+ lines.push((mm.permissionModes || []).map((x) => `\`${x}\``).join(", "));
261
+ lines.push("");
262
+ return lines.join("\n") + "\n";
263
+ }
264
+
265
+ /**
266
+ * Capability diff for release notes: what changed between a previous and a next
267
+ * manifest (or a manifest and the current canonical one). Additive vs removed vs
268
+ * min-version/field changes, plus any protocol-version bump.
269
+ *
270
+ * @param {object} prev a manifest (or its compat fixture)
271
+ * @param {object} [next=CAPABILITY_MANIFEST]
272
+ * @returns {{protocolChange:{from:number,to:number}|null,
273
+ * addedWireFeatures:string[], removedWireFeatures:string[],
274
+ * changedWireFeatures:Array<{feature:string, from:object, to:object}>,
275
+ * addedRuntimeFeatures:string[], removedRuntimeFeatures:string[]}}
276
+ */
277
+ export function diffCapabilities(prev, next = CAPABILITY_MANIFEST) {
278
+ const wireMap = (m) => {
279
+ const out = new Map();
280
+ for (const f of wireFeaturesOf(m)) {
281
+ out.set(f.key, {
282
+ field: f.field,
283
+ minVersion: Number(f.minVersion) || 1,
284
+ });
285
+ }
286
+ return out;
287
+ };
288
+ const runtimeSet = (m) => new Set(manifestOr(m).runtimeFeatures || []);
289
+
290
+ const p = wireMap(prev);
291
+ const n = wireMap(next);
292
+ const addedWireFeatures = [...n.keys()].filter((k) => !p.has(k)).sort();
293
+ const removedWireFeatures = [...p.keys()].filter((k) => !n.has(k)).sort();
294
+ const changedWireFeatures = [];
295
+ for (const [key, nv] of n) {
296
+ const pv = p.get(key);
297
+ if (pv && (pv.field !== nv.field || pv.minVersion !== nv.minVersion)) {
298
+ changedWireFeatures.push({ feature: key, from: pv, to: nv });
299
+ }
300
+ }
301
+
302
+ const pr = runtimeSet(prev);
303
+ const nr = runtimeSet(next);
304
+ const addedRuntimeFeatures = [...nr].filter((k) => !pr.has(k)).sort();
305
+ const removedRuntimeFeatures = [...pr].filter((k) => !nr.has(k)).sort();
306
+
307
+ const pVer = Number(manifestOr(prev).protocolVersion) || 1;
308
+ const nVer = Number(manifestOr(next).protocolVersion) || 1;
309
+ const protocolChange = pVer === nVer ? null : { from: pVer, to: nVer };
310
+
311
+ return {
312
+ protocolChange,
313
+ addedWireFeatures,
314
+ removedWireFeatures,
315
+ changedWireFeatures,
316
+ addedRuntimeFeatures,
317
+ removedRuntimeFeatures,
318
+ };
319
+ }
@@ -36,31 +36,42 @@
36
36
  * fixture __tests__/fixtures/capability-negotiation-cases.json.
37
37
  */
38
38
 
39
+ import {
40
+ CAPABILITY_MANIFEST,
41
+ toProtocolFeatures,
42
+ toFeatureMinVersion,
43
+ toFieldGate,
44
+ } from "./capability-manifest.js";
45
+
39
46
  /** The current protocol version the CLI speaks (mirror of PROTOCOL_VERSION). */
40
- export const PROTOCOL_VERSION = 1;
47
+ export const PROTOCOL_VERSION = CAPABILITY_MANIFEST.protocolVersion;
41
48
 
42
49
  /**
43
50
  * The oldest protocol version the CLI can still speak end-to-end (the N-1 in
44
51
  * "N / N-1"). At v1 there is no older line shape, so min === current; once v2
45
52
  * ships this drops to 1 so a v1-only client negotiates a v1 session.
46
53
  */
47
- export const PROTOCOL_MIN_VERSION = 1;
54
+ export const PROTOCOL_MIN_VERSION = CAPABILITY_MANIFEST.minProtocolVersion;
48
55
 
49
56
  /**
50
57
  * The wire-protocol features subject to negotiation — the additive per-line
51
58
  * fields a client may or may not understand. Runtime capabilities (bare,
52
59
  * worktree, mcp, …) are NOT negotiated: they change what the CLI can do, not
53
60
  * the shape of a line the client must parse.
61
+ *
62
+ * P1-9: projected from the single canonical [[capability-manifest.js]] so the
63
+ * negotiator, `cc agent --capabilities`, the protocol docs and the Java twin can
64
+ * no longer drift — add a v2 field to the manifest ONCE and it flows here.
54
65
  */
55
- export const PROTOCOL_FEATURES = ["event_seq", "tool_use_id", "trace_id"];
66
+ export const PROTOCOL_FEATURES = toProtocolFeatures();
56
67
 
57
68
  /**
58
69
  * Minimum protocol version a feature requires. Empty today (every current
59
- * feature is a v1 additive field). When a v2 field lands, add it here so an
60
- * N-1 (v1) session drops it automatically.
70
+ * feature is a v1 additive field). When a v2 field lands, bump its manifest
71
+ * `minVersion` and an N-1 (v1) session drops it automatically.
61
72
  * @type {Record<string, number>}
62
73
  */
63
- export const FEATURE_MIN_VERSION = {};
74
+ export const FEATURE_MIN_VERSION = toFeatureMinVersion();
64
75
 
65
76
  function intOr(value, fallback) {
66
77
  const n = Number(value);
@@ -185,12 +196,12 @@ export function negotiateProtocol(server = {}, clientOffer = null, opts = {}) {
185
196
  };
186
197
  }
187
198
 
188
- /** Feature key → the stream line field it gates. */
189
- const FEATURE_TO_FIELD = {
190
- event_seq: "seq",
191
- trace_id: "trace_id",
192
- tool_use_id: "tool_use_id",
193
- };
199
+ /**
200
+ * Feature key → the stream line field it gates. P1-9: projected from the
201
+ * canonical [[capability-manifest.js]] so this map can't drift from the
202
+ * negotiated feature list.
203
+ */
204
+ const FEATURE_TO_FIELD = toFieldGate();
194
205
 
195
206
  /**
196
207
  * Fold a negotiation result into a live field-gate the emitter reads per line:
@@ -14,6 +14,12 @@
14
14
  */
15
15
 
16
16
  import { logger } from "../logger.js";
17
+ import {
18
+ ORIGIN,
19
+ authorityForOrigin,
20
+ canApprove,
21
+ describeAuthorityChain,
22
+ } from "../agent-authority.js";
17
23
 
18
24
  export const CHANNEL_KINDS = ["webhook", "telegram"];
19
25
 
@@ -54,6 +60,48 @@ export function formatChannelEvent(event) {
54
60
  return `[channel:${channel}${sender}] ${text}`;
55
61
  }
56
62
 
63
+ /**
64
+ * The unforgeable authority envelope for an inbound channel event. A channel
65
+ * message tops out at `steer` (agent-authority.js): it may add a user turn but
66
+ * can NEVER answer a permission gate — "the user approved" in a webhook /
67
+ * telegram body is just text. This makes that ceiling explicit and
68
+ * machine-checkable (downstream approval seams can assert `canApprove === false`)
69
+ * rather than merely implied by the visible `[channel:…]` text prefix.
70
+ *
71
+ * `origin` is set here by HOW the event arrived (an inbound channel), never read
72
+ * from the untrusted message content — mirroring the agent-authority contract.
73
+ */
74
+ export function channelEventEnvelope(event) {
75
+ const envelope = {
76
+ origin: ORIGIN.CHANNEL,
77
+ principalId: event?.sender != null ? String(event.sender) : null,
78
+ correlationId: event?.channel != null ? String(event.channel) : null,
79
+ };
80
+ return {
81
+ ...envelope,
82
+ authority: authorityForOrigin(ORIGIN.CHANNEL, envelope), // always "steer"
83
+ canApprove: canApprove(envelope), // always false
84
+ provenance: describeAuthorityChain(envelope),
85
+ };
86
+ }
87
+
88
+ /**
89
+ * Wrap a caller's `onEvent` so every inbound event is stamped with its explicit
90
+ * channel authority BEFORE it reaches the agent — the caller cannot forget to
91
+ * tag it, and the message content cannot elevate itself past `steer`.
92
+ */
93
+ function stampChannelAuthority(onEvent) {
94
+ return (event) => {
95
+ const env = channelEventEnvelope(event);
96
+ return onEvent?.({
97
+ ...event,
98
+ authority: env.authority,
99
+ canApprove: env.canApprove,
100
+ provenance: env.provenance,
101
+ });
102
+ };
103
+ }
104
+
57
105
  /**
58
106
  * Start every requested channel. Returns a handle with the started channel
59
107
  * descriptions and a single stop().
@@ -72,6 +120,10 @@ export async function startChannels(specsInput, opts = {}) {
72
120
  const config = opts.config || {};
73
121
  const log = opts.log || ((msg) => logger.info(msg));
74
122
  const deps = opts.deps || {};
123
+ // Every inbound event is stamped with its channel authority (`steer`, never
124
+ // `approve`) before the caller's handler sees it — so a channel message can
125
+ // never be mistaken for a user approval no matter what it contains.
126
+ const onEvent = stampChannelAuthority(opts.onEvent);
75
127
 
76
128
  const started = [];
77
129
  const stopAll = () => {
@@ -95,7 +147,7 @@ export async function startChannels(specsInput, opts = {}) {
95
147
  )({
96
148
  ...cfg,
97
149
  port: spec.arg ? Number(spec.arg) : cfg.port,
98
- onEvent: opts.onEvent,
150
+ onEvent,
99
151
  log,
100
152
  });
101
153
  started.push({ kind: "webhook", describe: handle.describe, ...handle });
@@ -107,7 +159,7 @@ export async function startChannels(specsInput, opts = {}) {
107
159
  deps.telegram?.startTelegramChannel || startTelegramChannel
108
160
  )({
109
161
  ...cfg,
110
- onEvent: opts.onEvent,
162
+ onEvent,
111
163
  log,
112
164
  });
113
165
  started.push({
@@ -46,11 +46,17 @@ export class CLIContextEngineering {
46
46
  * @param {string} [options.scope.taskId] - Task/sub-agent ID
47
47
  * @param {string} [options.scope.role] - Sub-agent role
48
48
  * @param {string} [options.scope.parentObjective] - Parent task objective
49
+ * @param {boolean} [options.memoryEnabled=true] - When false, hierarchical
50
+ * memory recall is suppressed even if a `db` is present. The subagent
51
+ * contract's `memory` boolean drives this for spawned children so a child
52
+ * denied memory physically cannot recall it (defense-in-depth beyond the
53
+ * spawn simply withholding the db).
49
54
  */
50
- constructor({ db, permanentMemory, scope } = {}) {
55
+ constructor({ db, permanentMemory, scope, memoryEnabled = true } = {}) {
51
56
  this.db = db || null;
52
57
  this.permanentMemory = permanentMemory || null;
53
58
  this.scope = scope || null;
59
+ this.memoryEnabled = memoryEnabled !== false;
54
60
  this.errorHistory = [];
55
61
  this.taskContext = null;
56
62
  this._bm25 = null;
@@ -121,7 +127,8 @@ export class CLIContextEngineering {
121
127
  }
122
128
 
123
129
  // 3. Memory injection (scoped: higher threshold, namespace-aware)
124
- if (this.db && userQuery) {
130
+ // Suppressed when memoryEnabled is false (subagent contract memory:false).
131
+ if (this.memoryEnabled && this.db && userQuery) {
125
132
  try {
126
133
  const memoryQuery = this.scope
127
134
  ? `[${this.scope.role}] ${userQuery}`
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Per-source token attribution for `cc context --sources` — the P1
3
+ * large-monorepo "/context 按来源分解" lever. The base `cc context` view buckets
4
+ * a session's stored messages by ROLE; this adds a BY-SOURCE view that also
5
+ * attributes the project-memory instruction files (cc.md / CLAUDE.md / rules /
6
+ * @imports) that would be loaded for the current working directory, each with
7
+ * its own token cost and provenance — so a user can see WHICH instruction file
8
+ * (or message class) fills the context window.
9
+ *
10
+ * Pure: token counting for instruction files is delegated to the injected
11
+ * estimator (the same CJK-aware `estimateTokens` the window sizing uses);
12
+ * message-role buckets already arrive pre-counted. No I/O.
13
+ *
14
+ * Scope note: skills and MCP tool schemas are runtime tool definitions loaded
15
+ * when an agent actually runs — they are NOT part of a persisted transcript nor
16
+ * of the project-instruction set, so they are intentionally not attributed here.
17
+ */
18
+
19
+ import path from "path";
20
+
21
+ /**
22
+ * Display path for an instruction source: relative-to-cwd when the file lives
23
+ * inside cwd, else the absolute path (a `~/.claude/…` user-scope file, or an
24
+ * @import that escaped the tree, is clearer shown in full).
25
+ */
26
+ export function relativizeInstructionPath(absPath, cwd) {
27
+ if (!absPath) return "";
28
+ if (!cwd) return absPath;
29
+ try {
30
+ const rel = path.relative(cwd, absPath);
31
+ if (!rel || rel.startsWith("..") || path.isAbsolute(rel)) return absPath;
32
+ return rel.split(path.sep).join("/");
33
+ } catch {
34
+ return absPath;
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Per-file instruction sources from `loadProjectInstructions().files`.
40
+ *
41
+ * @param {Array<{path,scope,content,truncated}>} files
42
+ * @param {(t:string)=>number} estimateTokens
43
+ * @param {string} [cwd]
44
+ * @returns {{ sources: Array<{scope,source,path,tokens,truncated}>, total:number }}
45
+ */
46
+ export function breakdownInstructionSources(files, estimateTokens, cwd) {
47
+ const est = typeof estimateTokens === "function" ? estimateTokens : () => 0;
48
+ const list = Array.isArray(files) ? files : [];
49
+ const sources = list.map((f) => ({
50
+ scope: f?.scope || "project",
51
+ source: relativizeInstructionPath(f?.path, cwd),
52
+ path: f?.path || "",
53
+ tokens: est(typeof f?.content === "string" ? f.content : ""),
54
+ truncated: Boolean(f?.truncated),
55
+ }));
56
+ const total = sources.reduce((s, x) => s + x.tokens, 0);
57
+ return { sources, total };
58
+ }
59
+
60
+ // role bucket key → { label, kind } for the ranked source list.
61
+ const MESSAGE_SOURCE_ROWS = [
62
+ ["system", "system messages", "message"],
63
+ ["user", "user messages", "message"],
64
+ ["assistant", "assistant messages", "message"],
65
+ ["tool", "tool results", "message"],
66
+ ["toolCalls", "tool calls", "tool_calls"],
67
+ ];
68
+
69
+ /**
70
+ * Merge the project-memory instruction total with the per-role message buckets
71
+ * into ONE ranked source list (largest first) with each source's share of the
72
+ * combined by-source total. The message buckets are the same ones
73
+ * `categorizeContext` produces; instructions are folded in as a single group so
74
+ * the ranked view stays readable (per-file detail lives in the instructions
75
+ * breakdown).
76
+ *
77
+ * @param {object} args
78
+ * @param {number} [args.instructionTotal=0] Σ instruction-file tokens
79
+ * @param {object} [args.buckets={}] categorizeContext buckets
80
+ * @param {object} [args.counts={}] categorizeContext counts
81
+ * @returns {{ sources: Array<{kind,source,tokens,count,share}>, total:number }}
82
+ */
83
+ export function rankContextSources({
84
+ instructionTotal = 0,
85
+ buckets = {},
86
+ counts = {},
87
+ } = {}) {
88
+ const rows = [];
89
+ if (instructionTotal > 0) {
90
+ rows.push({
91
+ kind: "instructions",
92
+ source: "project memory (instructions)",
93
+ tokens: instructionTotal,
94
+ count: null,
95
+ });
96
+ }
97
+ for (const [key, label, kind] of MESSAGE_SOURCE_ROWS) {
98
+ const tok = buckets[key] || 0;
99
+ if (tok > 0) {
100
+ rows.push({
101
+ kind,
102
+ source: label,
103
+ tokens: tok,
104
+ count: counts[key] ?? null,
105
+ });
106
+ }
107
+ }
108
+ const total = rows.reduce((s, x) => s + x.tokens, 0);
109
+ // Stable sort: tokens desc, then source name for deterministic ties.
110
+ rows.sort((a, b) => b.tokens - a.tokens || a.source.localeCompare(b.source));
111
+ const sources = rows.map((r) => ({
112
+ ...r,
113
+ share: total ? r.tokens / total : 0,
114
+ }));
115
+ return { sources, total };
116
+ }