chainlesschain 0.166.100 → 0.166.102

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 (187) hide show
  1. package/package.json +3 -3
  2. package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
  3. package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
  4. package/src/assets/web-panel/assets/{AIOps-Cd4iUOPt.js → AIOps-CyHIMEd8.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton--ucr-zko.js → ActionButton-vuNxDpHm.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-DbejYMWk.js → Analytics-D0quEM0q.js} +3 -3
  7. package/src/assets/web-panel/assets/{AppLayout-CLgKxeGw.js → AppLayout-xRSVpbCs.js} +5 -5
  8. package/src/assets/web-panel/assets/{Artifacts-CTT5BIL5.js → Artifacts-ktfVAZBC.js} +1 -1
  9. package/src/assets/web-panel/assets/{Audit-DP-WBWe9.js → Audit-UJW6maH4.js} +1 -1
  10. package/src/assets/web-panel/assets/{BackgroundAgents-B6VqheJk.js → BackgroundAgents-BYrfdCoT.js} +1 -1
  11. package/src/assets/web-panel/assets/{Backup-VWJK5zim.js → Backup-IBgsJ7BK.js} +1 -1
  12. package/src/assets/web-panel/assets/{BaseInput-YGFO9RHd.js → BaseInput-BmP8_zxy.js} +1 -1
  13. package/src/assets/web-panel/assets/{Chat-CVfydnCd.js → Chat-urkw8_BF.js} +5 -5
  14. package/src/assets/web-panel/assets/{ChatBubbleRenderer-BICpB-qU.js → ChatBubbleRenderer-Cw44zZbh.js} +1 -1
  15. package/src/assets/web-panel/assets/{Checkbox-Bd5vKRMk.js → Checkbox-CYboo-__.js} +1 -1
  16. package/src/assets/web-panel/assets/{Codegen-DHNgPHvg.js → Codegen-DaqR_Ay8.js} +1 -1
  17. package/src/assets/web-panel/assets/{Col-CA2BYQ8T.js → Col-04BSIj_z.js} +1 -1
  18. package/src/assets/web-panel/assets/{Community-DnKJ-qpI.js → Community-DxFk7Trv.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compact-C9BZ8t4r.js → Compact-mjgWlMCB.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compliance-ByyQ2FOl.js → Compliance-CC5ee7QV.js} +1 -1
  21. package/src/assets/web-panel/assets/{Cowork-rXTwXE_c.js → Cowork-BK4BhHZd.js} +2 -2
  22. package/src/assets/web-panel/assets/{Cron-BuW-HODy.js → Cron-CP6jAxq0.js} +2 -2
  23. package/src/assets/web-panel/assets/{Crosschain-OudNtbYW.js → Crosschain-DJPaViZS.js} +1 -1
  24. package/src/assets/web-panel/assets/{DID-BQ6BxYNN.js → DID-BTLxkuOj.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dashboard-Cz5HG8tz.js → Dashboard-Djkiqh3d.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dropdown-BzclHOVv.js → Dropdown-t_eUhqom.js} +1 -1
  27. package/src/assets/web-panel/assets/{EmailListRenderer-CbJETFdy.js → EmailListRenderer-7w6USx_J.js} +1 -1
  28. package/src/assets/web-panel/assets/{EvolutionSettings-Dx_pJG3d.js → EvolutionSettings-mU5IHEk5.js} +1 -1
  29. package/src/assets/web-panel/assets/{FamilyGuardDashboard-6JCS1MNg.js → FamilyGuardDashboard-BCh-VBBC.js} +1 -1
  30. package/src/assets/web-panel/assets/{Federation-BrPkMYaf.js → Federation-Be_VpjI2.js} +1 -1
  31. package/src/assets/web-panel/assets/{FormItemContext-Bhc9pobs.js → FormItemContext-D_lzQ7PI.js} +1 -1
  32. package/src/assets/web-panel/assets/{GenericCardRenderer-BxOh07uQ.js → GenericCardRenderer-LYu3KapV.js} +1 -1
  33. package/src/assets/web-panel/assets/{Git-D_idoujr.js → Git-BBeF-PP4.js} +2 -2
  34. package/src/assets/web-panel/assets/{Governance-ZGfIRE-x.js → Governance-CoF8Kzg7.js} +1 -1
  35. package/src/assets/web-panel/assets/{Inference-DpAmcwbw.js → Inference-C4DLMnXS.js} +1 -1
  36. package/src/assets/web-panel/assets/{KnowledgeGraph-D1S1UTgP.js → KnowledgeGraph-B2mlNewk.js} +1 -1
  37. package/src/assets/web-panel/assets/{Logs-2sc8V5XV.js → Logs-DMZ_44Ya.js} +2 -2
  38. package/src/assets/web-panel/assets/MarkdownRenderer-Ck7Iv_9e.js +1 -0
  39. package/src/assets/web-panel/assets/{Marketplace-0xlFUKbe.js → Marketplace-BqDzTew_.js} +1 -1
  40. package/src/assets/web-panel/assets/{McpTools-D25eJLGm.js → McpTools-BbwSbDN9.js} +3 -3
  41. package/src/assets/web-panel/assets/{Memory-BLRGd9hM.js → Memory-DAaTWgrm.js} +2 -2
  42. package/src/assets/web-panel/assets/{MobileBridge-zpFINGzn.js → MobileBridge-BjbTGxoR.js} +1 -1
  43. package/src/assets/web-panel/assets/{MobileProjects-Cbyd-8kx.js → MobileProjects-DMODOBr-.js} +1 -1
  44. package/src/assets/web-panel/assets/{Mtc-DgXgUlHc.js → Mtc-DT9N2rCs.js} +2 -2
  45. package/src/assets/web-panel/assets/{MtcAudit-DzcL-dKH.js → MtcAudit-DagMfUVv.js} +2 -2
  46. package/src/assets/web-panel/assets/{Multisig-C3OrZ6VN.js → Multisig-C1BKP6nM.js} +3 -3
  47. package/src/assets/web-panel/assets/{NLProgramming-Bqp_vWA7.js → NLProgramming-B5LFh72i.js} +1 -1
  48. package/src/assets/web-panel/assets/{Notes-Dyn45-Ht.js → Notes-Q77V3ltW.js} +3 -3
  49. package/src/assets/web-panel/assets/{NotificationSettings-CLjafGZr.js → NotificationSettings-HxdpNIBs.js} +1 -1
  50. package/src/assets/web-panel/assets/OrderTableRenderer-Dc0DpvBH.js +1 -0
  51. package/src/assets/web-panel/assets/{Organization-5gr9hyLm.js → Organization-QL3NZ7uW.js} +4 -4
  52. package/src/assets/web-panel/assets/{Overflow-BRdU02hT.js → Overflow-B_gqOKho.js} +1 -1
  53. package/src/assets/web-panel/assets/{P2P-DIi7fzh6.js → P2P-BBJubU8Z.js} +2 -2
  54. package/src/assets/web-panel/assets/{PdhVaultBrowser-BCbS1KpA.js → PdhVaultBrowser-CFnGd-2E.js} +3 -3
  55. package/src/assets/web-panel/assets/{Permissions-BjeP9VtA.js → Permissions-BKkznIUM.js} +4 -4
  56. package/src/assets/web-panel/assets/{PersonalDataHub-y8PXOQUc.js → PersonalDataHub-DYK7ZAcd.js} +4 -4
  57. package/src/assets/web-panel/assets/{Pipeline-B0fL5uxY.js → Pipeline-CoeKpjoN.js} +1 -1
  58. package/src/assets/web-panel/assets/{Privacy-C8jCDn8Z.js → Privacy-Diw4G-92.js} +1 -1
  59. package/src/assets/web-panel/assets/{ProjectInit-B_L6Dc6V.js → ProjectInit-CHBOFkma.js} +2 -2
  60. package/src/assets/web-panel/assets/{ProjectSettings-Bb1CYbZh.js → ProjectSettings-BJIsgdOf.js} +2 -2
  61. package/src/assets/web-panel/assets/{Projects-CUSV10Cn.js → Projects-GJjItXIk.js} +1 -1
  62. package/src/assets/web-panel/assets/{Providers-mBSTDJ0E.js → Providers-o8QCimor.js} +1 -1
  63. package/src/assets/web-panel/assets/{QrScannerModal-CHxgalvt.js → QrScannerModal-z2W-zvhW.js} +1 -1
  64. package/src/assets/web-panel/assets/{QuickAsk-DI9KIMEV.js → QuickAsk-_yubhsna.js} +1 -1
  65. package/src/assets/web-panel/assets/{Recommend-B5_zW1JH.js → Recommend-CucgJwih.js} +1 -1
  66. package/src/assets/web-panel/assets/{RemoteSession-BkH4bmM5.js → RemoteSession-EzfIIRg1.js} +2 -2
  67. package/src/assets/web-panel/assets/{Reputation-DJrAqwAq.js → Reputation-_shttE67.js} +1 -1
  68. package/src/assets/web-panel/assets/{Row-xZ3MAM34.js → Row-DQA_S8-9.js} +1 -1
  69. package/src/assets/web-panel/assets/{RssFeed-CCsrLLiu.js → RssFeed-BOqWawXT.js} +3 -3
  70. package/src/assets/web-panel/assets/{Search-CTCRKvaP.js → Search-Dx1v2xOq.js} +1 -1
  71. package/src/assets/web-panel/assets/{Security-D7joyfp2.js → Security-Bt4HHsT4.js} +4 -4
  72. package/src/assets/web-panel/assets/{Services-oqHPmTG4.js → Services-sruHiQ-r.js} +2 -2
  73. package/src/assets/web-panel/assets/{Skeleton-BR_32bTG.js → Skeleton-CiBxvmOJ.js} +1 -1
  74. package/src/assets/web-panel/assets/{Skills-BoRz9mln.js → Skills-De9qKODU.js} +1 -1
  75. package/src/assets/web-panel/assets/{Sla-UAGUHZ9b.js → Sla-B_6yn8Wp.js} +1 -1
  76. package/src/assets/web-panel/assets/{SpeechSettings-DeP_rMgv.js → SpeechSettings-C2CafExS.js} +1 -1
  77. package/src/assets/web-panel/assets/{SyncSettings-CSzzMmeA.js → SyncSettings-Dhh3Qmb0.js} +2 -2
  78. package/src/assets/web-panel/assets/{Tasks-CcqOLsLB.js → Tasks-Mvo5mTWm.js} +1 -1
  79. package/src/assets/web-panel/assets/{Templates-cDbkGSDG.js → Templates-D7WVTQQy.js} +1 -1
  80. package/src/assets/web-panel/assets/{Tenant-DmOy58cq.js → Tenant-7ur9Yfxd.js} +1 -1
  81. package/src/assets/web-panel/assets/{Terminal-CsRZH5vr.js → Terminal-BgzrOA6k.js} +2 -2
  82. package/src/assets/web-panel/assets/{TimelineRenderer-BgJrk6HG.js → TimelineRenderer-Dco20pT1.js} +1 -1
  83. package/src/assets/web-panel/assets/{Tokens-CCQglKDE.js → Tokens-hN6qBPag.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trigger-t-Gt3oBY.js → Trigger-C4f_twAM.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trust-DQgu2kI0.js → Trust-Wf1SMypp.js} +1 -1
  86. package/src/assets/web-panel/assets/{UkeySign-Cod2WUGj.js → UkeySign-DUXSyg3N.js} +1 -1
  87. package/src/assets/web-panel/assets/{VideoEditing-SGN5zaVK.js → VideoEditing-BvqsJaL0.js} +1 -1
  88. package/src/assets/web-panel/assets/{Wallet-CnLEL-LD.js → Wallet-CgAbcjKl.js} +3 -3
  89. package/src/assets/web-panel/assets/{WebAuthn-C2keUpD6.js → WebAuthn-DaLT0W3s.js} +2 -2
  90. package/src/assets/web-panel/assets/{WorkflowEditor-B1GvrwWJ.js → WorkflowEditor-CQqAXoaS.js} +1 -1
  91. package/src/assets/web-panel/assets/{chat-1E9_P_qY.js → chat-BhlohFTB.js} +1 -1
  92. package/src/assets/web-panel/assets/{colors-DuU6Os4q.js → colors-D7HqXIL8.js} +1 -1
  93. package/src/assets/web-panel/assets/{compact-item-C5NfOAcM.js → compact-item-Bqk4FCLY.js} +1 -1
  94. package/src/assets/web-panel/assets/{createContext-D4Fxz9qQ.js → createContext-CEmWrWf0.js} +1 -1
  95. package/src/assets/web-panel/assets/devWarning-YPX_TU7w.js +1 -0
  96. package/src/assets/web-panel/assets/{hasIn-C6C49iFk.js → hasIn-CDY0pFi2.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-DP2DCKD-.js → index-1HBam9t1.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-B-bb-R99.js → index-6f6n0KFR.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BmvU4Tp_.js → index-B8L3_-sG.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BsH8mFp4.js → index-BHGOdvOQ.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-BVE2wCeb.js → index-BNrvBWDS.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CJS6GTpv.js → index-BPmRkxeX.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-C7mh6xlu.js → index-BXRooi-O.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-BZKRZYTX.js → index-BiLu-ImR.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-jFg3CPlQ.js → index-BuKGuH_y.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-BULggEX6.js → index-BxXFRLTZ.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DPzunJER.js → index-BxYO6nde.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-AO6iDCSL.js → index-C02yDu4f.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-BU5mPkNX.js → index-C3opQg47.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-DSypQU1h.js → index-C9mvnSii.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-DZgT7pH-.js → index-CVrwozwH.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-CpiOzt7U.js → index-CYcjOnDX.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-BlHkc48f.js → index-Cf1ha8l0.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-CXb8gEWh.js → index-Chxt0t-A.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-HQXFl8fh.js → index-CkjgSHVz.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-DpaGe-dr.js → index-CkqBoCiu.js} +3 -3
  117. package/src/assets/web-panel/assets/{index-C2nO02uW.js → index-CqK0J4Sj.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-Bu6qMjf4.js → index-CrsM-oiD.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-Bk-paNL3.js → index-Cur88hoN.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CXn-e3ki.js → index-D0nfNmbq.js} +1 -1
  121. package/src/assets/web-panel/assets/index-D53szVZQ.js +1 -0
  122. package/src/assets/web-panel/assets/{index-CDVwN9Sv.js → index-DEzL7s7P.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-B_ON9La1.js → index-DGKRAO61.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-CQJoh5rw.js → index-DPBoWNwq.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-cnDfwWU5.js → index-DRcDWMwP.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-BBVqlelF.js → index-DmKdCWq1.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-BYg1dtne.js → index-DpI1LqJX.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-B5lzRoHp.js → index-DuMt3ewl.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-gh11zJ9h.js → index-Dwob5XoD.js} +1 -1
  130. package/src/assets/web-panel/assets/index-Ub2nJbV2.js +1 -0
  131. package/src/assets/web-panel/assets/{index-D1TXgNPA.js → index-XErJQ1yF.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-DFK6PTGJ.js → index-aBHlgMrq.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-Dh-vezHe.js → index-e9oCy7_4.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-bW6vfpLH.js → index-lBAbMOzg.js} +1 -1
  135. package/src/assets/web-panel/assets/{index-lNmDaf3J.js → index-o_lc3eww.js} +1 -1
  136. package/src/assets/web-panel/assets/{initDefaultProps-3DSfnIpD.js → initDefaultProps-CIeEUxIN.js} +1 -1
  137. package/src/assets/web-panel/assets/{motion-DxGLmgA0.js → motion-IPIj1ZtP.js} +1 -1
  138. package/src/assets/web-panel/assets/{move-DrlLG6m5.js → move-BfSeXZ-f.js} +1 -1
  139. package/src/assets/web-panel/assets/{mtc-parser-BITbrJSb.js → mtc-parser-DX03-Xp4.js} +1 -1
  140. package/src/assets/web-panel/assets/{omit-D7k5vIbk.js → omit-z9EannfX.js} +1 -1
  141. package/src/assets/web-panel/assets/{pickAttrs-BJSvYFWo.js → pickAttrs-DXKmRkqZ.js} +1 -1
  142. package/src/assets/web-panel/assets/{placementArrow-Bf4to1jA.js → placementArrow-k2HV7cIU.js} +1 -1
  143. package/src/assets/web-panel/assets/{responsiveObserve-BXzeyzTa.js → responsiveObserve-bX7CsyWy.js} +1 -1
  144. package/src/assets/web-panel/assets/{slide-DLzNUNdj.js → slide-NskjQLbJ.js} +1 -1
  145. package/src/assets/web-panel/assets/{statusUtils-wBBnrRm_.js → statusUtils-B3IoG-Er.js} +1 -1
  146. package/src/assets/web-panel/assets/{styleChecker-BnmJzXNr.js → styleChecker-DHv_UilX.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFlexGapSupport-DrN8MrJb.js → useFlexGapSupport-DEqGB5Ng.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFs-dnkYGkjY.js → useFs-Bl9CbrqZ.js} +1 -1
  149. package/src/assets/web-panel/assets/{usePersonalDataHub-k_xkv7-k.js → usePersonalDataHub-O-Ukv93M.js} +1 -1
  150. package/src/assets/web-panel/assets/{vnode-B-v8PXpK.js → vnode-hGCHTaZt.js} +1 -1
  151. package/src/assets/web-panel/assets/{zoom-Coue8wAK.js → zoom-BWhIVeKQ.js} +1 -1
  152. package/src/assets/web-panel/index.html +1 -1
  153. package/src/command-help-index.json +1 -1
  154. package/src/commands/agent.js +64 -40
  155. package/src/commands/eval.js +11 -8
  156. package/src/data/changelog.json +26 -0
  157. package/src/harness/provider-backed-compaction.js +13 -5
  158. package/src/lib/config-schema.js +18 -5
  159. package/src/lib/context-memory-kernel/live-compaction.js +142 -61
  160. package/src/lib/context-memory-kernel/memory-query-index.js +5 -2
  161. package/src/lib/context-memory-kernel/runtime.js +4 -0
  162. package/src/lib/context-memory-kernel/segmented-memory-port.js +28 -3
  163. package/src/lib/context-source-ledger.js +52 -9
  164. package/src/lib/formal-budget-authority.js +533 -0
  165. package/src/lib/formal-budget-contract.js +609 -0
  166. package/src/lib/formal-budget-transport.js +345 -0
  167. package/src/lib/goal-condition-engine.js +25 -2
  168. package/src/lib/llm-config-defaults.js +10 -4
  169. package/src/lib/llm-pricing.js +16 -4
  170. package/src/lib/model-capabilities.js +26 -0
  171. package/src/lib/model-catalog-review.js +18 -1
  172. package/src/lib/model-context-catalog.js +41 -1
  173. package/src/lib/openai-responses.js +8 -0
  174. package/src/lib/skill-retrieval-router.js +1 -0
  175. package/src/lib/usage-pricing-context.js +33 -2
  176. package/src/repl/agent-repl.js +247 -153
  177. package/src/runtime/agent-core.js +371 -97
  178. package/src/runtime/coding-agent-contract-shared.cjs +14 -1
  179. package/src/runtime/headless-runner.js +1 -0
  180. package/src/runtime/headless-stream.js +137 -4
  181. package/src/runtime/mcp-tool-search.js +0 -0
  182. package/src/runtime/provider-stream-state.js +14 -1
  183. package/src/assets/web-panel/assets/MarkdownRenderer-575jjYE6.js +0 -1
  184. package/src/assets/web-panel/assets/OrderTableRenderer-Bx8wMauC.js +0 -1
  185. package/src/assets/web-panel/assets/devWarning-zDWbYMr7.js +0 -1
  186. package/src/assets/web-panel/assets/index-BPBsZZnT.js +0 -1
  187. package/src/assets/web-panel/assets/index-CtGQDg7m.js +0 -1
