chainlesschain 0.166.86 → 0.166.88

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 (190) hide show
  1. package/README.md +26 -15
  2. package/package.json +1 -1
  3. package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
  4. package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
  5. package/src/assets/web-panel/assets/{AIOps-DZwiXAIh.js → AIOps-QzeGep9J.js} +1 -1
  6. package/src/assets/web-panel/assets/{ActionButton-aNzXoIJP.js → ActionButton-Dfc5bx7S.js} +1 -1
  7. package/src/assets/web-panel/assets/{Analytics-ETQk4ZXt.js → Analytics-tn-_ZG2E.js} +3 -3
  8. package/src/assets/web-panel/assets/{AppLayout-D5oEbeEC.js → AppLayout-Deg3WAK8.js} +3 -3
  9. package/src/assets/web-panel/assets/{Artifacts-ja48FAne.js → Artifacts-KU05t0a6.js} +1 -1
  10. package/src/assets/web-panel/assets/{Audit-DlN0YnDt.js → Audit-CkSZf54T.js} +1 -1
  11. package/src/assets/web-panel/assets/{BackgroundAgents-CzvyNsRg.js → BackgroundAgents-i7ivfXF0.js} +1 -1
  12. package/src/assets/web-panel/assets/{Backup-DXgEC2MQ.js → Backup-QcVUKtf0.js} +1 -1
  13. package/src/assets/web-panel/assets/{BaseInput-D9XqejLx.js → BaseInput-B3h5ZJ0g.js} +1 -1
  14. package/src/assets/web-panel/assets/{Chat-BTwuYUlN.js → Chat-D7AVz0xi.js} +5 -5
  15. package/src/assets/web-panel/assets/{ChatBubbleRenderer-0anIC2Wn.js → ChatBubbleRenderer-B0-euPW7.js} +1 -1
  16. package/src/assets/web-panel/assets/{Checkbox-CLuaQbDt.js → Checkbox-H0p0TMlD.js} +1 -1
  17. package/src/assets/web-panel/assets/{Codegen-KwQUZs8A.js → Codegen-B6HOmAY3.js} +1 -1
  18. package/src/assets/web-panel/assets/{Col-BCmROkzc.js → Col-n_64Fog2.js} +1 -1
  19. package/src/assets/web-panel/assets/{Community-CXlUEHR4.js → Community-CX0JGgj0.js} +1 -1
  20. package/src/assets/web-panel/assets/{Compact-Dzx-lWI2.js → Compact-C4JWUZlx.js} +1 -1
  21. package/src/assets/web-panel/assets/{Compliance-CfXW82FF.js → Compliance-DKyTZakB.js} +1 -1
  22. package/src/assets/web-panel/assets/{Cowork-DIISTRm2.js → Cowork-C0joBMci.js} +3 -3
  23. package/src/assets/web-panel/assets/{Cron-nyJ-KcFE.js → Cron-D6VkYpxK.js} +2 -2
  24. package/src/assets/web-panel/assets/{Crosschain-Dtv1E4cV.js → Crosschain-7b6Uu8jc.js} +1 -1
  25. package/src/assets/web-panel/assets/{DID-BCTpektS.js → DID-C8YPKqzY.js} +2 -2
  26. package/src/assets/web-panel/assets/{Dashboard-C1Q_m0So.js → Dashboard-DJsOiEry.js} +2 -2
  27. package/src/assets/web-panel/assets/{Dropdown-BrQ5_PPL.js → Dropdown-CyStFY-4.js} +1 -1
  28. package/src/assets/web-panel/assets/EmailListRenderer-COrIx2Rg.js +1 -0
  29. package/src/assets/web-panel/assets/{EvolutionSettings-DaGaE6bX.js → EvolutionSettings-DpxORusH.js} +1 -1
  30. package/src/assets/web-panel/assets/{FamilyGuardDashboard-nJDWBECt.js → FamilyGuardDashboard-5BYZdMG0.js} +1 -1
  31. package/src/assets/web-panel/assets/{Federation-DhMUY_wG.js → Federation-s1kS0ekU.js} +1 -1
  32. package/src/assets/web-panel/assets/{FormItemContext-CbONJPuc.js → FormItemContext-CmgoH9HV.js} +1 -1
  33. package/src/assets/web-panel/assets/{GenericCardRenderer-CDdX4dX-.js → GenericCardRenderer-DSRWrvcL.js} +1 -1
  34. package/src/assets/web-panel/assets/{Git-DXbDVJdR.js → Git-Cz3EgnS1.js} +2 -2
  35. package/src/assets/web-panel/assets/{Governance-DbAfAvs1.js → Governance-De4atTe7.js} +1 -1
  36. package/src/assets/web-panel/assets/{Inference-Dy-fGea2.js → Inference-DoitBBxJ.js} +1 -1
  37. package/src/assets/web-panel/assets/{KnowledgeGraph-DAxRpGUF.js → KnowledgeGraph-CIdmJ1pH.js} +1 -1
  38. package/src/assets/web-panel/assets/{Logs-5L1UCR8X.js → Logs-Coa_qNhU.js} +2 -2
  39. package/src/assets/web-panel/assets/{MarkdownRenderer-u0FPafvT.js → MarkdownRenderer-CeT_RocE.js} +1 -1
  40. package/src/assets/web-panel/assets/{Marketplace-DUk_McDG.js → Marketplace-C6kbAQoM.js} +1 -1
  41. package/src/assets/web-panel/assets/{McpTools-B6PNsZ_p.js → McpTools-C2TZn8D-.js} +3 -3
  42. package/src/assets/web-panel/assets/{Memory-BUUs8j5F.js → Memory-DYdEKDuB.js} +2 -2
  43. package/src/assets/web-panel/assets/{MobileBridge-pXRsgyuO.js → MobileBridge-pKLeVviZ.js} +1 -1
  44. package/src/assets/web-panel/assets/MobileProjects-D4bWcHA_.js +1 -0
  45. package/src/assets/web-panel/assets/{Mtc-Deaj4faB.js → Mtc-IEoVRV29.js} +4 -4
  46. package/src/assets/web-panel/assets/{MtcAudit-wUV0VUH1.js → MtcAudit-Cov-yYTY.js} +2 -2
  47. package/src/assets/web-panel/assets/{Multisig-C67IIkts.js → Multisig--Jr7OCmp.js} +3 -3
  48. package/src/assets/web-panel/assets/{NLProgramming-BCA_CWrW.js → NLProgramming-D2gXnYAA.js} +1 -1
  49. package/src/assets/web-panel/assets/{Notes-D9eu14hQ.js → Notes-hk8pMyve.js} +3 -3
  50. package/src/assets/web-panel/assets/{NotificationSettings-Cnd-J4LM.js → NotificationSettings-D26Nc7MU.js} +1 -1
  51. package/src/assets/web-panel/assets/{OrderTableRenderer-C4pHUuyZ.js → OrderTableRenderer-DmzHMEOa.js} +1 -1
  52. package/src/assets/web-panel/assets/{Organization-4YExAbnp.js → Organization-Cn-o6mHT.js} +4 -4
  53. package/src/assets/web-panel/assets/{Overflow-BF-wFuZz.js → Overflow-DP6xpDak.js} +1 -1
  54. package/src/assets/web-panel/assets/{P2P-CdiajqCT.js → P2P-C9WAjG-I.js} +2 -2
  55. package/src/assets/web-panel/assets/PdhVaultBrowser-DxZb0Ux8.js +7 -0
  56. package/src/assets/web-panel/assets/{Permissions-DrZ4D78_.js → Permissions-BFBN4-IL.js} +4 -4
  57. package/src/assets/web-panel/assets/{PersonalDataHub-lDc6OXjz.js → PersonalDataHub-BEDvoAiz.js} +6 -6
  58. package/src/assets/web-panel/assets/{Pipeline-DqDS9ON1.js → Pipeline-Co2Ze_rR.js} +1 -1
  59. package/src/assets/web-panel/assets/{Privacy-BMekZRZu.js → Privacy-BOTn1EId.js} +1 -1
  60. package/src/assets/web-panel/assets/{ProjectInit-LYS7NFvJ.js → ProjectInit-CObyrZYm.js} +2 -2
  61. package/src/assets/web-panel/assets/{ProjectSettings-CcJNHk9A.js → ProjectSettings-DVTN31rd.js} +2 -2
  62. package/src/assets/web-panel/assets/{Projects-DrfAHgdF.js → Projects-DQSEaVjE.js} +1 -1
  63. package/src/assets/web-panel/assets/{Providers-aqsly9SR.js → Providers-BRIKWIdQ.js} +1 -1
  64. package/src/assets/web-panel/assets/{QrScannerModal-ZWvR3zqg.js → QrScannerModal-3nxaEXxN.js} +1 -1
  65. package/src/assets/web-panel/assets/{QuickAsk-BT5CgsvW.js → QuickAsk-iwZJEE9z.js} +1 -1
  66. package/src/assets/web-panel/assets/{Recommend-Cz8Dz2RN.js → Recommend-D2_EEbvc.js} +1 -1
  67. package/src/assets/web-panel/assets/{RemoteSession-BlxPVbtQ.js → RemoteSession-S4w2mUfq.js} +2 -2
  68. package/src/assets/web-panel/assets/{Reputation-B3VGBE-1.js → Reputation-CstUvfTC.js} +1 -1
  69. package/src/assets/web-panel/assets/{Row-Bwv7vSEA.js → Row-DEGHFpxz.js} +1 -1
  70. package/src/assets/web-panel/assets/{RssFeed-DHI085r_.js → RssFeed-DGdZtJQl.js} +2 -2
  71. package/src/assets/web-panel/assets/{Search-DBler5T0.js → Search-DhfXi99U.js} +1 -1
  72. package/src/assets/web-panel/assets/{Security-BZdw43NW.js → Security-BbzISrgX.js} +4 -4
  73. package/src/assets/web-panel/assets/{Services-Cslk5lUj.js → Services-CFjP2sQ3.js} +2 -2
  74. package/src/assets/web-panel/assets/{Skeleton-Bur-C-25.js → Skeleton-CFn5wbvm.js} +1 -1
  75. package/src/assets/web-panel/assets/Skills-fVbT8RcW.js +1 -0
  76. package/src/assets/web-panel/assets/{Sla-B1OWgQ51.js → Sla-D6OtC0MT.js} +1 -1
  77. package/src/assets/web-panel/assets/{SpeechSettings-CaBcEaV4.js → SpeechSettings-D0kteBjU.js} +1 -1
  78. package/src/assets/web-panel/assets/{SyncSettings-CBbG8L6J.js → SyncSettings-BGEWCtPh.js} +2 -2
  79. package/src/assets/web-panel/assets/Tasks-B1xZUG4D.js +1 -0
  80. package/src/assets/web-panel/assets/{Templates-VBBOZ1H5.js → Templates-COlorjqb.js} +1 -1
  81. package/src/assets/web-panel/assets/{Tenant-CtQTj7IF.js → Tenant-yLkwfuo3.js} +1 -1
  82. package/src/assets/web-panel/assets/{Terminal-DXVTQjnl.js → Terminal-CAmkq1wf.js} +2 -2
  83. package/src/assets/web-panel/assets/{TimelineRenderer-BRIno0aN.js → TimelineRenderer-CcKYq1Ue.js} +1 -1
  84. package/src/assets/web-panel/assets/{Tokens-uiiAfkYN.js → Tokens-9hIqn_LE.js} +1 -1
  85. package/src/assets/web-panel/assets/{Trigger-CPApN8o6.js → Trigger-Dsdkb74C.js} +1 -1
  86. package/src/assets/web-panel/assets/{Trust-T2jKVwCE.js → Trust-DC4GuE3C.js} +1 -1
  87. package/src/assets/web-panel/assets/{UkeySign-C2U_gbzP.js → UkeySign-CSlh00wf.js} +1 -1
  88. package/src/assets/web-panel/assets/{VideoEditing-BCdlr3Kj.js → VideoEditing-QEWLo3QY.js} +1 -1
  89. package/src/assets/web-panel/assets/{Wallet-CWnjoSc1.js → Wallet-BkPNQgmg.js} +4 -4
  90. package/src/assets/web-panel/assets/{WebAuthn-CqSbYqHq.js → WebAuthn-7---jCBl.js} +4 -4
  91. package/src/assets/web-panel/assets/{WorkflowEditor-Dr_I3jcr.js → WorkflowEditor-Dq6Yiu8E.js} +1 -1
  92. package/src/assets/web-panel/assets/{chat-Cg21FKdE.js → chat-CTYIMpWD.js} +1 -1
  93. package/src/assets/web-panel/assets/{colors-CK85tY9e.js → colors-C8JtYlDN.js} +1 -1
  94. package/src/assets/web-panel/assets/{compact-item-m-XYPC7W.js → compact-item-spXpnsNC.js} +1 -1
  95. package/src/assets/web-panel/assets/{createContext-BmiEeNvs.js → createContext-D04ewPuL.js} +1 -1
  96. package/src/assets/web-panel/assets/devWarning-3-s4adfp.js +1 -0
  97. package/src/assets/web-panel/assets/{hasIn-CCw4KAoc.js → hasIn-DZblOKXx.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-Br9t_I1X.js → index-749P1pkM.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BvjC3t35.js → index-B-cKXztT.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BiVPFsat.js → index-B57W1RB6.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-8KzhlvJ9.js → index-B7RA974g.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-OIbfsi-o.js → index-BKfR2eSQ.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-BGb1j2z9.js → index-BLv-KSGc.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-yYmjkf38.js → index-BOuUUW2U.js} +3 -3
  105. package/src/assets/web-panel/assets/{index-J81uvUMN.js → index-BSO33_O2.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DI9GJFcn.js → index-B_65aY6c.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-BHsiSoGY.js → index-BjMY3Y_L.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-6jXf-Lln.js → index-Bm0z1M6s.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-BGUYgc96.js → index-Bw-3CtK2.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-sWUmvT8H.js → index-CE3TYhl0.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-CN2xbLGz.js → index-CHtwoTKX.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-D7gS_TJl.js → index-CLkua5sJ.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-BStyjmLG.js → index-COvZnoIg.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-DmSgfXuz.js → index-CZmBlh5P.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-lhoexBDH.js → index-Cfk4o9eI.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-DMbrl43d.js → index-Cgztj1JO.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-DxRhnsEC.js → index-Cz0gkRz_.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-DAlGVix-.js → index-DHOV24VR.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DIlGxS2W.js → index-DLUHbPl3.js} +1 -1
  120. package/src/assets/web-panel/assets/{index-CYEzWoyZ.js → index-DSoyEHi2.js} +1 -1
  121. package/src/assets/web-panel/assets/{index-CBcgIWOe.js → index-D_Md0Jhp.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-D1sU5-XA.js → index-Dcd-qZ68.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-B8IC9ZeZ.js → index-DcjouIsi.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-ByVvAXdl.js → index-DdC0OsNh.js} +1 -1
  125. package/src/assets/web-panel/assets/{index-BtvVupUL.js → index-DruABY-g.js} +1 -1
  126. package/src/assets/web-panel/assets/{index-IskAKXhx.js → index-Dssnz_1x.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-DpIy2HzE.js → index-DtSzmzFF.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-BIOTRzaF.js → index-DwIEfKo7.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-B7xJkhtJ.js → index-EM4_wLPi.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-Bv90WEWa.js → index-IFEbaISP.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-Cf5arJie.js → index-KIoJ2eCK.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-BUYyhYP6.js → index-Mxj-qi1G.js} +1 -1
  133. package/src/assets/web-panel/assets/index-ZMf_BGlO.js +1 -0
  134. package/src/assets/web-panel/assets/index-jvp8bJBF.js +1 -0
  135. package/src/assets/web-panel/assets/{index-Br0ZNdu1.js → index-rU6_An6N.js} +1 -1
  136. package/src/assets/web-panel/assets/{index-BcfVHmFK.js → index-rVEqWa0_.js} +1 -1
  137. package/src/assets/web-panel/assets/{initDefaultProps-Cc1XOmNe.js → initDefaultProps-Dl0wiMxn.js} +1 -1
  138. package/src/assets/web-panel/assets/{motion-BehsX88u.js → motion-BFmZYrGO.js} +1 -1
  139. package/src/assets/web-panel/assets/{move-BPx2YsqY.js → move-Cjs64yWq.js} +1 -1
  140. package/src/assets/web-panel/assets/{mtc-parser-BSFJgFQA.js → mtc-parser-NeQsnBuP.js} +1 -1
  141. package/src/assets/web-panel/assets/{omit-DBN5KUeo.js → omit-4Rs-rfs9.js} +1 -1
  142. package/src/assets/web-panel/assets/{pickAttrs-BDK1yZ-9.js → pickAttrs-CUhx2rDY.js} +1 -1
  143. package/src/assets/web-panel/assets/{placementArrow-C4rMmKNJ.js → placementArrow-DbIM_OB2.js} +1 -1
  144. package/src/assets/web-panel/assets/{responsiveObserve-BoeoOnxX.js → responsiveObserve-B_TGx9AN.js} +1 -1
  145. package/src/assets/web-panel/assets/{slide-BKlr1bl9.js → slide-C46cEP5t.js} +1 -1
  146. package/src/assets/web-panel/assets/{statusUtils-Ky1apWPI.js → statusUtils-DqeksICX.js} +1 -1
  147. package/src/assets/web-panel/assets/{styleChecker-DxxR7uXk.js → styleChecker-2rrypo5u.js} +1 -1
  148. package/src/assets/web-panel/assets/{useFlexGapSupport-DmsUqVe9.js → useFlexGapSupport-RRe1Edsg.js} +1 -1
  149. package/src/assets/web-panel/assets/{useFs-CwkG7sOg.js → useFs-CB0oxU1U.js} +1 -1
  150. package/src/assets/web-panel/assets/{usePersonalDataHub-CddgeEfF.js → usePersonalDataHub-B98WdlUE.js} +1 -1
  151. package/src/assets/web-panel/assets/{vnode-C_-H8i4Y.js → vnode-CY8AoD95.js} +1 -1
  152. package/src/assets/web-panel/assets/{zoom-aAsHUMNE.js → zoom-BnT-0MbP.js} +1 -1
  153. package/src/assets/web-panel/index.html +1 -1
  154. package/src/command-help-index.json +1 -1
  155. package/src/commands/eval.js +116 -67
  156. package/src/commands/memory.js +34 -15
  157. package/src/commands/sandbox.js +9 -0
  158. package/src/data/changelog.json +26 -0
  159. package/src/lib/causal-observability.js +6 -45
  160. package/src/lib/context-memory-kernel/durable-memory-port.js +49 -10
  161. package/src/lib/context-memory-kernel/memory-query-index.js +278 -0
  162. package/src/lib/context-memory-kernel/memory-service.js +17 -2
  163. package/src/lib/context-memory-kernel/segmented-memory-port.js +277 -9
  164. package/src/lib/eval/outcomes.js +20 -10
  165. package/src/lib/eval/runner.js +49 -5
  166. package/src/lib/eval/stream-terminal.js +51 -0
  167. package/src/lib/eval/tasks.js +8 -3
  168. package/src/lib/eval/verify01-contracts.js +349 -0
  169. package/src/lib/eval/verify01-execution.js +611 -0
  170. package/src/lib/eval/verify01-host-evidence.js +604 -0
  171. package/src/lib/execution-support.js +58 -0
  172. package/src/lib/llm-pricing.js +98 -11
  173. package/src/lib/model-catalog-review.js +116 -0
  174. package/src/lib/model-context-catalog.js +23 -1
  175. package/src/lib/openai-responses.js +39 -0
  176. package/src/lib/process-execution-broker/index.js +8 -0
  177. package/src/lib/process-execution-broker/linux-subreaper-process.js +24 -2
  178. package/src/lib/process-execution-broker/process-ownership-journal.js +168 -7
  179. package/src/lib/process-execution-broker/process-ownership-quarantine.js +56 -1
  180. package/src/lib/process-execution-broker/process-recovery-cgroup.js +272 -0
  181. package/src/runtime/agent-core.js +9 -24
  182. package/src/runtime/permission-authority-host.js +14 -0
  183. package/src/assets/web-panel/assets/EmailListRenderer-DjoNlONP.js +0 -1
  184. package/src/assets/web-panel/assets/MobileProjects-D7v-2Hwm.js +0 -1
  185. package/src/assets/web-panel/assets/PdhVaultBrowser-BkjfS6Th.js +0 -7
  186. package/src/assets/web-panel/assets/Skills-v0zgLy0X.js +0 -1
  187. package/src/assets/web-panel/assets/Tasks-C7EjXrnN.js +0 -1
  188. package/src/assets/web-panel/assets/devWarning-CkMEODFC.js +0 -1
  189. package/src/assets/web-panel/assets/index-BjE5qaKn.js +0 -1
  190. package/src/assets/web-panel/assets/index-CsFH-2Zk.js +0 -1