@@ -2,6 +2,7 @@ import { randomUUID } from "node:crypto";
2
2
  import {
3
3
  canonicalDigest,
4
4
  InMemorySessionContextPort,
5
+ getCompactionPlanRejection,
5
6
  } from "@chainlesschain/context-memory-kernel";
6
7
  import { sessionExists } from "../../harness/jsonl-session-store.js";
7
8
  import {
@@ -11,6 +12,17 @@ import {
11
12
  } from "./message-adapter.js";
12
13
  import { JsonlSessionContextPort } from "./jsonl-session-context-port.js";
13
14
  import { createCliContextMemoryRuntime } from "./runtime.js";
15
+ import { projectRuntimeTokenUsage } from "../runtime-usage-ledger.js";
16
+
17
+ const rejectedCompactionUsage = new WeakMap();
18
+
19
+ // Only the owned canonical adapter can associate an error with its completed
20
+ // summarizer. A caller-supplied error property is never a settlement authority.
21
+ export function getRejectedCompactionUsage(error) {
22
+ return error && typeof error === "object"
23
+ ? rejectedCompactionUsage.get(error) || null
24
+ : null;
25
+ }
14
26
 
15
27
  function estimatedTokens(messages) {
16
28
  return Math.max(
@@ -20,7 +32,9 @@ function estimatedTokens(messages) {
20
32
  typeof message?.content === "string"
21
33
  ? message.content
22
34
  : JSON.stringify(message?.content ?? "");
23
- return total + Math.max(1, Math.ceil(Buffer.byteLength(content, "utf8") / 4));
35
+ return (
36
+ total + Math.max(1, Math.ceil(Buffer.byteLength(content, "utf8") / 4))
37
+ );
24
38
  }, 0),
25
39
  );
26
40
  }
@@ -125,13 +139,22 @@ class CallbackSessionContextPort extends InMemorySessionContextPort {
125
139
  }
126
140
 
127
141
  function kernelBudget(compressor) {
128
- const inputBudget = Math.max(256, Math.trunc(Number(compressor?.maxTokens)) || 16_384);
129
- const reservedOutputTokens = Math.max(1, Math.min(2048, Math.floor(inputBudget / 10)));
142
+ const inputBudget = Math.max(
143
+ 256,
144
+ Math.trunc(Number(compressor?.maxTokens)) || 16_384,
145
+ );
146
+ const reservedOutputTokens = Math.max(
147
+ 1,
148
+ Math.min(2048, Math.floor(inputBudget / 10)),
149
+ );
130
150
  return {
131
151
  modelWindowTokens: inputBudget + reservedOutputTokens,
132
152
  reservedOutputTokens,
133
153
  safetyMarginTokens: 0,
134
- recoveryReserveTokens: Math.min(256, Math.max(1, Math.floor(inputBudget * 0.05))),
154
+ recoveryReserveTokens: Math.min(
155
+ 256,
156
+ Math.max(1, Math.floor(inputBudget * 0.05)),
157
+ ),
135
158
  };
136
159
  }
137
160
 
@@ -175,7 +198,10 @@ function usageReceipt(stats, provider, model) {
175
198
  * summarizer for the Kernel-selected dropped partition; it cannot commit or
176
199
  * choose the authoritative output on its own.
177
200
  */
178
- export async function compactLiveMessagesCanonical(messagesInput, options = {}) {
201
+ export async function compactLiveMessagesCanonical(
202
+ messagesInput,
203
+ options = {},
204
+ ) {
179
205
  const messages = Array.isArray(messagesInput) ? [...messagesInput] : [];
180
206
  const sessionId = String(options.sessionId || `live-${randomUUID()}`);
181
207
  const operationId = String(options.operationId || `compact-${randomUUID()}`);
@@ -185,10 +211,13 @@ export async function compactLiveMessagesCanonical(messagesInput, options = {})
185
211
  new Date(Number((options.clock || Date.now)())).toISOString();
186
212
  const compressor = options.compressor;
187
213
  if (!compressor || typeof compressor.compress !== "function") {
188
- throw new TypeError("canonical live compaction requires a compatibility summarizer");
214
+ throw new TypeError(
215
+ "canonical live compaction requires a compatibility summarizer",
216
+ );
189
217
  }
190
218
 
191
219
  let summaryStats = null;
220
+ let summaryReceipt = null;
192
221
  let runtime;
193
222
  let verifiedAuthoritySnapshot = null;
194
223
  const persistentSession =
@@ -227,9 +256,7 @@ export async function compactLiveMessagesCanonical(messagesInput, options = {})
227
256
  memoryPort: bootstrapRuntime.memoryPort,
228
257
  sessionPort,
229
258
  });
230
- } else if (
231
- persistentSession
232
- ) {
259
+ } else if (persistentSession) {
233
260
  runtime = createCliContextMemoryRuntime({
234
261
  sessionId,
235
262
  scopeKey: `cli:session:${sessionId}`,
@@ -265,13 +292,13 @@ export async function compactLiveMessagesCanonical(messagesInput, options = {})
265
292
  });
266
293
  }