@@ -0,0 +1,278 @@
1
+ import { createHash } from "node:crypto";
2
+
3
+ export const MEMORY_QUERY_INDEX_SCHEMA = "chainlesschain.memory-query-index/v1";
4
+ const CURSOR_SCHEMA = "chainlesschain.memory-list-cursor/v1";
5
+
6
+ export function queryDigest(bytes) {
7
+ return `sha256:${createHash("sha256").update(bytes).digest("hex")}`;
8
+ }
9
+
10
+ export function compareMemoryRows(left, right) {
11
+ return (
12
+ right.importance - left.importance ||
13
+ right.updatedAt.localeCompare(left.updatedAt, "en") ||
14
+ left.memoryId.localeCompare(right.memoryId, "en")
15
+ );
16
+ }
17
+
18
+ // No content, evidence, or audit is copied into the derived index. The manifest
19
+ // binds these bytes to the immutable authority shard from which they were made.
20
+ export function encodeQueryIndex(state) {
21
+ const rows = Object.values(state.records)
22
+ .map((record) => ({
23
+ memoryId: record.memoryId,
24
+ category: record.category,
25
+ scope: record.scope,
26
+ scopeId: record.scopeId ?? null,
27
+ state: record.state,
28
+ importance: record.importance,
29
+ updatedAt: record.updatedAt,
30
+ tags: record.tags,
31
+ allowedSinks: record.allowedSinks,
32
+ }))
33
+ .sort(compareMemoryRows);
34
+ return Buffer.from(
35
+ JSON.stringify({
36
+ schema: MEMORY_QUERY_INDEX_SCHEMA,
37
+ shardDigest: state.digest,
38
+ rows,
39
+ }),
40
+ );
41
+ }
42
+
43
+ function scopeKey(scope, scopeId) {
44
+ return JSON.stringify([scope, scopeId ?? null]);
45
+ }
46
+
47
+ export function compileQueryIndex(bytes, descriptor) {
48
+ const value = JSON.parse(bytes.toString("utf8"));
49
+ if (
50
+ value.schema !== MEMORY_QUERY_INDEX_SCHEMA ||
51
+ value.shardDigest !== descriptor.digest ||
52
+ !Array.isArray(value.rows) ||
53
+ value.rows.length !== descriptor.recordCount
54
+ ) {
55
+ throw new Error("query index does not match authority shard");
56
+ }
57
+ const fields = ["category", "scope", "state", "tag", "sink"];
58
+ const postings = Object.fromEntries(
59
+ fields.map((field) => [field, new Map()]),
60
+ );
61
+ const add = (field, key, index) => {
62
+ const map = postings[field];
63
+ if (!map.has(key)) map.set(key, []);
64
+ map.get(key).push(index);
65
+ };
66
+ value.rows.forEach((row, index) => {
67
+ add("category", row.category, index);
68
+ add("scope", scopeKey(row.scope, row.scopeId), index);
69
+ add("state", row.state, index);
70
+ for (const tag of row.tags) add("tag", tag, index);
71
+ for (const sink of row.allowedSinks) add("sink", sink, index);
72
+ });
73
+ return { rows: value.rows, postings };
74
+ }
75
+
76
+ export function normalizeListQuery(options = {}) {
77
+ const result = { includeTombstones: options.includeTombstones === true };
78
+ if (options.category) result.category = String(options.category);
79
+ if (options.sink) result.sink = String(options.sink);
80
+ if (options.scopeAdmissions !== undefined) {
81
+ if (!Array.isArray(options.scopeAdmissions))
82
+ throw new TypeError("scopeAdmissions must be an array");
83
+ result.scopeAdmissions = options.scopeAdmissions.map(
84
+ ({ scope, scopeId }) => ({
85
+ scope,
86
+ scopeId: scopeId ?? null,
87
+ }),
88
+ );
89
+ }
90
+ if (options.tags !== undefined) {
91
+ if (!Array.isArray(options.tags))
92
+ throw new TypeError("tags must be an array");
93
+ result.tags = [...new Set(options.tags.map(String))].sort();
94
+ }
95
+ if (options.states !== undefined) {
96
+ if (!Array.isArray(options.states))
97
+ throw new TypeError("states must be an array");
98
+ result.states = [...new Set(options.states.map(String))].sort();
99
+ }
100
+ return result;
101
+ }
102
+
103
+ export function matchesListQuery(row, query) {
104
+ return (
105
+ (query.includeTombstones || !["deleted", "purged"].includes(row.state)) &&
106
+ (!query.category || row.category === query.category) &&
107
+ (!query.states || query.states.includes(row.state)) &&
108
+ (!query.scopeAdmissions ||
109
+ query.scopeAdmissions.some(
110
+ (scope) =>
111
+ scope.scope === row.scope &&
112
+ (scope.scopeId ?? null) === (row.scopeId ?? null),
113
+ )) &&
114
+ (!query.sink ||
115
+ row.allowedSinks.includes("*") ||
116
+ row.allowedSinks.includes(query.sink)) &&
117
+ (!query.tags?.length || row.tags.some((tag) => query.tags.includes(tag)))
118
+ );
119
+ }
120
+
121
+ // Each posting is already in the public list order. Pick the narrowest posting
122
+ // before applying the remaining predicates; no full-record scan or top-k before
123
+ // permission filtering. Recall uses these gates but retains kernel ranking.
124
+ export function* selectQueryRows(index, query, after = null) {
125
+ const candidates = [];
126
+ const union = (field, keys) => {
127
+ const lists = keys
128
+ .map((key) => index.postings[field].get(key))
129
+ .filter(Boolean);
130
+ return lists.length < 2
131
+ ? lists[0] || []
132
+ : [...new Set(lists.flat())].sort((a, b) => a - b);
133
+ };
134
+ if (query.category)
135
+ candidates.push(index.postings.category.get(query.category) || []);
136
+ if (query.scopeAdmissions)
137
+ candidates.push(
138
+ union(
139
+ "scope",
140
+ query.scopeAdmissions.map((scope) =>
141
+ scopeKey(scope.scope, scope.scopeId),
142
+ ),
143
+ ),
144
+ );
145
+ if (query.states) candidates.push(union("state", query.states));
146
+ if (query.tags?.length) candidates.push(union("tag", query.tags));
147
+ if (query.sink) candidates.push(union("sink", ["*", query.sink]));
148
+ candidates.sort((a, b) => a.length - b.length);
149
+ const positions = candidates[0];
150
+ const length = positions ? positions.length : index.rows.length;
151
+ const rowAt = (offset) => index.rows[positions ? positions[offset] : offset];
152
+ let start = 0;
153
+ if (after) {
154
+ let end = length;
155
+ while (start < end) {
156
+ const middle = Math.floor((start + end) / 2);
157
+ if (compareMemoryRows(rowAt(middle), after) <= 0) start = middle + 1;
158
+ else end = middle;
159
+ }
160
+ }
161
+ for (let offset = start; offset < length; offset++) {
162
+ const row = rowAt(offset);
163
+ if (matchesListQuery(row, query)) yield row;
164
+ }
165
+ }
166
+
167
+ export function* mergeQueryRows(heads) {
168
+ const heap = [];
169
+ const less = (left, right) => compareMemoryRows(left.row, right.row) < 0;
170
+ const push = (head) => {
171
+ let at = heap.length;
172
+ heap.push(head);
173
+ while (at > 0) {
174
+ const parent = Math.floor((at - 1) / 2);
175
+ if (!less(head, heap[parent])) break;
176
+ heap[at] = heap[parent];
177
+ at = parent;
178
+ }
179
+ heap[at] = head;
180
+ };
181
+ for (const head of heads) push(head);
182
+ while (heap.length) {
183
+ const first = heap[0];
184
+ const last = heap.pop();
185
+ if (heap.length) {
186
+ let at = 0;
187
+ while (at * 2 + 1 < heap.length) {
188
+ let child = at * 2 + 1;
189
+ if (child + 1 < heap.length && less(heap[child + 1], heap[child]))
190
+ child++;
191
+ if (!less(heap[child], last)) break;
192
+ heap[at] = heap[child];
193
+ at = child;
194
+ }
195
+ heap[at] = last;
196
+ }
197
+ yield { bucket: first.bucket, row: first.row };
198
+ const next = first.iterator.next();
199
+ if (!next.done) push({ ...first, row: next.value });
200
+ }
201
+ }
202
+
203
+ export function cursorError(reason) {
204
+ return Object.assign(new Error(`Memory list cursor is invalid: ${reason}`), {
205
+ code: "CONTEXT_MEMORY_CURSOR_INVALID",
206
+ });
207
+ }
208
+
209
+ export function listCursorBinding(filePath, generation, query) {
210
+ return queryDigest(
211
+ JSON.stringify({
212
+ filePath,
213
+ generation,
214
+ query,
215
+ order: "importance-desc,updatedAt-desc,memoryId-en-asc/v1",
216
+ }),
217
+ );
218
+ }
219
+
220
+ export function decodeListCursor(cursor, binding) {
221
+ if (cursor == null) return null;
222
+ if (
223
+ typeof cursor !== "string" ||
224
+ cursor.length > 4096 ||
225
+ !/^[\w-]+$/u.test(cursor)
226
+ )
227
+ throw cursorError("encoding");
228
+ let decoded;
229
+ try {
230
+ decoded = JSON.parse(Buffer.from(cursor, "base64url").toString("utf8"));
231
+ } catch {
232
+ throw cursorError("encoding");
233
+ }
234
+ if (
235
+ !decoded ||
236
+ decoded.schema !== CURSOR_SCHEMA ||
237
+ decoded.binding !== binding ||
238
+ !decoded.after ||
239
+ typeof decoded.after.memoryId !== "string" ||
240
+ typeof decoded.after.updatedAt !== "string" ||
241
+ !Number.isFinite(decoded.after.importance) ||
242
+ decoded.digest !==
243
+ queryDigest(
244
+ JSON.stringify({
245
+ schema: decoded.schema,
246
+ binding: decoded.binding,
247
+ after: decoded.after,
248
+ }),
249
+ )
250
+ ) {
251
+ throw cursorError("generation, filters, or checksum changed");
252
+ }
253
+ return decoded.after;
254
+ }
255
+
256
+ export function encodeListCursor(binding, row) {
257
+ const value = {
258
+ schema: CURSOR_SCHEMA,
259
+ binding,
260
+ after: {
261
+ memoryId: row.memoryId,
262
+ updatedAt: row.updatedAt,
263
+ importance: row.importance,
264
+ },
265
+ };
266
+ return Buffer.from(
267
+ JSON.stringify({ ...value, digest: queryDigest(JSON.stringify(value)) }),
268
+ ).toString("base64url");
269
+ }
270
+
271
+ export function pageLimit(value, fallback = 20) {
272
+ const number = value == null ? fallback : Number(value);
273
+ if (!Number.isSafeInteger(number) || number < 1 || number > 10000)
274
+ throw new RangeError(
275
+ "memory page limit must be an integer from 1 to 10000",
276
+ );
277
+ return number;
278
+ }
@@ -403,14 +403,29 @@ export class CliCanonicalMemoryService {
403
403
  return result;
404
404
  }