267
294
  if (!runtime.decision.canonical) {
268
- const error = new Error("canonical live compaction is not authoritative for this cohort");
295
+ const error = new Error(
296
+ "canonical live compaction is not authoritative for this cohort",
297
+ );
269
298
  error.code = "legacy_writer_fenced";
270
299
  throw error;
271
300
  }
272
- if (
273
- persistentSession
274
- ) {
301
+ if (persistentSession) {
275
302
  const authority =
276
303
  verifiedAuthoritySnapshot ||
277
304
  (await runtime.sessionPort.readSnapshot(sessionId));
@@ -296,52 +323,102 @@ export async function compactLiveMessagesCanonical(messagesInput, options = {})
296
323
  const provider = options.provider || "provider.local";
297
324
  const model = options.model || "default";
298
325
  const memoryRevision = await runtime.memoryPort.getRevision();
299
- const receipt = await runtime.kernel.compactContext({
300
- operationId,
301
- sessionId,
302
- ...kernelBudget(compressor),
303
- sink: provider,
304
- scopeAdmissions: [{ scope: "session", scopeId: sessionId }],
305
- policyVersion: "cli-context-policy-v1",
306
- modelProfile: model,
307
- memoryRevision,
308
- allowFallback: false,
309
- now: operationNow,
310
- metadata: {
311
- inputMessageCount: messages.length,
312
- originalTokens: estimatedTokens(messages),
313
- trigger,
314
- provider,
315
- model,
316
- },
317
- summarizer: async (droppedItems, context) => {
318
- const droppedMessages = contextItemsToMessages(droppedItems);
319
- const result = await compressor.compress(droppedMessages, {
320
- preserveToolPairs: true,
321
- ...(options.compressOptions || {}),
322
- });
323
- summaryStats = result.stats || {};
324
- const reduced =
325
- Number(summaryStats.saved || 0) > 0 ||
326
- result.messages.length < droppedMessages.length;
327
- const item = reduced
328
- ? createSummaryContextItem({
329
- messages: result.messages,
330
- parents: droppedItems,
331
- operationId: context.operationId,
332
- now: operationNow,
333
- })
334
- : null;
335
- return {
336
- items: item ? [item] : [],
337
- usageReceipt: usageReceipt(summaryStats, provider, model),
338
- degraded: summaryStats.degraded === true,
339
- ...(summaryStats.degradedReason
340
- ? { degradedReason: String(summaryStats.degradedReason).slice(0, 160) }
341
- : {}),
342
- };
343
- },
344
- });
326
+ let receipt;
327
+ try {
328
+ receipt = await runtime.kernel.compactContext({
329
+ operationId,
330
+ sessionId,
331
+ ...kernelBudget(compressor),
332
+ sink: provider,
333
+ scopeAdmissions: [{ scope: "session", scopeId: sessionId }],
334
+ policyVersion: "cli-context-policy-v1",
335
+ modelProfile: model,
336
+ memoryRevision,
337
+ allowFallback: false,
338
+ now: operationNow,
339
+ metadata: {
340
+ inputMessageCount: messages.length,
341
+ originalTokens: estimatedTokens(messages),
342
+ trigger,
343
+ provider,
344
+ model,
345
+ },
346
+ summarizer: async (droppedItems, context) => {
347
+ const droppedMessages = contextItemsToMessages(droppedItems);
348
+ const result = await compressor.compress(droppedMessages, {
349
+ preserveToolPairs: true,
350
+ ...(options.compressOptions || {}),
351
+ });
352
+ summaryStats = result.stats || {};
353
+ summaryReceipt = usageReceipt(summaryStats, provider, model);
354
+ const reduced =
355
+ Number(summaryStats.saved || 0) > 0 ||
356
+ result.messages.length < droppedMessages.length;
357
+ const item = reduced
358
+ ? createSummaryContextItem({
359
+ messages: result.messages,
360
+ parents: droppedItems,
361
+ operationId: context.operationId,
362
+ now: operationNow,
363
+ })
364
+ : null;
365
+ return {
366
+ items: item ? [item] : [],
367
+ usageReceipt: summaryReceipt,
368
+ degraded: summaryStats.degraded === true,
369
+ ...(summaryStats.degradedReason
370
+ ? {
371
+ degradedReason: String(summaryStats.degradedReason).slice(
372
+ 0,
373
+ 160,
374
+ ),
375
+ }
376
+ : {}),
377
+ };
378
+ },
379
+ });
380
+ } catch (error) {
381
+ const rejection = getCompactionPlanRejection(error);
382
+ if (
383
+ rejection?.operationId === operationId &&
384
+ rejection.sessionId === sessionId &&
385
+ summaryReceipt !== null &&
386
+ rejection.usageReceipt &&
387
+ canonicalDigest(rejection.usageReceipt) ===
388
+ canonicalDigest(summaryReceipt) &&
389
+ summaryStats?.summaryUsageUnknown !== true
390
+ ) {
391
+ try {
392
+ const usage = projectRuntimeTokenUsage({
393
+ ...(summaryStats.summaryCallId
394
+ ? { callId: summaryStats.summaryCallId }
395
+ : {}),
396
+ provider: summaryStats.summaryProvider || provider,
397
+ model: summaryStats.summaryModel || model,
398
+ source: "semantic-compaction",
399
+ usage: {
400
+ input_tokens: summaryStats.summaryUsage?.inputTokens,
401
+ output_tokens: summaryStats.summaryUsage?.outputTokens,
402
+ cache_read_input_tokens:
403
+ summaryStats.summaryUsage?.cacheReadTokens ?? 0,
404
+ cache_creation_input_tokens:
405
+ summaryStats.summaryUsage?.cacheCreationTokens ?? 0,
406
+ },
407
+ });
408
+ rejectedCompactionUsage.set(
409
+ error,
410
+ Object.freeze({
411
+ ...usage,
412
+ usage: Object.freeze(usage.usage),
413
+ receipt: Object.freeze({ ...summaryReceipt }),
414
+ }),
415
+ );
416
+ } catch {
417
+ // Missing or invalid usage retains the caller's unknown outcome path.
418
+ }
419
+ }
420
+ throw error;
421
+ }
345
422
  if (!["committed", "degraded"].includes(receipt.status)) {
346
423
  return {
347
424
  messages,
@@ -361,12 +438,16 @@ export async function compactLiveMessagesCanonical(messagesInput, options = {})
361
438
  messages: outputMessages,
362
439
  stats: {
363
440
  ...(summaryStats || {}),
364
- strategy: receipt.status === "degraded" ? "deterministic-fallback" : "canonical",
441
+ strategy:
442
+ receipt.status === "degraded" ? "deterministic-fallback" : "canonical",
365
443
  originalMessages: messages.length,
366
444
  compressedMessages: outputMessages.length,
367
445
  originalTokens: estimatedTokens(messages),
368
446
  compressedTokens: estimatedTokens(outputMessages),
369
- saved: Math.max(0, estimatedTokens(messages) - estimatedTokens(outputMessages)),
447
+ saved: Math.max(
448
+ 0,
449
+ estimatedTokens(messages) - estimatedTokens(outputMessages),
450
+ ),
370
451
  canonicalAlreadySettled: true,
371
452
  canonicalReceipt: receipt,
372
453
  },
@@ -2,6 +2,9 @@ import { createHash } from "node:crypto";
2
2
 
3
3
  export const MEMORY_QUERY_INDEX_SCHEMA = "chainlesschain.memory-query-index/v1";
4
4
  const CURSOR_SCHEMA = "chainlesschain.memory-list-cursor/v1";
5
+ // Preserve the existing English collation while avoiding constructing locale
6
+ // options for every comparison during shard sorts, cursor search and merging.
7
+ const memoryRowCollator = new Intl.Collator("en");
5
8
 
6
9
  export function queryDigest(bytes) {
7
10
  return `sha256:${createHash("sha256").update(bytes).digest("hex")}`;
@@ -10,8 +13,8 @@ export function queryDigest(bytes) {
10
13
  export function compareMemoryRows(left, right) {
11
14
  return (
12
15
  right.importance - left.importance ||
13
- right.updatedAt.localeCompare(left.updatedAt, "en") ||
14
- left.memoryId.localeCompare(right.memoryId, "en")
16
+ memoryRowCollator.compare(right.updatedAt, left.updatedAt) ||
17
+ memoryRowCollator.compare(left.memoryId, right.memoryId)
15
18
  );
16
19
  }
17
20
 
@@ -22,6 +22,10 @@ export function createCliContextMemoryRuntime(options = {}) {
22
22
  const memoryPort =
23
23
  options.memoryPort ||
24
24
  new SegmentedMemoryPort({
25
+ queryIndexCacheMode:
26
+ options.memoryQueryIndexCacheMode ||
27
+ (options.env || process.env).CC_CONTEXT_MEMORY_QUERY_CACHE ||
28
+ "validate-disk",
25
29
  readOnly: !decision.canonical,
26
30
  ...(options.memoryFilePath ? { filePath: options.memoryFilePath } : {}),
27
31
  });
@@ -170,6 +170,7 @@ export class SegmentedMemoryPort extends DurableJsonMemoryPort {
170
170
  maxTotalBytes = DEFAULT_MAX_TOTAL_BYTES,
171
171
  maxEvents = DEFAULT_SEGMENTED_MAX_EVENTS,
172
172
  readOnly = false,
173
+ queryIndexCacheMode = "validate-disk",
173
174
  ...options
174
175
  } = {}) {
175
176
  super({ ...options, maxEvents });
@@ -177,6 +178,9 @@ export class SegmentedMemoryPort extends DurableJsonMemoryPort {
177
178
  throw new TypeError("maxTotalBytes must be a positive safe integer");
178
179
  this.maxTotalBytes = maxTotalBytes;
179
180
  this.readOnly = Boolean(readOnly);
181
+ if (!["validate-disk", "verified-memory"].includes(queryIndexCacheMode))
182
+ throw new TypeError("Unknown query index cache mode");
183
+ this.queryIndexCacheMode = queryIndexCacheMode;
180
184
  this.filePath = resolve(this.filePath);
181
185
  this.shardDirectory = `${this.filePath}.shards`;
182
186
  this._queryIndexes = new Map();
@@ -656,6 +660,27 @@ export class SegmentedMemoryPort extends DurableJsonMemoryPort {
656
660
 
657
661
  _readQueryIndex(manifest, bucket) {
658
662
  const descriptor = manifest.shards[bucket];
663
+ const binding = JSON.stringify([
664
+ manifest.digest,
665
+ manifest.storeRevision,
666
+ descriptor.digest,
667
+ descriptor.queryDigest,
668
+ descriptor.queryBytes,
669
+ descriptor.recordCount,
670
+ ]);
671
+ const cached = this._queryIndexes.get(bucket);
672
+ // This is an already verified, host-owned decoded snapshot, never a trust
673
+ // decision based on filesystem timestamps. Re-read and verify the current
674
+ // manifest on every operation; any generation/authority change invalidates
675
+ // this binding. Selected authority shards are still read and verified.
676
+ // Disk repair remains eager in validate-disk mode; verified-memory repairs
677
+ // a derived index on the next cache miss, rather than every warm query.
678
+ if (
679
+ this.queryIndexCacheMode === "verified-memory" &&
680
+ descriptor.queryDigest &&
681
+ cached?.binding === binding
682
+ )
683
+ return cached.index;
659
684
  let bytes;
660
685
  if (descriptor.queryDigest) {
661
686
  const file = this._queryIndexPath(bucket, descriptor);
@@ -705,8 +730,8 @@ export class SegmentedMemoryPort extends DurableJsonMemoryPort {
705
730
  bytes = encodeQueryIndex(this._readShard(manifest, bucket));
706
731
  }
707
732
  const digest = descriptor.queryDigest || queryDigest(bytes);
708
- const cached = this._queryIndexes.get(bucket);
709
- if (cached?.digest === digest) return cached.index;
733
+ if (cached?.digest === digest && cached.binding === binding)
734
+ return cached.index;
710
735
  let index;
711
736
  try {
712
737
  index = compileQueryIndex(bytes, descriptor);
@@ -717,7 +742,7 @@ export class SegmentedMemoryPort extends DurableJsonMemoryPort {
717
742
  cause,
718
743
  );
719
744
  }
720
- this._queryIndexes.set(bucket, { digest, index });
745
+ this._queryIndexes.set(bucket, { digest, binding, index });
721
746
  return index;
722
747
  }
723
748
 
@@ -40,7 +40,28 @@ class ContextSourceLedger {
40
40
  * @returns {string} entryId
41
41
  */
42
42
  record(entry) {
43
+ if (
44
+ entry.tokenCount != null &&
45
+ (!Number.isSafeInteger(entry.tokenCount) || entry.tokenCount < 0)
46
+ ) {
47
+ throw new TypeError(
48
+ "Context tokenCount must be a non-negative safe integer",
49
+ );
50
+ }
43
51
  const entryId = entry.entryId || crypto.randomUUID();
52
+ const previous = this._entries.get(entryId);
53
+ if (previous) {
54
+ for (const [index, key] of [
55
+ [this._byTurn, previous.turnId],
56
+ [this._bySession, previous.sessionId],
57
+ ]) {
58
+ const remaining = (index.get(key) || []).filter(
59
+ (item) => item.entryId !== entryId,
60
+ );
61
+ if (remaining.length) index.set(key, remaining);
62
+ else index.delete(key);
63
+ }
64
+ }
44
65
  const full = {
45
66
  entryId,
46
67
  traceId: entry.traceId || null,
@@ -53,6 +74,7 @@ class ContextSourceLedger {
53
74
  summary: entry.summary,
54
75
  metadata: entry.metadata,
55
76
  tokenCount: entry.tokenCount || 0,
77
+ tokenBasis: entry.tokenBasis === "observed" ? "observed" : "estimated",
56
78
  insertedAt: new Date(),
57
79
  tags: entry.tags || [],
58
80
  };
@@ -64,7 +86,8 @@ class ContextSourceLedger {
64
86
  this._byTurn.get(full.turnId).push(full);
65
87
 
66
88
  // Index by session
67
- if (!this._bySession.has(full.sessionId)) this._bySession.set(full.sessionId, []);
89
+ if (!this._bySession.has(full.sessionId))
90
+ this._bySession.set(full.sessionId, []);
68
91
  this._bySession.get(full.sessionId).push(full);
69
92
 
70
93
  return entryId;
@@ -82,6 +105,7 @@ class ContextSourceLedger {
82
105
  summary: entry.summary || entry.content,
83
106
  metadata: entry.metadata,
84
107
  tokenCount: entry.tokenCount ?? entry.tokens ?? 0,
108
+ tokenBasis: entry.tokenBasis,
85
109
  traceId: entry.traceId,
86
110
  });
87
111
  }
@@ -95,14 +119,31 @@ class ContextSourceLedger {
95
119
  }
96
120
 
97
121
  /** Aggregate token usage by source type. */
98
- getTokenBreakdown() {
99
- const bySource = {};
122
+ getTokenBreakdown(options = {}) {
123
+ const sources = new Map();
100
124
  let total = 0;
101
- for (const entry of this._entries.values()) {
125
+ for (const entry of this.getProvenance(options)) {
102
126
  total += entry.tokenCount;
103
- bySource[entry.sourceType] = (bySource[entry.sourceType] || 0) + entry.tokenCount;
127
+ sources.set(
128
+ entry.sourceType,
129
+ (sources.get(entry.sourceType) || 0) + entry.tokenCount,
130
+ );
104
131
  }
105
- return { total, bySource };
132
+ return { total, bySource: Object.fromEntries(sources) };
133
+ }
134
+
135
+ /** Source attribution is separate from provider request usage and billing. */
136
+ getTokenReport(options = {}) {
137
+ const entries = this.getProvenance(options);
138
+ const byBasis = { estimated: 0, observed: 0 };
139
+ for (const entry of entries) byBasis[entry.tokenBasis] += entry.tokenCount;
140
+ return {
141
+ ...this.getTokenBreakdown(options),
142
+ byBasis,
143
+ entries: entries.length,
144
+ currentRequestVerified: false,
145
+ billingVerified: false,
146
+ };
106
147
  }
107
148
 
108
149
  /** Clear the in-memory ledger (test/runtime lifecycle boundary). */
@@ -146,7 +187,8 @@ class ContextSourceLedger {
146
187
 
147
188
  for (const e of entries) {
148
189
  byType[e.sourceType] = (byType[e.sourceType] || 0) + 1;
149
- byPermission[e.permissionMode] = (byPermission[e.permissionMode] || 0) + 1;
190
+ byPermission[e.permissionMode] =
191
+ (byPermission[e.permissionMode] || 0) + 1;
150
192
  bySource[e.sourceId] = (bySource[e.sourceId] || 0) + 1;
151
193
  totalTokens += e.tokenCount;
152
194
  avgConfidence += e.confidence;
@@ -162,7 +204,7 @@ class ContextSourceLedger {
162
204
  byType,
163
205
  byPermission,
164
206
  bySource,
165
- entries: entries.map(e => ({
207
+ entries: entries.map((e) => ({
166
208
  sourceType: e.sourceType,
167
209
  sourceId: e.sourceId,
168
210
  permissionMode: e.permissionMode,
@@ -184,8 +226,9 @@ class ContextSourceLedger {
184
226
  this._entries.delete(e.entryId);
185
227
  const turnEntries = this._byTurn.get(e.turnId);
186
228
  if (turnEntries) {
187
- const idx = turnEntries.findIndex(x => x.entryId === e.entryId);
229
+ const idx = turnEntries.findIndex((x) => x.entryId === e.entryId);
188
230
  if (idx >= 0) turnEntries.splice(idx, 1);
231
+ if (!turnEntries.length) this._byTurn.delete(e.turnId);
189
232
  }
190
233
  }
191
234
  this._bySession.delete(sessionId);