405
405
 
406
- async list({ limit = 20, category } = {}) {
407
- const records = await this.runtime.memoryPort.listRecords();
406
+ async list({ limit = 20, category, scopeAdmissions, sink, tags } = {}) {
407
+ const records = await this.runtime.memoryPort.listRecords({
408
+ limit: Math.max(1, Number(limit) || 20),
409
+ category,
410
+ scopeAdmissions,
411
+ sink,
412
+ tags,
413
+ });
408
414
  return records
409
415
  .filter((record) => !category || record.category === category)
410
416
  .slice(0, Math.max(1, Number(limit) || 20))
411
417
  .map((record) => publicEntry(record));
412
418
  }
413
419
 
420
+ async listPage(options = {}) {
421
+ const page = await this.runtime.memoryPort.listPage(options);
422
+ return {
423
+ entries: page.records.map((record) => publicEntry(record)),
424
+ nextCursor: page.nextCursor,
425
+ storeRevision: page.storeRevision,
426
+ };
427
+ }
428
+
414
429
  async add(content, options = {}) {
415
430
  const now = new Date(Number(this.now())).toISOString();
416
431
  const evidenceId = `add-${canonicalDigest(
@@ -26,6 +26,20 @@ import {
26
26
  stateDigest,
27
27
  syncDirectory,
28
28
  } from "./durable-memory-port.js";
29
+ import {
30
+ compareMemoryRows,
31
+ compileQueryIndex,
32
+ decodeListCursor,
33
+ encodeListCursor,
34
+ encodeQueryIndex,
35
+ listCursorBinding,
36
+ matchesListQuery,
37
+ mergeQueryRows,
38
+ normalizeListQuery,
39
+ pageLimit,
40
+ queryDigest,
41
+ selectQueryRows,
42
+ } from "./memory-query-index.js";
29
43
 
30
44
  export const SEGMENTED_STORE_SCHEMA =
31
45
  "chainlesschain.cli-context-memory-store/v2";
@@ -147,6 +161,7 @@ export class SegmentedMemoryPort extends DurableJsonMemoryPort {
147
161
  this.readOnly = Boolean(readOnly);
148
162
  this.filePath = resolve(this.filePath);
149
163
  this.shardDirectory = `${this.filePath}.shards`;
164
+ this._queryIndexes = new Map();
150
165
  }
151
166
 
152
167
  _locked(operation) {
@@ -194,6 +209,13 @@ export class SegmentedMemoryPort extends DurableJsonMemoryPort {
194
209
  );
195
210
  }
196
211
 
212
+ _queryIndexPath(bucket, descriptor) {
213
+ return join(
214
+ this.shardDirectory,
215
+ `query-${bucket}-${descriptor.queryDigest.slice(7)}.json`,
216
+ );
217
+ }
218
+
197
219
  _validateManifest(input) {
198
220
  const invalid = () => {
199
221
  throw corruptStore(this.filePath, "segmented manifest is invalid");
@@ -219,13 +241,23 @@ export class SegmentedMemoryPort extends DurableJsonMemoryPort {
219
241
  if (
220
242
  !BUCKET.test(bucket) ||
221
243
  !entry ||
222
- Object.keys(entry).sort().join() !==
223
- "bytes,digest,eventCount,recordCount" ||
244
+ ![
245
+ "bytes,digest,eventCount,recordCount",
246
+ "bytes,digest,eventCount,queryBytes,queryDigest,recordCount",
247
+ ].includes(Object.keys(entry).sort().join()) ||
224
248
  !HEX.test(entry.digest)
225
249
  )
226
250
  invalid();
227
251
  for (const key of ["bytes", "eventCount", "recordCount"])
228
252
  if (!Number.isSafeInteger(entry[key]) || entry[key] < 0) invalid();
253
+ if (
254
+ entry.queryDigest !== undefined &&
255
+ (!HEX.test(entry.queryDigest) ||
256
+ !Number.isSafeInteger(entry.queryBytes) ||
257
+ entry.queryBytes < 1 ||
258
+ entry.queryBytes > this.maxStoreBytes)
259
+ )
260
+ invalid();
229
261
  if (entry.bytes > this.maxStoreBytes)
230
262
  throw limit("shard exceeds configured byte limit");
231
263
  bytes += entry.bytes;
@@ -241,6 +273,15 @@ export class SegmentedMemoryPort extends DurableJsonMemoryPort {
241
273
  invalid();
242
274
  if (bytes > this.maxTotalBytes || events > this.maxEvents)
243
275
  throw limit("aggregate capacity exceeded");
276
+ if (
277
+ bytes +
278
+ Object.values(input.shards).reduce(
279
+ (sum, entry) => sum + (entry.queryBytes || 0),
280
+ 0,
281
+ ) >
282
+ this.maxTotalBytes
283
+ )
284
+ throw limit("authority and query indexes exceed aggregate capacity");
244
285
  return input;
245
286
  }
246
287
 
@@ -339,9 +380,12 @@ export class SegmentedMemoryPort extends DurableJsonMemoryPort {
339
380
  _collect(manifest) {
340
381
  this._checkDirectories();
341
382
  const live = new Set(
342
- Object.entries(manifest.shards).map(
343
- ([bucket, entry]) => `${bucket}-${entry.digest.slice(7)}.json`,
344
- ),
383
+ Object.entries(manifest.shards).flatMap(([bucket, entry]) => [
384
+ `${bucket}-${entry.digest.slice(7)}.json`,
385
+ ...(entry.queryDigest
386
+ ? [`query-${bucket}-${entry.queryDigest.slice(7)}.json`]
387
+ : []),
388
+ ]),
345
389
  );
346
390
  // All readers hold the same authority lock. No reader can still be using
347
391
  // a superseded shard here. Unknown files are never treated as our garbage.
@@ -355,6 +399,8 @@ export class SegmentedMemoryPort extends DurableJsonMemoryPort {
355
399
  throw limit("shard directory inventory exceeds 4096 entries");
356
400
  const owned =
357
401
  /^[a-f0-9]{2}-[a-f0-9]{64}\.json$/u.test(entry.name) ||
402
+ /^query-[a-f0-9]{2}-[a-f0-9]{64}\.json$/u.test(entry.name) ||
403
+ /^query-rebuild-[a-f0-9-]{36}\.tmp$/u.test(entry.name) ||
358
404
  /^manifest-[a-f0-9-]{36}\.tmp$/u.test(entry.name);
359
405
  if (owned && !live.has(entry.name)) {
360
406
  const file = join(this.shardDirectory, entry.name);
@@ -388,7 +434,12 @@ export class SegmentedMemoryPort extends DurableJsonMemoryPort {
388
434
  for (const [bucket, state] of changed) {
389
435
  state.digest = stateDigest(state);
390
436
  const bytes = `${JSON.stringify(state)}\n`;
391
- const size = Buffer.byteLength(bytes);
437
+ const unchanged = manifest.shards[bucket]?.digest === state.digest;
438
+ // Canonical digests do not encode JSON property order. During a derived
439
+ // index upgrade retain the original immutable authority bytes verbatim.
440
+ const size = unchanged
441
+ ? manifest.shards[bucket].bytes
442
+ : Buffer.byteLength(bytes);
392
443
  if (size > this.maxStoreBytes)
393
444
  throw limit("shard exceeds configured byte limit");
394
445
  pendingBytes += size - (next.shards[bucket]?.bytes || 0);
@@ -402,9 +453,19 @@ export class SegmentedMemoryPort extends DurableJsonMemoryPort {
402
453
  eventCount: state.events.length,
403
454
  recordCount: Object.keys(state.records).length,
404
455
  };
456
+ const queryBytes = encodeQueryIndex(state);
457
+ if (queryBytes.length > this.maxStoreBytes)
458
+ throw limit("query index exceeds configured byte limit");
459
+ next.shards[bucket].queryDigest = queryDigest(queryBytes);
460
+ next.shards[bucket].queryBytes = queryBytes.length;
461
+ if (!unchanged)
462
+ pending.push({
463
+ file: this._shardPath(bucket, next.shards[bucket]),
464
+ bytes,
465
+ });
405
466
  pending.push({
406
- file: this._shardPath(bucket, next.shards[bucket]),
407
- bytes,
467
+ file: this._queryIndexPath(bucket, next.shards[bucket]),
468
+ bytes: queryBytes,
408
469
  });
409
470
  }
410
471
  next.totalBytes = Object.values(next.shards).reduce(
@@ -557,7 +618,214 @@ export class SegmentedMemoryPort extends DurableJsonMemoryPort {
557
618
  ),
558
619
  );
559
620
  }
560
- async query() {
621
+
622
+ _ensureQueryIndexes(manifest) {
623
+ if (manifest.schema === STORE_SCHEMA || this.readOnly) return manifest;
624
+ const missing = Object.keys(manifest.shards).filter(
625
+ (bucket) => !manifest.shards[bucket].queryDigest,
626
+ );
627
+ if (!missing.length) return manifest;
628
+ // Upgrade older v2 snapshots without changing records, revisions or audit.
629
+ // Old strict readers reject these extended descriptors instead of writing
630
+ // a second authority. Shadow readers derive indexes only in memory.
631
+ return this._publish(
632
+ manifest,
633
+ new Map(
634
+ missing.map((bucket) => [bucket, this._readShard(manifest, bucket)]),
635
+ ),
636
+ );
637
+ }
638
+
639
+ _readQueryIndex(manifest, bucket) {
640
+ const descriptor = manifest.shards[bucket];
641
+ let bytes;
642
+ if (descriptor.queryDigest) {
643
+ const file = this._queryIndexPath(bucket, descriptor);
644
+ this._checkDirectories();
645
+ if (existsSync(file)) {
646
+ // Unsafe filesystem objects are authority errors, never repair targets.
647
+ regular(file);
648
+ try {
649
+ bytes = readBoundedState(file, descriptor.queryBytes, true);
650
+ } catch (error) {
651
+ if (error.code !== "CONTEXT_MEMORY_STORE_CORRUPT") throw error;
652
+ }
653
+ }
654
+ if (
655
+ !bytes ||
656
+ bytes.length !== descriptor.queryBytes ||
657
+ queryDigest(bytes) !== descriptor.queryDigest
658
+ ) {
659
+ bytes = encodeQueryIndex(this._readShard(manifest, bucket));
660
+ if (
661
+ bytes.length !== descriptor.queryBytes ||
662
+ queryDigest(bytes) !== descriptor.queryDigest
663
+ )
664
+ throw corruptStore(
665
+ file,
666
+ "query index cannot be reproduced from authority",
667
+ );
668
+ if (!this.readOnly) {
669
+ const temporary = join(
670
+ this.shardDirectory,
671
+ `query-rebuild-${randomUUID()}.tmp`,
672
+ );
673
+ const fd = openSync(temporary, "wx", 0o600);
674
+ try {
675
+ writeFileSync(fd, bytes);
676
+ fsyncSync(fd);
677
+ } finally {
678
+ closeSync(fd);
679
+ }
680
+ this._checkDirectories();
681
+ if (existsSync(file)) regular(file);
682
+ renameSync(temporary, file);
683
+ syncDirectory(this.shardDirectory);
684
+ }
685
+ }
686
+ } else {
687
+ bytes = encodeQueryIndex(this._readShard(manifest, bucket));
688
+ }
689
+ const digest = descriptor.queryDigest || queryDigest(bytes);
690
+ const cached = this._queryIndexes.get(bucket);
691
+ if (cached?.digest === digest) return cached.index;
692
+ let index;
693
+ try {
694
+ index = compileQueryIndex(bytes, descriptor);
695
+ } catch (cause) {
696
+ throw corruptStore(
697
+ this.filePath,
698
+ "query index structure is invalid",
699
+ cause,
700
+ );
701
+ }
702
+ this._queryIndexes.set(bucket, { digest, index });
703
+ return index;
704
+ }
705
+
706
+ async _indexedRecords(
707
+ options = {},
708
+ { limit: count = Infinity, cursor = null } = {},
709
+ ) {
710
+ const query = normalizeListQuery(options);
711
+ const captured = await this._locked(() => {
712
+ const manifest = this._ensureQueryIndexes(this._loadManifest());
713
+ const binding = listCursorBinding(
714
+ this.filePath,
715
+ manifest.digest || queryDigest(JSON.stringify(manifest)),
716
+ query,
717
+ );
718
+ const after = decodeListCursor(cursor, binding);
719
+ if (manifest.schema === STORE_SCHEMA) {
720
+ const matches = Object.values(manifest.records)
721
+ .filter(
722
+ (row) =>
723
+ matchesListQuery(row, query) &&
724
+ (!after || compareMemoryRows(row, after) > 0),
725
+ )
726
+ .sort(compareMemoryRows);
727
+ const records = matches.slice(0, count);
728
+ return {
729
+ legacy: records,
730
+ storeRevision: manifest.storeRevision,
731
+ nextCursor:
732
+ matches.length > count
733
+ ? encodeListCursor(binding, records.at(-1))
734
+ : null,
735
+ };
736
+ }
737
+ // Merge each sorted posting lazily. Only the requested page is captured;
738
+ // every candidate has already passed scope, sink and lifecycle filters.
739
+ const heads = [];
740
+ for (const bucket of Object.keys(manifest.shards)) {
741
+ const iterator = selectQueryRows(
742
+ this._readQueryIndex(manifest, bucket),
743
+ query,
744
+ after,
745
+ );
746
+ const next = iterator.next();
747
+ if (!next.done) heads.push({ bucket, iterator, row: next.value });
748
+ }
749
+ const selected = [];
750
+ for (const row of mergeQueryRows(heads)) {
751
+ selected.push(row);
752
+ if (selected.length > count) break;
753
+ }
754
+ const more = selected.length > count;
755
+ if (more) selected.pop();
756
+ const shards = new Map();
757
+ for (const { bucket } of selected)
758
+ if (!shards.has(bucket))
759
+ shards.set(bucket, this._readShardBytes(manifest, bucket));
760
+ return {
761
+ manifest,
762
+ selected,
763
+ shards,
764
+ storeRevision: manifest.storeRevision,
765
+ nextCursor: more
766
+ ? encodeListCursor(binding, selected.at(-1).row)
767
+ : null,
768
+ };
769
+ });
770
+ if (captured.legacy)
771
+ return {
772
+ records: captured.legacy,
773
+ nextCursor: captured.nextCursor,
774
+ storeRevision: captured.storeRevision,
775
+ };
776
+ const decoded = new Map(
777
+ [...captured.shards].map(([bucket, bytes]) => [
778
+ bucket,
779
+ this._decodeShard(captured.manifest, bucket, bytes),
780
+ ]),
781
+ );
782
+ const records = captured.selected.map(({ bucket, row }) => {
783
+ const record = own(decoded.get(bucket).records, row.memoryId);
784
+ if (
785
+ !record ||
786
+ !matchesListQuery(record, query) ||
787
+ compareMemoryRows(record, row) !== 0
788
+ )
789
+ throw corruptStore(
790
+ this.filePath,
791
+ "query index result disagrees with authority",
792
+ );
793
+ return record;
794
+ });
795
+ return {
796
+ records,
797
+ nextCursor: captured.nextCursor,
798
+ storeRevision: captured.storeRevision,
799
+ };
800
+ }
801
+
802
+ async listRecords(options = {}) {
803
+ const count =
804
+ options.limit == null
805
+ ? Infinity
806
+ : Math.max(1, Number(options.limit) || 20);
807
+ return (await this._indexedRecords(options, { limit: count })).records;
808
+ }
809
+
810
+ async listPage(options = {}) {
811
+ return this._indexedRecords(options, {
812
+ limit: pageLimit(options.limit),
813
+ cursor: options.cursor,
814
+ });
815
+ }
816
+
817
+ async query(request) {
818
+ if (request?.scopeAdmissions || request?.sink) {
819
+ // Do not push recall's limit before lexical/semantic ranking in the
820
+ // kernel. Push only gates that cannot discard an admissible result.
821
+ return (
822
+ await this._indexedRecords({
823
+ scopeAdmissions: request.scopeAdmissions,
824
+ sink: request.sink,
825
+ states: ["active", "reinforced"],
826
+ })
827
+ ).records;
828
+ }
561
829
  const snapshot = await this._locked(() => {
562
830
  const manifest = this._loadManifest();
563
831
  if (manifest.schema === STORE_SCHEMA) return { legacy: manifest };