chainlesschain 0.166.129 → 0.166.131
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.
- package/README.md +24 -2
- package/package.json +2 -2
- package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
- package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/AIOps-CHItp4vg.js +1 -0
- package/src/assets/web-panel/assets/AIOps-Cchx1iXI.css +1 -0
- package/src/assets/web-panel/assets/{ActionButton-_zlP_Z6z.js → ActionButton-nhMNWW_d.js} +1 -1
- package/src/assets/web-panel/assets/Analytics-DRc81BBI.js +3 -0
- package/src/assets/web-panel/assets/Analytics-Dr-1kvaM.css +1 -0
- package/src/assets/web-panel/assets/AppLayout-BTBIIl1e.css +1 -0
- package/src/assets/web-panel/assets/AppLayout-CVt7HMkp.js +3 -0
- package/src/assets/web-panel/assets/Artifacts-BuJgG5jf.js +1 -0
- package/src/assets/web-panel/assets/Artifacts-Dohtjyfl.css +1 -0
- package/src/assets/web-panel/assets/Audit-DDnViLtj.css +1 -0
- package/src/assets/web-panel/assets/Audit-msNg0aH-.js +1 -0
- package/src/assets/web-panel/assets/BackgroundAgents-BpcV8yWC.js +1 -0
- package/src/assets/web-panel/assets/BackgroundAgents-CH3Uc9sF.css +1 -0
- package/src/assets/web-panel/assets/Backup-CYh10zO3.css +1 -0
- package/src/assets/web-panel/assets/Backup-P53DADwG.js +1 -0
- package/src/assets/web-panel/assets/BaseInput-DFxT2yWN.js +1 -0
- package/src/assets/web-panel/assets/Chat-B5JvvQJb.css +1 -0
- package/src/assets/web-panel/assets/Chat-BXoHisHW.js +7 -0
- package/src/assets/web-panel/assets/ChatBubbleRenderer-CO908iBt.css +1 -0
- package/src/assets/web-panel/assets/ChatBubbleRenderer-DMGtSdDx.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-nMgYkH8H.js → Checkbox-B4g_ckJq.js} +1 -1
- package/src/assets/web-panel/assets/Codegen-BLP7id2a.css +1 -0
- package/src/assets/web-panel/assets/Codegen-C6SSSOfp.js +1 -0
- package/src/assets/web-panel/assets/{Col-i0owJaGP.js → Col-IO1NEUYL.js} +1 -1
- package/src/assets/web-panel/assets/Community-C2RejeOY.css +1 -0
- package/src/assets/web-panel/assets/Community-CdEBl93F.js +1 -0
- package/src/assets/web-panel/assets/{Compact-DDXrvvm-.js → Compact-DYs0a9k7.js} +1 -1
- package/src/assets/web-panel/assets/Compliance-BPnk7948.js +1 -0
- package/src/assets/web-panel/assets/Compliance-DOys4Ov1.css +1 -0
- package/src/assets/web-panel/assets/Cowork-DsOst4XK.css +1 -0
- package/src/assets/web-panel/assets/Cowork-VLOTGbza.js +6 -0
- package/src/assets/web-panel/assets/Cron-_9GgQLJo.js +2 -0
- package/src/assets/web-panel/assets/Crosschain-B21yn0qy.js +1 -0
- package/src/assets/web-panel/assets/Crosschain-C7Le4Pte.css +1 -0
- package/src/assets/web-panel/assets/DID-BX6k3jZi.css +1 -0
- package/src/assets/web-panel/assets/DID-mBeDgRZ7.js +2 -0
- package/src/assets/web-panel/assets/Dashboard-BckYYzhP.js +3 -0
- package/src/assets/web-panel/assets/Dashboard-MFDcsVcM.css +1 -0
- package/src/assets/web-panel/assets/Dropdown-DEedqFiE.js +1 -0
- package/src/assets/web-panel/assets/EmailListRenderer-CMs0k9TB.js +1 -0
- package/src/assets/web-panel/assets/EmailListRenderer-CVJ1j3Ll.css +1 -0
- package/src/assets/web-panel/assets/EvolutionSettings-B00Qd0fN.js +1 -0
- package/src/assets/web-panel/assets/EvolutionSettings-BnQ91YHJ.css +1 -0
- package/src/assets/web-panel/assets/FamilyGuardDashboard-Df-D09Q4.css +1 -0
- package/src/assets/web-panel/assets/FamilyGuardDashboard-DxMTAMa8.js +1 -0
- package/src/assets/web-panel/assets/Federation-B-UZw0LO.js +1 -0
- package/src/assets/web-panel/assets/Federation-CgmfLbx1.css +1 -0
- package/src/assets/web-panel/assets/FormItemContext-CkafazEw.js +1 -0
- package/src/assets/web-panel/assets/GenericCardRenderer-DEUG25ZJ.js +1 -0
- package/src/assets/web-panel/assets/GenericCardRenderer-DtJFcJYl.css +1 -0
- package/src/assets/web-panel/assets/Git-D7dr9oz9.js +2 -0
- package/src/assets/web-panel/assets/{Git-BdHhxBWR.css → Git-DPuaGtg7.css} +1 -1
- package/src/assets/web-panel/assets/Governance-BoipmXaM.css +1 -0
- package/src/assets/web-panel/assets/Governance-DKlUJ1wg.js +1 -0
- package/src/assets/web-panel/assets/Inference-BJKqplap.js +1 -0
- package/src/assets/web-panel/assets/Inference-BWxYJF9-.css +1 -0
- package/src/assets/web-panel/assets/KnowledgeGraph-B78fB-bz.js +1 -0
- package/src/assets/web-panel/assets/KnowledgeGraph-CztPDA96.css +1 -0
- package/src/assets/web-panel/assets/Logs-DJGcHYH_.js +2 -0
- package/src/assets/web-panel/assets/Logs-Gf_Mv9Nx.css +1 -0
- package/src/assets/web-panel/assets/MarkdownRenderer-BAxj61I3.css +1 -0
- package/src/assets/web-panel/assets/MarkdownRenderer-DkcG_MxW.js +1 -0
- package/src/assets/web-panel/assets/Marketplace-Djp5q9dS.css +1 -0
- package/src/assets/web-panel/assets/Marketplace-ucTbwByD.js +1 -0
- package/src/assets/web-panel/assets/McpTools-Cu1xZYYk.js +2 -0
- package/src/assets/web-panel/assets/McpTools-DSGHWYS_.css +1 -0
- package/src/assets/web-panel/assets/Memory-Bcc2hxOA.css +1 -0
- package/src/assets/web-panel/assets/Memory-DCGpXmi-.js +2 -0
- package/src/assets/web-panel/assets/MobileBridge-BQ-Uwwg7.css +1 -0
- package/src/assets/web-panel/assets/MobileBridge-BnKr0aAS.js +1 -0
- package/src/assets/web-panel/assets/MobileProjects-C5UvYJTP.js +1 -0
- package/src/assets/web-panel/assets/MobileProjects-Ceaxrqzc.css +1 -0
- package/src/assets/web-panel/assets/Mtc-D1UUl4WH.js +6 -0
- package/src/assets/web-panel/assets/Mtc-DHwbdUqA.css +1 -0
- package/src/assets/web-panel/assets/MtcAudit-B0x8gahq.css +1 -0
- package/src/assets/web-panel/assets/MtcAudit-D3aa8XP4.js +19 -0
- package/src/assets/web-panel/assets/Multisig-DiXdfJjO.js +7 -0
- package/src/assets/web-panel/assets/Multisig-kwPDnXnl.css +1 -0
- package/src/assets/web-panel/assets/NLProgramming-CLOvy-35.css +1 -0
- package/src/assets/web-panel/assets/NLProgramming-DbWABgSE.js +1 -0
- package/src/assets/web-panel/assets/Notes-BP1DPl-R.js +7 -0
- package/src/assets/web-panel/assets/Notes-COE2q2gD.css +1 -0
- package/src/assets/web-panel/assets/NotificationSettings-Co0e0uEO.css +1 -0
- package/src/assets/web-panel/assets/NotificationSettings-xaB6ONe7.js +1 -0
- package/src/assets/web-panel/assets/OrderTableRenderer-BnOISpKI.css +1 -0
- package/src/assets/web-panel/assets/OrderTableRenderer-D1uNcz3b.js +1 -0
- package/src/assets/web-panel/assets/Organization-BM3Lh8Q8.css +1 -0
- package/src/assets/web-panel/assets/Organization-DMLDGaf1.js +4 -0
- package/src/assets/web-panel/assets/{Overflow-CaRUAOY_.js → Overflow-DH4QPEoI.js} +1 -1
- package/src/assets/web-panel/assets/{OverrideContext-C0w0P4A3.js → OverrideContext-DLR1AtLy.js} +1 -1
- package/src/assets/web-panel/assets/P2P-Bl4OS10o.js +2 -0
- package/src/assets/web-panel/assets/P2P-Cx88UaiD.css +1 -0
- package/src/assets/web-panel/assets/PdhVaultBrowser-B9ZGFpn4.css +1 -0
- package/src/assets/web-panel/assets/PdhVaultBrowser-D9XSE2YI.js +7 -0
- package/src/assets/web-panel/assets/Permissions-CUaPlr6d.js +4 -0
- package/src/assets/web-panel/assets/Permissions-Diejgkbs.css +1 -0
- package/src/assets/web-panel/assets/PersonalDataHub-Ba92dZk-.js +3 -0
- package/src/assets/web-panel/assets/PersonalDataHub-C_xhspRy.css +1 -0
- package/src/assets/web-panel/assets/Pipeline-Bh2okm-8.js +1 -0
- package/src/assets/web-panel/assets/Pipeline-DxkXqrH2.css +1 -0
- package/src/assets/web-panel/assets/Privacy-Bmq3p4gC.js +1 -0
- package/src/assets/web-panel/assets/Privacy-CrsfSFKd.css +1 -0
- package/src/assets/web-panel/assets/ProjectInit-BPu2fdKR.js +2 -0
- package/src/assets/web-panel/assets/ProjectInit-CteEo-wF.css +1 -0
- package/src/assets/web-panel/assets/ProjectSettings-D6ABLpmt.js +2 -0
- package/src/assets/web-panel/assets/ProjectSettings-pLSae-wy.css +1 -0
- package/src/assets/web-panel/assets/Projects-BX-SG9R4.css +1 -0
- package/src/assets/web-panel/assets/Projects-qWHEve0z.js +1 -0
- package/src/assets/web-panel/assets/Providers-CpAXh_6c.css +1 -0
- package/src/assets/web-panel/assets/Providers-D9DI-2hc.js +1 -0
- package/src/assets/web-panel/assets/{QrScannerModal-fFkycCT4.js → QrScannerModal-CxifoeD5.js} +1 -1
- package/src/assets/web-panel/assets/QrScannerModal-DFrn7rxS.css +1 -0
- package/src/assets/web-panel/assets/QuickAsk-DC1BvwR7.js +1 -0
- package/src/assets/web-panel/assets/Recommend-CH6wKzGo.css +1 -0
- package/src/assets/web-panel/assets/Recommend-CKqbMB5o.js +1 -0
- package/src/assets/web-panel/assets/RemoteSession-BGGzPdS5.js +5 -0
- package/src/assets/web-panel/assets/Reputation-D6VPNEd0.css +1 -0
- package/src/assets/web-panel/assets/Reputation-DH90O9-5.js +1 -0
- package/src/assets/web-panel/assets/Row-h7ovueJc.js +1 -0
- package/src/assets/web-panel/assets/RssFeed-Cze7YLaG.css +1 -0
- package/src/assets/web-panel/assets/RssFeed-DaHxXTZg.js +3 -0
- package/src/assets/web-panel/assets/Search-B6RalzTB.css +1 -0
- package/src/assets/web-panel/assets/Search-Bn6Nqpn4.js +1 -0
- package/src/assets/web-panel/assets/Security-13K57V_v.css +1 -0
- package/src/assets/web-panel/assets/Security-ClbBmPJi.js +4 -0
- package/src/assets/web-panel/assets/Services-C8Qs6KXv.css +1 -0
- package/src/assets/web-panel/assets/Services-ChHLQwRn.js +2 -0
- package/src/assets/web-panel/assets/{Skeleton-ASRgSh_Y.js → Skeleton-DfN6BFzt.js} +1 -1
- package/src/assets/web-panel/assets/Skills-BdjRyorN.css +1 -0
- package/src/assets/web-panel/assets/Skills-C926wDev.js +1 -0
- package/src/assets/web-panel/assets/Sla-DJzi1l1M.js +1 -0
- package/src/assets/web-panel/assets/Sla-K19oOyQc.css +1 -0
- package/src/assets/web-panel/assets/SpeechSettings-DYPJTDKz.css +1 -0
- package/src/assets/web-panel/assets/SpeechSettings-_GSyVjm_.js +1 -0
- package/src/assets/web-panel/assets/SyncSettings-B67xnERe.js +1 -0
- package/src/assets/web-panel/assets/SyncSettings-C6cDrwDR.css +1 -0
- package/src/assets/web-panel/assets/Tasks-BJjN_YEm.css +1 -0
- package/src/assets/web-panel/assets/Tasks-BaYZadcG.js +1 -0
- package/src/assets/web-panel/assets/Templates-BsMmCdZI.css +1 -0
- package/src/assets/web-panel/assets/Templates-Bu8kN1Xt.js +1 -0
- package/src/assets/web-panel/assets/Tenant-BM9qufw1.js +1 -0
- package/src/assets/web-panel/assets/Tenant-D3zkSAV0.css +1 -0
- package/src/assets/web-panel/assets/Terminal-MEdd5DjB.js +3 -0
- package/src/assets/web-panel/assets/Terminal-qPp9MaPu.css +1 -0
- package/src/assets/web-panel/assets/TimelineRenderer-C27kL2oU.js +1 -0
- package/src/assets/web-panel/assets/TimelineRenderer-DmztdsbF.css +1 -0
- package/src/assets/web-panel/assets/Tokens-BBOdNRHQ.css +1 -0
- package/src/assets/web-panel/assets/Tokens-Cvjd98VC.js +1 -0
- package/src/assets/web-panel/assets/{Trigger-DgGU_D0o.js → Trigger-CLym84HI.js} +1 -1
- package/src/assets/web-panel/assets/Trust-Bv2JTaNN.js +1 -0
- package/src/assets/web-panel/assets/Trust-DeOo0xAh.css +1 -0
- package/src/assets/web-panel/assets/UkeySign-CSCkNbtm.js +1 -0
- package/src/assets/web-panel/assets/VideoEditing-BFDXB4xh.js +1 -0
- package/src/assets/web-panel/assets/VideoEditing-DksiizfS.css +1 -0
- package/src/assets/web-panel/assets/Wallet-CMEFrG_b.js +4 -0
- package/src/assets/web-panel/assets/Wallet-Dw8uV4Ug.css +1 -0
- package/src/assets/web-panel/assets/WebAuthn-DKx6xPPl.css +1 -0
- package/src/assets/web-panel/assets/WebAuthn-x4eO_Q4y.js +5 -0
- package/src/assets/web-panel/assets/WorkflowEditor-ClWEPgV1.js +1 -0
- package/src/assets/web-panel/assets/WorkflowEditor-IiwsD8Kh.css +1 -0
- package/src/assets/web-panel/assets/{_getTag-DnrRH4E6.js → _getTag-BVc6NQ_K.js} +1 -1
- package/src/assets/web-panel/assets/{chat-C_kELmV6.js → chat-BdYOI4gM.js} +1 -1
- package/src/assets/web-panel/assets/{collapseMotion-CqM1QOwM.js → collapseMotion-B4IZiILV.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DE-ZxAv_.js → colors-DcTBrGvS.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BowulLDi.js → compact-item-Dn2ktVuj.js} +1 -1
- package/src/assets/web-panel/assets/createContext-XTreuyqp.js +1 -0
- package/src/assets/web-panel/assets/{debounce-CFGTTtN3.js → debounce-D9xTw4Sx.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-CNIS3FrJ.js +1 -0
- package/src/assets/web-panel/assets/echarts-CDp6K7pj.js +19 -0
- package/src/assets/web-panel/assets/{hasIn-Be7mK-iw.js → hasIn-CFRNsYQd.js} +1 -1
- package/src/assets/web-panel/assets/{icons-DG5UD-6K.js → icons-DlxlFL4g.js} +4 -4
- package/src/assets/web-panel/assets/index-3RqDry-K.js +71 -0
- package/src/assets/web-panel/assets/{index-nLHTuHoT.js → index-8METW_Wr.js} +1 -1
- package/src/assets/web-panel/assets/index-BBd64wj8.js +31 -0
- package/src/assets/web-panel/assets/index-BEyVNbNE.js +3 -0
- package/src/assets/web-panel/assets/index-BMLpP8QQ.js +1 -0
- package/src/assets/web-panel/assets/{index-DMKo49Um.js → index-BSqydcDa.js} +1 -1
- package/src/assets/web-panel/assets/index-BV6LojRv.js +21 -0
- package/src/assets/web-panel/assets/index-BbMWvjLZ.js +1 -0
- package/src/assets/web-panel/assets/{index-DjC2TJeH.js → index-Brc0BF-k.js} +2 -2
- package/src/assets/web-panel/assets/{index-3Ql7xQLn.js → index-CG9YLDmI.js} +1 -1
- package/src/assets/web-panel/assets/{index-lN916819.js → index-CNHWMMDX.js} +1 -1
- package/src/assets/web-panel/assets/{index-DLCzaLH4.js → index-COuEJdmr.js} +3 -3
- package/src/assets/web-panel/assets/{index-BdzVLz-c.js → index-CRW3AWdS.js} +1 -1
- package/src/assets/web-panel/assets/{index-_cYsz4df.js → index-CUT4h5JB.js} +2 -2
- package/src/assets/web-panel/assets/index-CXMa7Z-S.js +1 -0
- package/src/assets/web-panel/assets/index-CbaPXyNc.js +19 -0
- package/src/assets/web-panel/assets/{index-Cq93VfoF.css → index-CfX1DEtk.css} +1 -1
- package/src/assets/web-panel/assets/{index-OH54KMLN.js → index-CjHA_Q7s.js} +1 -1
- package/src/assets/web-panel/assets/index-CsnYp4qF.js +1 -0
- package/src/assets/web-panel/assets/index-D45vulkq.js +12 -0
- package/src/assets/web-panel/assets/index-D9kPBEqD.js +55 -0
- package/src/assets/web-panel/assets/index-DDTSgpXz.js +1 -0
- package/src/assets/web-panel/assets/index-DFl_a0n5.js +1 -0
- package/src/assets/web-panel/assets/index-DNdiAymC.js +1 -0
- package/src/assets/web-panel/assets/{index-DEDVYN7D.js → index-DQEu7uW0.js} +1 -1
- package/src/assets/web-panel/assets/index-DW9XncMy.js +21 -0
- package/src/assets/web-panel/assets/index-Daa1yCt_.js +1 -0
- package/src/assets/web-panel/assets/index-DdVpoNEQ.js +12 -0
- package/src/assets/web-panel/assets/index-Dhi4Oybt.js +1 -0
- package/src/assets/web-panel/assets/index-DoVoNjtJ.js +1 -0
- package/src/assets/web-panel/assets/{index-Ao-LXr-d.js → index-Vo7A4aiN.js} +4 -4
- package/src/assets/web-panel/assets/{index-LVrxqU88.js → index-XdlYkgCa.js} +1 -1
- package/src/assets/web-panel/assets/{index-4KkYmFy5.js → index-ir2ZwWz5.js} +2 -2
- package/src/assets/web-panel/assets/index-kzyCd8a0.js +3 -0
- package/src/assets/web-panel/assets/{index-Cvy4vdVW.js → index-lnTt0Jps.js} +2 -2
- package/src/assets/web-panel/assets/{index-D3lOYd9_.js → index-ma-rJkfE.js} +1 -1
- package/src/assets/web-panel/assets/index-oE4jTpHK.js +13 -0
- package/src/assets/web-panel/assets/{index-CXvy8HrM.js → index-r5sNECM5.js} +1 -1
- package/src/assets/web-panel/assets/index-uT4fRDzU.js +1 -0
- package/src/assets/web-panel/assets/index-xlS8pDS2.js +1 -0
- package/src/assets/web-panel/assets/{initDefaultProps-BNhziAal.js → initDefaultProps-mdL0oeZa.js} +1 -1
- package/src/assets/web-panel/assets/{isPlainObject-BWRMT62c.js → isPlainObject-_gz-soRW.js} +1 -1
- package/src/assets/web-panel/assets/isSymbol-DAy2hlR5.js +1 -0
- package/src/assets/web-panel/assets/motion-ZgVCKcEX.js +11 -0
- package/src/assets/web-panel/assets/{move-rFx211Cl.js → move-A_28O5T2.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-CEP1wN3R.js → mtc-parser-0zlMjabo.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DacHd_Zm.js → omit-DF7mU3yG.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-Dqp58Ep2.js → pickAttrs-Cmt8liJP.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-Cv6Rm0pV.js → placementArrow-DaMDC57b.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-rNE0p9ZW.js → responsiveObserve-CHw_f2d3.js} +1 -1
- package/src/assets/web-panel/assets/{slide-C97JxD4S.js → slide-DJS9fFQq.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-Cxk1gV9M.js → statusUtils-Bk3XdZwh.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-CbtKKsPo.js → styleChecker-DMybAFsA.js} +1 -1
- package/src/assets/web-panel/assets/useFlexGapSupport-_tbIIFMu.js +1 -0
- package/src/assets/web-panel/assets/{useFs-6c7qrpE_.js → useFs-KPklVptS.js} +1 -1
- package/src/assets/web-panel/assets/{useMergedState-DXbJa_zE.js → useMergedState-d-EXs3xd.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-OjxtBGe7.js → usePersonalDataHub-C7FrKDhD.js} +1 -1
- package/src/assets/web-panel/assets/{useRefs-BrCfMLMc.js → useRefs-DHeCQehi.js} +1 -1
- package/src/assets/web-panel/assets/{useState-CnxtbLoC.js → useState-Dlgl7fUg.js} +1 -1
- package/src/assets/web-panel/assets/vendor-BXcBOG8b.js +1 -0
- package/src/assets/web-panel/assets/vnode-DB3JBusp.js +1 -0
- package/src/assets/web-panel/assets/warning-Pq00owYb.js +1 -0
- package/src/assets/web-panel/assets/{zoom-Cc1qKiSZ.js → zoom-C8rAdf81.js} +1 -1
- package/src/assets/web-panel/index.html +4 -4
- package/src/command-help-index.json +1 -1
- package/src/commands/agent.js +1 -1
- package/src/commands/governed-skill-marketplace.js +24 -10
- package/src/commands/llm.js +4 -3
- package/src/constants.js +1 -1
- package/src/data/changelog.json +27 -1
- package/src/harness/worktree-isolator.js +4 -1
- package/src/lib/compaction-host-provenance.js +24 -0
- package/src/lib/context-memory-kernel/durable-memory-port.js +46 -34
- package/src/lib/context-memory-kernel/live-compaction.js +12 -3
- package/src/lib/context-memory-kernel/memory-query-bundle.js +375 -0
- package/src/lib/context-memory-kernel/memory-query-control.js +28 -0
- package/src/lib/context-memory-kernel/memory-service.js +30 -16
- package/src/lib/context-memory-kernel/memory-shard-snapshots.js +63 -0
- package/src/lib/context-memory-kernel/provider-context.js +55 -24
- package/src/lib/context-memory-kernel/segmented-memory-port.js +347 -138
- package/src/lib/cost-budget.js +2 -0
- package/src/lib/ephemeral-worktree-scope.js +24 -0
- package/src/lib/evolution/evolution-deployment-loader.js +6 -4
- package/src/lib/evolution/governed-skill-marketplace-abort.js +14 -0
- package/src/lib/evolution/governed-skill-marketplace-candidate.js +10 -2
- package/src/lib/evolution/governed-skill-marketplace-cli-host.js +47 -20
- package/src/lib/evolution/governed-skill-marketplace.js +47 -24
- package/src/lib/goal-assess.js +4 -1
- package/src/lib/goal-check-evidence.js +77 -9
- package/src/lib/goal-condition-engine.js +20 -3
- package/src/lib/goal-model-call.js +107 -0
- package/src/lib/goal-verification-command.js +221 -0
- package/src/lib/goal-verification-plan.js +372 -0
- package/src/lib/goal-workspace-evidence.js +299 -0
- package/src/lib/llm-connection-probe.js +12 -5
- package/src/lib/llm-onboarding-catalog.json +2 -2
- package/src/lib/llm-pricing.js +34 -8
- package/src/lib/llm-providers.js +1 -0
- package/src/lib/mcp-tool-catalog-authority.js +244 -0
- package/src/lib/model-capabilities.js +6 -0
- package/src/lib/model-catalog-review.js +3 -0
- package/src/lib/model-context-catalog.js +44 -2
- package/src/lib/openai-responses.js +35 -6
- package/src/lib/sub-agent-context.js +12 -4
- package/src/lib/subagent-inheritance.js +162 -2
- package/src/lib/task-model-selector.js +1 -1
- package/src/lib/usage-pricing-context.js +34 -17
- package/src/repl/agent-repl.js +34 -2
- package/src/runtime/agent-core.js +226 -10
- package/src/runtime/compaction-host-context.js +72 -0
- package/src/runtime/headless-runner.js +331 -141
- package/src/runtime/headless-stream.js +38 -21
- package/src/runtime/mcp-agent-catalog.js +257 -0
- package/src/runtime/mcp-config.js +18 -69
- package/src/runtime/mcp-tool-search.js +16 -1
- package/src/runtime/system-prompt.js +9 -0
- package/src/assets/web-panel/assets/AIOps-CSpp7iGY.css +0 -1
- package/src/assets/web-panel/assets/AIOps-CjPaaF2r.js +0 -1
- package/src/assets/web-panel/assets/Analytics-C7X31L8l.js +0 -3
- package/src/assets/web-panel/assets/Analytics-DJcHjy5J.css +0 -1
- package/src/assets/web-panel/assets/AppLayout-BmYa34Se.js +0 -9
- package/src/assets/web-panel/assets/AppLayout-VlanTjPw.css +0 -1
- package/src/assets/web-panel/assets/Artifacts-B_YKNjlp.js +0 -1
- package/src/assets/web-panel/assets/Artifacts-CTVt96zW.css +0 -1
- package/src/assets/web-panel/assets/Audit-5JsI67XQ.js +0 -1
- package/src/assets/web-panel/assets/Audit-D8oxP0wr.css +0 -1
- package/src/assets/web-panel/assets/BackgroundAgents-BL3QbzvS.js +0 -1
- package/src/assets/web-panel/assets/BackgroundAgents-Dq2340Kl.css +0 -1
- package/src/assets/web-panel/assets/Backup-BRmg-gTa.js +0 -1
- package/src/assets/web-panel/assets/Backup-Wi9CaP3d.css +0 -1
- package/src/assets/web-panel/assets/BaseInput-DNE7mT3K.js +0 -1
- package/src/assets/web-panel/assets/Chat-KSGPtU0L.css +0 -1
- package/src/assets/web-panel/assets/Chat-OYwAopdM.js +0 -8
- package/src/assets/web-panel/assets/ChatBubbleRenderer-Dtxw3Wgt.js +0 -1
- package/src/assets/web-panel/assets/ChatBubbleRenderer-gy5SDGw2.css +0 -1
- package/src/assets/web-panel/assets/Codegen-B9G2ngLI.js +0 -1
- package/src/assets/web-panel/assets/Codegen-BB08p1fn.css +0 -1
- package/src/assets/web-panel/assets/Community-B3Ta0mI_.js +0 -1
- package/src/assets/web-panel/assets/Community-Cbq1nrpo.css +0 -1
- package/src/assets/web-panel/assets/Compliance-Bn4Uq6U1.js +0 -1
- package/src/assets/web-panel/assets/Compliance-NoXr2Vof.css +0 -1
- package/src/assets/web-panel/assets/Cowork-BlXJRu6L.css +0 -1
- package/src/assets/web-panel/assets/Cowork-CO5NKD6r.js +0 -6
- package/src/assets/web-panel/assets/Cron-ByjNese0.js +0 -2
- package/src/assets/web-panel/assets/Crosschain-BN1FUYyi.js +0 -1
- package/src/assets/web-panel/assets/Crosschain-CgRAecoR.css +0 -1
- package/src/assets/web-panel/assets/DID-CUFX5RL3.js +0 -2
- package/src/assets/web-panel/assets/DID-DVsYcgvs.css +0 -1
- package/src/assets/web-panel/assets/Dashboard-CAPSdFR4.css +0 -1
- package/src/assets/web-panel/assets/Dashboard-D_2FDPBP.js +0 -3
- package/src/assets/web-panel/assets/Dropdown-lGOMtIzb.js +0 -1
- package/src/assets/web-panel/assets/EmailListRenderer-DA3Qf1S2.js +0 -1
- package/src/assets/web-panel/assets/EmailListRenderer-DTPZPx_S.css +0 -1
- package/src/assets/web-panel/assets/EvolutionSettings-Bdw8ApoT.css +0 -1
- package/src/assets/web-panel/assets/EvolutionSettings-DLcnicCr.js +0 -1
- package/src/assets/web-panel/assets/FamilyGuardDashboard-BPOSaIN1.js +0 -1
- package/src/assets/web-panel/assets/FamilyGuardDashboard-nd3idUVb.css +0 -1
- package/src/assets/web-panel/assets/Federation-DzJUCQq8.js +0 -1
- package/src/assets/web-panel/assets/Federation-fGN6iMX_.css +0 -1
- package/src/assets/web-panel/assets/FormItemContext-DVx1XNKx.js +0 -2
- package/src/assets/web-panel/assets/GenericCardRenderer-BkqzO_lh.js +0 -1
- package/src/assets/web-panel/assets/GenericCardRenderer-o85VDYQS.css +0 -1
- package/src/assets/web-panel/assets/Git-Dr_rdT_j.js +0 -2
- package/src/assets/web-panel/assets/Governance-DtCS4NDm.css +0 -1
- package/src/assets/web-panel/assets/Governance-DyVkZddw.js +0 -1
- package/src/assets/web-panel/assets/Inference-IN2YDd4v.js +0 -1
- package/src/assets/web-panel/assets/Inference-t-w0NgIS.css +0 -1
- package/src/assets/web-panel/assets/KnowledgeGraph-4NU1S2Xm.css +0 -1
- package/src/assets/web-panel/assets/KnowledgeGraph-Ceiy4n6N.js +0 -1
- package/src/assets/web-panel/assets/Logs-DQbCaYhL.css +0 -1
- package/src/assets/web-panel/assets/Logs-d7pIEAX2.js +0 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-DbzhFwvz.css +0 -1
- package/src/assets/web-panel/assets/MarkdownRenderer-DmSl0MNI.js +0 -1
- package/src/assets/web-panel/assets/Marketplace-Bvo5cuGa.css +0 -1
- package/src/assets/web-panel/assets/Marketplace-uVE7U14g.js +0 -1
- package/src/assets/web-panel/assets/McpTools-534Q95Mx.css +0 -1
- package/src/assets/web-panel/assets/McpTools-DUfBM--y.js +0 -4
- package/src/assets/web-panel/assets/Memory-6gkcR02J.js +0 -2
- package/src/assets/web-panel/assets/Memory-CleW_R6V.css +0 -1
- package/src/assets/web-panel/assets/MobileBridge-Cl6ys2O9.js +0 -1
- package/src/assets/web-panel/assets/MobileBridge-D3Arxfeg.css +0 -1
- package/src/assets/web-panel/assets/MobileProjects-5P8jN4gf.js +0 -1
- package/src/assets/web-panel/assets/MobileProjects-BD4alw6-.css +0 -1
- package/src/assets/web-panel/assets/Mtc-CXZGO9Sh.css +0 -1
- package/src/assets/web-panel/assets/Mtc-DtiT1Kol.js +0 -6
- package/src/assets/web-panel/assets/MtcAudit-C1JM8esp.css +0 -1
- package/src/assets/web-panel/assets/MtcAudit-DZz8iiTE.js +0 -19
- package/src/assets/web-panel/assets/Multisig-BryR2Jpr.css +0 -1
- package/src/assets/web-panel/assets/Multisig-DFH3-fBJ.js +0 -13
- package/src/assets/web-panel/assets/NLProgramming-BYNuDOt-.js +0 -1
- package/src/assets/web-panel/assets/NLProgramming-DGDHq6Z9.css +0 -1
- package/src/assets/web-panel/assets/Notes-BCY4jgYy.js +0 -7
- package/src/assets/web-panel/assets/Notes-BKKmMtqV.css +0 -1
- package/src/assets/web-panel/assets/NotificationSettings-Bk2ltghU.js +0 -1
- package/src/assets/web-panel/assets/NotificationSettings-CG3Kfuef.css +0 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-CfrDjSHT.css +0 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-OdeXEGAn.js +0 -1
- package/src/assets/web-panel/assets/Organization-CY4_mSiV.js +0 -4
- package/src/assets/web-panel/assets/Organization-LVvqwG0D.css +0 -1
- package/src/assets/web-panel/assets/P2P-Bd96rBWQ.js +0 -2
- package/src/assets/web-panel/assets/P2P-DcFvP7F-.css +0 -1
- package/src/assets/web-panel/assets/PdhVaultBrowser-DZZrUOr1.css +0 -1
- package/src/assets/web-panel/assets/PdhVaultBrowser-JjnExxan.js +0 -7
- package/src/assets/web-panel/assets/Permissions-CW1PUJB0.js +0 -4
- package/src/assets/web-panel/assets/Permissions-DsPE_IQy.css +0 -1
- package/src/assets/web-panel/assets/PersonalDataHub-BNn9alTk.js +0 -9
- package/src/assets/web-panel/assets/PersonalDataHub-BhpRlh9D.css +0 -1
- package/src/assets/web-panel/assets/Pipeline-01_PBiUu.js +0 -1
- package/src/assets/web-panel/assets/Pipeline-BItr5CyP.css +0 -1
- package/src/assets/web-panel/assets/Privacy-BP4DlVGb.js +0 -1
- package/src/assets/web-panel/assets/Privacy-F_ENsxZk.css +0 -1
- package/src/assets/web-panel/assets/ProjectInit-B86LEzDL.css +0 -1
- package/src/assets/web-panel/assets/ProjectInit-CAMnQj4n.js +0 -2
- package/src/assets/web-panel/assets/ProjectSettings-DK7KA_iX.css +0 -1
- package/src/assets/web-panel/assets/ProjectSettings-DKxV5On_.js +0 -2
- package/src/assets/web-panel/assets/Projects-B_4kRnM8.js +0 -1
- package/src/assets/web-panel/assets/Projects-CmJeUDBW.css +0 -1
- package/src/assets/web-panel/assets/Providers-C6q_fvea.css +0 -1
- package/src/assets/web-panel/assets/Providers-DeqqZyUv.js +0 -1
- package/src/assets/web-panel/assets/QrScannerModal-NwAHNfiJ.css +0 -1
- package/src/assets/web-panel/assets/QuickAsk-Ln6qQidy.js +0 -1
- package/src/assets/web-panel/assets/Recommend-D_bf91K6.css +0 -1
- package/src/assets/web-panel/assets/Recommend-DeENA-y0.js +0 -1
- package/src/assets/web-panel/assets/RemoteSession-CRxSYxo4.js +0 -5
- package/src/assets/web-panel/assets/Reputation-B2kU2F0l.js +0 -1
- package/src/assets/web-panel/assets/Reputation-DiOsOleI.css +0 -1
- package/src/assets/web-panel/assets/Row-lV_nLlFq.js +0 -1
- package/src/assets/web-panel/assets/RssFeed-CjcbkyUb.css +0 -1
- package/src/assets/web-panel/assets/RssFeed-Df21mCdF.js +0 -3
- package/src/assets/web-panel/assets/Search-8_Dz4qU9.js +0 -1
- package/src/assets/web-panel/assets/Search-Klk29S7C.css +0 -1
- package/src/assets/web-panel/assets/Security-BmrukMHn.css +0 -1
- package/src/assets/web-panel/assets/Security-Cl5-PEcp.js +0 -4
- package/src/assets/web-panel/assets/Services-C5qgCqA7.js +0 -2
- package/src/assets/web-panel/assets/Services-DAnVNhUG.css +0 -1
- package/src/assets/web-panel/assets/Skills-BUu9owbR.css +0 -1
- package/src/assets/web-panel/assets/Skills-DWx01ZJ7.js +0 -1
- package/src/assets/web-panel/assets/Sla-I2gbgtW8.js +0 -1
- package/src/assets/web-panel/assets/Sla-sodqCU4a.css +0 -1
- package/src/assets/web-panel/assets/SpeechSettings-BqTikzfe.js +0 -1
- package/src/assets/web-panel/assets/SpeechSettings-CgB9nFyq.css +0 -1
- package/src/assets/web-panel/assets/SyncSettings-B3hJqmBP.css +0 -1
- package/src/assets/web-panel/assets/SyncSettings-D3zCpBFV.js +0 -2
- package/src/assets/web-panel/assets/Tasks-DjMWII45.js +0 -1
- package/src/assets/web-panel/assets/Tasks-nbTUVXvt.css +0 -1
- package/src/assets/web-panel/assets/Templates-CpFsKk_l.css +0 -1
- package/src/assets/web-panel/assets/Templates-Cq7qDnHX.js +0 -1
- package/src/assets/web-panel/assets/Tenant-DEasKDpQ.js +0 -1
- package/src/assets/web-panel/assets/Tenant-MuPJnOjk.css +0 -1
- package/src/assets/web-panel/assets/Terminal-DHoveJwj.css +0 -1
- package/src/assets/web-panel/assets/Terminal-J6fLkTzi.js +0 -3
- package/src/assets/web-panel/assets/TimelineRenderer-BlTAtkOc.css +0 -1
- package/src/assets/web-panel/assets/TimelineRenderer-CNvWrWN-.js +0 -1
- package/src/assets/web-panel/assets/Tokens-BSgHJCKH.js +0 -1
- package/src/assets/web-panel/assets/Tokens-CynVae-o.css +0 -1
- package/src/assets/web-panel/assets/Trust-BANlv-uB.js +0 -1
- package/src/assets/web-panel/assets/Trust-C-WrW0Fj.css +0 -1
- package/src/assets/web-panel/assets/UkeySign-qh8GPRsU.js +0 -1
- package/src/assets/web-panel/assets/VideoEditing-BDFghpzP.css +0 -1
- package/src/assets/web-panel/assets/VideoEditing-DBiGTB4H.js +0 -1
- package/src/assets/web-panel/assets/Wallet-DMUFR7cL.js +0 -4
- package/src/assets/web-panel/assets/Wallet-DUbpTRcg.css +0 -1
- package/src/assets/web-panel/assets/WebAuthn-CVAFRfCQ.css +0 -1
- package/src/assets/web-panel/assets/WebAuthn-DP9nQQzW.js +0 -5
- package/src/assets/web-panel/assets/WorkflowEditor-429lPWYk.css +0 -1
- package/src/assets/web-panel/assets/WorkflowEditor-DT_6jDkL.js +0 -1
- package/src/assets/web-panel/assets/createContext-DCh8oMBQ.js +0 -1
- package/src/assets/web-panel/assets/devWarning-BVvJAp91.js +0 -1
- package/src/assets/web-panel/assets/echarts-C61Vn3mP.js +0 -25
- package/src/assets/web-panel/assets/index-6OluUVJJ.js +0 -55
- package/src/assets/web-panel/assets/index-B-3EDOlf.js +0 -1
- package/src/assets/web-panel/assets/index-B7IhCfsh.js +0 -1
- package/src/assets/web-panel/assets/index-BDIIR8g6.js +0 -1
- package/src/assets/web-panel/assets/index-BMrbe_Ey.js +0 -1
- package/src/assets/web-panel/assets/index-BlzMqaWB.js +0 -1
- package/src/assets/web-panel/assets/index-BwY31W-u.js +0 -12
- package/src/assets/web-panel/assets/index-C2pCquZC.js +0 -1
- package/src/assets/web-panel/assets/index-CKmC6ugN.js +0 -1
- package/src/assets/web-panel/assets/index-CL2hAUWh.js +0 -1
- package/src/assets/web-panel/assets/index-CUXfwAhF.js +0 -3
- package/src/assets/web-panel/assets/index-C_VnSUjh.js +0 -3
- package/src/assets/web-panel/assets/index-CecGCLWI.js +0 -31
- package/src/assets/web-panel/assets/index-Ck6MYKVN.js +0 -21
- package/src/assets/web-panel/assets/index-CwJfLNqv.js +0 -1
- package/src/assets/web-panel/assets/index-DMDaGPxG.js +0 -19
- package/src/assets/web-panel/assets/index-DN1AT3FH.js +0 -1
- package/src/assets/web-panel/assets/index-DOebEvgn.js +0 -1
- package/src/assets/web-panel/assets/index-DPX3N4T8.js +0 -13
- package/src/assets/web-panel/assets/index-DSRKtgJg.js +0 -1
- package/src/assets/web-panel/assets/index-DSqZBvQM.js +0 -12
- package/src/assets/web-panel/assets/index-DbrQO1p9.js +0 -21
- package/src/assets/web-panel/assets/index-Qx8cTReg.js +0 -75
- package/src/assets/web-panel/assets/isSymbol-S5WZT7lS.js +0 -1
- package/src/assets/web-panel/assets/motion-fUkbJz38.js +0 -11
- package/src/assets/web-panel/assets/useFlexGapSupport-CQATs2JQ.js +0 -1
- package/src/assets/web-panel/assets/vendor-Bn1JzzAn.js +0 -42
- package/src/assets/web-panel/assets/vnode-CSlXfUSh.js +0 -1
package/src/data/changelog.json
CHANGED
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"source": "CHANGELOG.md",
|
|
3
3
|
"releases": [
|
|
4
|
+
{
|
|
5
|
+
"productVersion": null,
|
|
6
|
+
"cliVersion": "0.166.131",
|
|
7
|
+
"cliVersions": ["0.166.131"],
|
|
8
|
+
"date": "2026-10-29",
|
|
9
|
+
"title": "",
|
|
10
|
+
"sections": [
|
|
11
|
+
{
|
|
12
|
+
"heading": "Fixed - cc CLI 0.166.131: memory consistency and temporary worktree ownership (candidate, 2026-10-29)",
|
|
13
|
+
"body": "- Bind Memory recall to the same monotonic revision before and after query/ranking, and interrupt asynchronous semantic candidate waits on Stop. Late results cannot resume a cancelled request.\n- Verify all disk query bundle frames and file identities with exact BigInt metadata; narrowly bridge affected Windows libuv path-device projections through independently opened parent/volume handles. Preserve replacement, link, corruption and cleanup refusals.\n- Refresh project rules and Memory around canonical compaction; validate real killed-writer recovery and independent mutation/readback without duplicating compaction events. Incomplete semantic usage intents require reconciliation. Full IDE recovery, semantic quality and latency SLO remain separate acceptance work.\n- Preserve privately identified host system rules across unsaved canonical compaction, including headless, stream, hermetic and sub-agent hosts; copied messages cannot acquire host identity, and retained context still counts against the input budget.\n- Restrict temporary worktree callbacks from launching unowned background shell/subagents, persistent schedules or isolated skill children; retain awaited foreground execution and ordinary persistent-host background behavior. Arbitrary daemon containment is not claimed.\n- Include independent verify: Goal checks, live MCP catalog inheritance/cancellation, skill download cancellation and Terra capability/cache-billing changes accumulated on main. These are unreleased until the new exact-source gates and publication complete.\n- Require context-memory-kernel 0.1.11 publication and public verification before CLI 0.166.131, then pair IDE candidates 0.37.169 / 0.4.186 after the CLI is verified. Use OIDC only; never reuse the occupied .130 tag. Accepted deliveries remain 34/45; NOT_PAID_READY / NOT_ADMITTED / HOLD and the unresolved original dispatch remain."
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"productVersion": null,
|
|
19
|
+
"cliVersion": "0.166.130",
|
|
20
|
+
"cliVersions": ["0.166.130"],
|
|
21
|
+
"date": "2026-10-29",
|
|
22
|
+
"title": "",
|
|
23
|
+
"sections": [
|
|
24
|
+
{
|
|
25
|
+
"heading": "Fixed - cc CLI 0.166.130: Goal budget and workspace evidence (candidate, 2026-10-29)",
|
|
26
|
+
"body": "- Share model Goal review with the author run iteration/cost budgets, cancellation and output limits; retain known usage and stop on unknown usage or transport failure.\n- Bind Goal tool and artifact evidence to current workspace bytes and identities before and after review. External changes invalidate earlier successful observations; bounded reads fail closed when coverage is incomplete.\n- Refresh the reviewed security-map producer digest after adding Goal checkpoint evidence assertions. Preserve every mapped test, original threshold and required operating system.\n- Include the subsequent independent Goal acceptance, Memory cancellation/cache and Terra profile/cache-billing work now on main; validate their final combined source before release.\n- Pair with VS Code 0.37.168 / JetBrains 0.4.185. Before CLI publication, align changed child-package versions and verify their upstream releases. Release requires exact-source CLI CI and Strict Sandbox, OIDC publication and public artifact verification. Cumulative accepted deliverables remain 34/45, with 11 unfinished; NOT_PAID_READY / NOT_ADMITTED / HOLD remain."
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
},
|
|
4
30
|
{
|
|
5
31
|
"productVersion": null,
|
|
6
32
|
"cliVersion": "0.166.129",
|
|
@@ -10,7 +36,7 @@
|
|
|
10
36
|
"sections": [
|
|
11
37
|
{
|
|
12
38
|
"heading": "Fixed - cc CLI 0.166.129: independent change review and Codex support evidence (candidate, 2026-10-28)",
|
|
13
|
-
"body": "- Give opted-in hermetic change review its own request context and tool journal, preserving original requirements, shared request limits, permissions and cancellation. Missing review usage blocks further calls; review is not independent task acceptance.\n- Centralize experimental Codex App Server support, versioned schema probes and CI targets. Keep default-off routing and the existing experimental allowlist; probe-only 0.160.0 and 0.164.0 do not imply production admission.\n- Verify concurrent thread recovery with explicit database recency pagination on Linux, Windows and macOS. Retain documented limitations for default rollout scanning and legacy creation-time pagination.\n- Retain published child dependencies. Candidate publication requires exact-commit CLI CI and Strict Sandbox across all configured systems, GitHub Actions OIDC publication and public artifact readback. Historical task and native acceptance remain separately reported."
|
|
39
|
+
"body": "- Give opted-in hermetic change review its own request context and tool journal, preserving original requirements, shared request limits, permissions and cancellation. Missing review usage blocks further calls; review is not independent task acceptance.\n- Centralize experimental Codex App Server support, versioned schema probes and CI targets. Keep default-off routing and the existing experimental allowlist; probe-only 0.160.0 and 0.164.0 do not imply production admission.\n- Verify concurrent thread recovery with explicit database recency pagination on Linux, Windows and macOS. Retain documented limitations for default rollout scanning and legacy creation-time pagination.\n- Skip automatic and managed workspace snapshots for read-only Git inspection commands in IDE and CLI agent sessions. Retain checkpoints for mutations, explicit output files, external diff drivers and custom Git executors; session persistence and permission checks remain active.\n- Retain published child dependencies. Candidate publication requires exact-commit CLI CI and Strict Sandbox across all configured systems, GitHub Actions OIDC publication and public artifact readback. Historical task and native acceptance remain separately reported."
|
|
14
40
|
}
|
|
15
41
|
]
|
|
16
42
|
},
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
assertSafeGitPath,
|
|
29
29
|
} from "../lib/git-integration.js";
|
|
30
30
|
import { evaluateWorktreeCleanup } from "../lib/worktree-cleanup-safety.js";
|
|
31
|
+
import { withEphemeralWorktreeScope } from "../lib/ephemeral-worktree-scope.js";
|
|
31
32
|
import {
|
|
32
33
|
normalizeSparsePaths,
|
|
33
34
|
planSymlinkDirectories,
|
|
@@ -818,7 +819,9 @@ export async function isolateTask(repoDir, taskId, fn, options = {}) {
|
|
|
818
819
|
const worktreePath = created.path;
|
|
819
820
|
|
|
820
821
|
try {
|
|
821
|
-
const result = await
|
|
822
|
+
const result = await withEphemeralWorktreeScope(worktreePath, () =>
|
|
823
|
+
fn(worktreePath),
|
|
824
|
+
);
|
|
822
825
|
const hasChanges = _hasUncommittedChanges(worktreePath);
|
|
823
826
|
|
|
824
827
|
return {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { getDurableSystemMessageProvenance } from "./session-message-provenance.js";
|
|
2
|
+
|
|
3
|
+
// A live host grants this capability only after validating and rendering its
|
|
4
|
+
// own base. Neither serialized fields nor a cloned message carry authority.
|
|
5
|
+
const LIVE_HOST_BASES = new WeakSet();
|
|
6
|
+
|
|
7
|
+
export function markCompactionHostBase(message) {
|
|
8
|
+
if (
|
|
9
|
+
!message ||
|
|
10
|
+
message.role !== "system" ||
|
|
11
|
+
getDurableSystemMessageProvenance(message)
|
|
12
|
+
)
|
|
13
|
+
throw new TypeError("Compaction host base must be a live system message");
|
|
14
|
+
LIVE_HOST_BASES.add(message);
|
|
15
|
+
return message;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function isCompactionHostBase(message) {
|
|
19
|
+
return (
|
|
20
|
+
LIVE_HOST_BASES.has(message) &&
|
|
21
|
+
message.role === "system" &&
|
|
22
|
+
!getDurableSystemMessageProvenance(message)
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -19,7 +19,11 @@ import {
|
|
|
19
19
|
cloneCanonical,
|
|
20
20
|
normalizeMemoryRecord,
|
|
21
21
|
} from "@chainlesschain/context-memory-kernel";
|
|
22
|
-
import {
|
|
22
|
+
import { withFileLockAsync } from "../with-file-lock.js";
|
|
23
|
+
import {
|
|
24
|
+
checkMemoryQueryAborted,
|
|
25
|
+
memoryLockWait,
|
|
26
|
+
} from "./memory-query-control.js";
|
|
23
27
|
import { getHomeDir } from "../paths.js";
|
|
24
28
|
import { resolve } from "node:path";
|
|
25
29
|
import {
|
|
@@ -261,11 +265,13 @@ export class DurableJsonMemoryPort {
|
|
|
261
265
|
}
|
|
262
266
|
}
|
|
263
267
|
|
|
264
|
-
_locked(operation) {
|
|
268
|
+
_locked(operation, { signal } = {}) {
|
|
269
|
+
checkMemoryQueryAborted(signal);
|
|
265
270
|
mkdirSync(dirname(this.filePath), { recursive: true, mode: 0o700 });
|
|
266
|
-
return
|
|
271
|
+
return withFileLockAsync(
|
|
267
272
|
this.filePath,
|
|
268
273
|
(context) => {
|
|
274
|
+
checkMemoryQueryAborted(signal);
|
|
269
275
|
if (this.lockObserver) {
|
|
270
276
|
try {
|
|
271
277
|
this.lockObserver({
|
|
@@ -285,6 +291,7 @@ export class DurableJsonMemoryPort {
|
|
|
285
291
|
retryMs: 2,
|
|
286
292
|
maxRetryMs: 32,
|
|
287
293
|
retryJitterMs: 8,
|
|
294
|
+
_sleep: memoryLockWait(signal),
|
|
288
295
|
},
|
|
289
296
|
);
|
|
290
297
|
}
|
|
@@ -296,15 +303,17 @@ export class DurableJsonMemoryPort {
|
|
|
296
303
|
});
|
|
297
304
|
}
|
|
298
305
|
|
|
299
|
-
async query() {
|
|
300
|
-
return this._locked(
|
|
301
|
-
Object.values(this._readUnlocked().records).map(cloneCanonical),
|
|
306
|
+
async query(_request, { signal } = {}) {
|
|
307
|
+
return this._locked(
|
|
308
|
+
() => Object.values(this._readUnlocked().records).map(cloneCanonical),
|
|
309
|
+
{ signal },
|
|
302
310
|
);
|
|
303
311
|
}
|
|
304
312
|
|
|
305
313
|
async listRecords(options = {}) {
|
|
306
314
|
const query = normalizeListQuery(options);
|
|
307
|
-
const records = await this.query();
|
|
315
|
+
const records = await this.query(undefined, { signal: options.signal });
|
|
316
|
+
checkMemoryQueryAborted(options.signal);
|
|
308
317
|
return records
|
|
309
318
|
.filter((record) => matchesListQuery(record, query))
|
|
310
319
|
.sort(compareMemoryRows)
|
|
@@ -319,31 +328,34 @@ export class DurableJsonMemoryPort {
|
|
|
319
328
|
async listPage(options = {}) {
|
|
320
329
|
const query = normalizeListQuery(options);
|
|
321
330
|
const count = pageLimit(options.limit);
|
|
322
|
-
return this._locked(
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
.
|
|
332
|
-
(
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
331
|
+
return this._locked(
|
|
332
|
+
() => {
|
|
333
|
+
const state = this._readUnlocked();
|
|
334
|
+
const binding = listCursorBinding(
|
|
335
|
+
resolve(this.filePath),
|
|
336
|
+
state.digest,
|
|
337
|
+
query,
|
|
338
|
+
);
|
|
339
|
+
const after = decodeListCursor(options.cursor, binding);
|
|
340
|
+
const matches = Object.values(state.records)
|
|
341
|
+
.filter(
|
|
342
|
+
(record) =>
|
|
343
|
+
matchesListQuery(record, query) &&
|
|
344
|
+
(!after || compareMemoryRows(record, after) > 0),
|
|
345
|
+
)
|
|
346
|
+
.sort(compareMemoryRows);
|
|
347
|
+
const records = matches.slice(0, count);
|
|
348
|
+
return {
|
|
349
|
+
records,
|
|
350
|
+
storeRevision: state.storeRevision,
|
|
351
|
+
nextCursor:
|
|
352
|
+
matches.length > count
|
|
353
|
+
? encodeListCursor(binding, records.at(-1))
|
|
354
|
+
: null,
|
|
355
|
+
};
|
|
356
|
+
},
|
|
357
|
+
{ signal: options.signal },
|
|
358
|
+
);
|
|
347
359
|
}
|
|
348
360
|
|
|
349
361
|
async commit({ record, event, reconciliation }, expectedRevision = 0) {
|
|
@@ -381,8 +393,8 @@ export class DurableJsonMemoryPort {
|
|
|
381
393
|
});
|
|
382
394
|
}
|
|
383
395
|
|
|
384
|
-
async getRevision() {
|
|
385
|
-
return this._locked(() => this._readUnlocked().storeRevision);
|
|
396
|
+
async getRevision({ signal } = {}) {
|
|
397
|
+
return this._locked(() => this._readUnlocked().storeRevision, { signal });
|
|
386
398
|
}
|
|
387
399
|
|
|
388
400
|
async getReconciliation(requestId) {
|
|
@@ -14,6 +14,7 @@ import { JsonlSessionContextPort } from "./jsonl-session-context-port.js";
|
|
|
14
14
|
import { createCliContextMemoryRuntime } from "./runtime.js";
|
|
15
15
|
import { imageTransportEstimate } from "../image-token-estimate.js";
|
|
16
16
|
import { projectRuntimeTokenUsage } from "../runtime-usage-ledger.js";
|
|
17
|
+
import { isCompactionHostBase } from "../compaction-host-provenance.js";
|
|
17
18
|
import {
|
|
18
19
|
projectCanonicalResumeMessages,
|
|
19
20
|
getDurableSystemMessageProvenance,
|
|
@@ -252,16 +253,24 @@ export async function compactLiveMessagesCanonical(
|
|
|
252
253
|
sessionExists(sessionId);
|
|
253
254
|
// Host policy is live-only. Durable summary/lineage systems retain their
|
|
254
255
|
// private provenance and remain part of the exact authority comparison.
|
|
256
|
+
// Unsaved sessions have no durable host projection: only privately admitted
|
|
257
|
+
// live bases/nudges may bypass the planner, never arbitrary system messages.
|
|
255
258
|
const messages = persistentSession
|
|
256
259
|
? projectCanonicalResumeMessages(liveMessages, { strict: true })
|
|
257
|
-
: liveMessages
|
|
260
|
+
: liveMessages.filter(
|
|
261
|
+
(message) =>
|
|
262
|
+
!isCompactionHostBase(message) &&
|
|
263
|
+
!isRuntimeOnlySessionMessage(message),
|
|
264
|
+
);
|
|
258
265
|
const ephemeralMessages = [];
|
|
259
|
-
|
|
266
|
+
{
|
|
260
267
|
let sequence = 0;
|
|
261
268
|
for (const message of liveMessages) {
|
|
262
269
|
if (
|
|
263
270
|
isRuntimeOnlySessionMessage(message) ||
|
|
264
|
-
(message
|
|
271
|
+
isCompactionHostBase(message) ||
|
|
272
|
+
(persistentSession &&
|
|
273
|
+
message.role === "system" &&
|
|
265
274
|
!getDurableSystemMessageProvenance(message))
|
|
266
275
|
)
|
|
267
276
|
ephemeralMessages.push({ sequence, message });
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import fs, {
|
|
3
|
+
closeSync,
|
|
4
|
+
constants,
|
|
5
|
+
fstatSync,
|
|
6
|
+
fsyncSync,
|
|
7
|
+
lstatSync,
|
|
8
|
+
openSync,
|
|
9
|
+
readSync,
|
|
10
|
+
renameSync,
|
|
11
|
+
unlinkSync,
|
|
12
|
+
writeSync,
|
|
13
|
+
} from "node:fs";
|
|
14
|
+
import { basename, dirname, join } from "node:path";
|
|
15
|
+
import { corruptStore, syncDirectory } from "./durable-memory-port.js";
|
|
16
|
+
import {
|
|
17
|
+
isAffectedWindowsZeroDeviceStatRuntime,
|
|
18
|
+
samePathHandleStableFileIdentity,
|
|
19
|
+
withTrustedFileParentSync,
|
|
20
|
+
} from "../secure-file-identity.js";
|
|
21
|
+
|
|
22
|
+
const CHUNK_BYTES = 64 * 1024;
|
|
23
|
+
const DIGEST = /^sha256:[a-f0-9]{64}$/u;
|
|
24
|
+
const MAGIC = "chainlesschain.memory-query-bundle/v1\n";
|
|
25
|
+
const NAME_DOMAIN = "chainlesschain.memory-query-bundle/name/v1\0";
|
|
26
|
+
const noop = () => {};
|
|
27
|
+
|
|
28
|
+
function corruptBundle(file, reason) {
|
|
29
|
+
return Object.assign(
|
|
30
|
+
new Error(`Context/Memory query bundle is invalid: ${reason}`),
|
|
31
|
+
{
|
|
32
|
+
code: "CONTEXT_MEMORY_QUERY_BUNDLE_CORRUPT",
|
|
33
|
+
filePath: file,
|
|
34
|
+
},
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function sameIdentity(left, right) {
|
|
39
|
+
return left.dev === right.dev && left.ino === right.ino;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function samePathHandle(file, pathStat, handleStat) {
|
|
43
|
+
if (
|
|
44
|
+
!isAffectedWindowsZeroDeviceStatRuntime() ||
|
|
45
|
+
(handleStat.dev !== 0n && sameIdentity(pathStat, handleStat))
|
|
46
|
+
)
|
|
47
|
+
return sameIdentity(pathStat, handleStat);
|
|
48
|
+
// libuv 1.49/1.50 can project a Windows path device differently from its
|
|
49
|
+
// handle. Bind the handle to a separately opened parent/volume device;
|
|
50
|
+
// never accept a zero device as a wildcard or relax the exact inode.
|
|
51
|
+
try {
|
|
52
|
+
return withTrustedFileParentSync(fs, file, ({ parentDevice }) =>
|
|
53
|
+
samePathHandleStableFileIdentity(pathStat, handleStat, parentDevice),
|
|
54
|
+
);
|
|
55
|
+
} catch (cause) {
|
|
56
|
+
throw corruptStore(
|
|
57
|
+
file,
|
|
58
|
+
"query bundle parent identity cannot be verified",
|
|
59
|
+
cause,
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function regular(stat, file) {
|
|
65
|
+
if (!stat.isFile() || stat.isSymbolicLink() || stat.nlink !== 1n)
|
|
66
|
+
throw corruptStore(file, "query bundle must be an unlinked regular file");
|
|
67
|
+
return stat;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function targetStat(file) {
|
|
71
|
+
try {
|
|
72
|
+
return regular(lstatSync(file, { bigint: true }), file);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
if (error.code === "ENOENT") return null;
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function sameFile(file, expected) {
|
|
80
|
+
const current = targetStat(file);
|
|
81
|
+
if (!current || !samePathHandle(file, current, expected))
|
|
82
|
+
throw corruptStore(file, "query bundle file identity changed");
|
|
83
|
+
return current;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function sameDirectory(directory, expected) {
|
|
87
|
+
const current = lstatSync(directory, { bigint: true });
|
|
88
|
+
if (
|
|
89
|
+
!current.isDirectory() ||
|
|
90
|
+
current.isSymbolicLink() ||
|
|
91
|
+
!sameIdentity(current, expected)
|
|
92
|
+
)
|
|
93
|
+
throw corruptStore(directory, "query bundle directory identity changed");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** A derived representation; only the caller's verified manifest supplies lengths and hashes. */
|
|
97
|
+
export function createQueryBundlePlan(
|
|
98
|
+
manifest,
|
|
99
|
+
{ maxFrameBytes = 64 * 1024 * 1024, maxBundleBytes = 0 } = {},
|
|
100
|
+
) {
|
|
101
|
+
if (
|
|
102
|
+
!DIGEST.test(manifest?.digest) ||
|
|
103
|
+
!manifest.shards ||
|
|
104
|
+
!Number.isSafeInteger(maxFrameBytes) ||
|
|
105
|
+
maxFrameBytes < 1 ||
|
|
106
|
+
!Number.isSafeInteger(maxBundleBytes) ||
|
|
107
|
+
maxBundleBytes < 1
|
|
108
|
+
)
|
|
109
|
+
return null;
|
|
110
|
+
const buckets = Object.keys(manifest.shards).sort();
|
|
111
|
+
if (!buckets.length || buckets.length > 256) return null;
|
|
112
|
+
const key = createHash("sha256")
|
|
113
|
+
.update(NAME_DOMAIN)
|
|
114
|
+
.update(manifest.digest)
|
|
115
|
+
.digest("hex");
|
|
116
|
+
const name = `query-00-${key}.json`;
|
|
117
|
+
const frames = [];
|
|
118
|
+
let payloadBytes = 0;
|
|
119
|
+
for (const bucket of buckets) {
|
|
120
|
+
const entry = manifest.shards[bucket];
|
|
121
|
+
if (
|
|
122
|
+
!/^[a-f0-9]{2}$/u.test(bucket) ||
|
|
123
|
+
!DIGEST.test(entry?.queryDigest) ||
|
|
124
|
+
!Number.isSafeInteger(entry.queryBytes) ||
|
|
125
|
+
entry.queryBytes < 1 ||
|
|
126
|
+
entry.queryBytes > maxFrameBytes
|
|
127
|
+
)
|
|
128
|
+
return null;
|
|
129
|
+
if (`query-${bucket}-${entry.queryDigest.slice(7)}.json` === name)
|
|
130
|
+
return null;
|
|
131
|
+
payloadBytes += entry.queryBytes;
|
|
132
|
+
if (!Number.isSafeInteger(payloadBytes) || payloadBytes > maxBundleBytes)
|
|
133
|
+
return null;
|
|
134
|
+
frames.push(
|
|
135
|
+
Object.freeze({
|
|
136
|
+
bucket,
|
|
137
|
+
byteLength: entry.queryBytes,
|
|
138
|
+
digest: entry.queryDigest,
|
|
139
|
+
}),
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
const header = Buffer.from(
|
|
143
|
+
`${MAGIC}${JSON.stringify({ manifestDigest: manifest.digest, frames })}\n`,
|
|
144
|
+
);
|
|
145
|
+
const byteLength = header.length + payloadBytes;
|
|
146
|
+
if (!Number.isSafeInteger(byteLength) || byteLength > maxBundleBytes)
|
|
147
|
+
return null;
|
|
148
|
+
return Object.freeze({
|
|
149
|
+
name,
|
|
150
|
+
manifestDigest: manifest.digest,
|
|
151
|
+
frames: Object.freeze(frames),
|
|
152
|
+
header,
|
|
153
|
+
byteLength,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* onFrame receives verified bytes; withhold results until the entire read succeeds.
|
|
159
|
+
* reuseFrameBuffer borrows storage only until onFrame settles. Opted-in callers
|
|
160
|
+
* must finish decoding before returning and must not retain the bytes or views.
|
|
161
|
+
* The default gives each callback its own independently retainable Buffer.
|
|
162
|
+
*/
|
|
163
|
+
export async function readQueryBundle(
|
|
164
|
+
file,
|
|
165
|
+
plan,
|
|
166
|
+
{ checkpoint = noop, onFrame = noop, reuseFrameBuffer = false } = {},
|
|
167
|
+
) {
|
|
168
|
+
await checkpoint();
|
|
169
|
+
const before = regular(lstatSync(file, { bigint: true }), file);
|
|
170
|
+
let fd, opened;
|
|
171
|
+
try {
|
|
172
|
+
try {
|
|
173
|
+
fd = openSync(
|
|
174
|
+
file,
|
|
175
|
+
constants.O_RDONLY |
|
|
176
|
+
(constants.O_NOFOLLOW || 0) |
|
|
177
|
+
(constants.O_NONBLOCK || 0),
|
|
178
|
+
);
|
|
179
|
+
} catch (error) {
|
|
180
|
+
if (["ELOOP", "ENOENT", "ENOTDIR"].includes(error.code))
|
|
181
|
+
throw corruptStore(
|
|
182
|
+
file,
|
|
183
|
+
"query bundle path changed while opening",
|
|
184
|
+
error,
|
|
185
|
+
);
|
|
186
|
+
throw error;
|
|
187
|
+
}
|
|
188
|
+
opened = regular(fstatSync(fd, { bigint: true }), file);
|
|
189
|
+
if (!samePathHandle(file, before, opened))
|
|
190
|
+
throw corruptStore(file, "query bundle changed while opening");
|
|
191
|
+
if (opened.size !== BigInt(plan.byteLength))
|
|
192
|
+
throw corruptBundle(file, "byte length does not match manifest plan");
|
|
193
|
+
async function readBytes(bytes, hash) {
|
|
194
|
+
let offset = 0;
|
|
195
|
+
while (offset < bytes.length) {
|
|
196
|
+
const count = readSync(
|
|
197
|
+
fd,
|
|
198
|
+
bytes,
|
|
199
|
+
offset,
|
|
200
|
+
Math.min(CHUNK_BYTES, bytes.length - offset),
|
|
201
|
+
null,
|
|
202
|
+
);
|
|
203
|
+
if (!count) throw corruptBundle(file, "unexpected end of file");
|
|
204
|
+
hash?.update(bytes.subarray(offset, offset + count));
|
|
205
|
+
offset += count;
|
|
206
|
+
await checkpoint();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
const header = Buffer.allocUnsafe(plan.header.length);
|
|
210
|
+
await readBytes(header);
|
|
211
|
+
if (!header.equals(plan.header))
|
|
212
|
+
throw corruptBundle(file, "header does not match current manifest");
|
|
213
|
+
const reusable = reuseFrameBuffer
|
|
214
|
+
? Buffer.allocUnsafe(
|
|
215
|
+
Math.max(...plan.frames.map((frame) => frame.byteLength)),
|
|
216
|
+
)
|
|
217
|
+
: null;
|
|
218
|
+
for (const frame of plan.frames) {
|
|
219
|
+
const bytes = reusable
|
|
220
|
+
? reusable.subarray(0, frame.byteLength)
|
|
221
|
+
: Buffer.allocUnsafe(frame.byteLength);
|
|
222
|
+
const hash = createHash("sha256");
|
|
223
|
+
await readBytes(bytes, hash);
|
|
224
|
+
if (`sha256:${hash.digest("hex")}` !== frame.digest)
|
|
225
|
+
throw corruptBundle(
|
|
226
|
+
file,
|
|
227
|
+
`frame digest does not match bucket ${frame.bucket}`,
|
|
228
|
+
);
|
|
229
|
+
await onFrame(frame.bucket, bytes);
|
|
230
|
+
}
|
|
231
|
+
if (readSync(fd, Buffer.allocUnsafe(1), 0, 1, null) !== 0)
|
|
232
|
+
throw corruptBundle(file, "trailing data");
|
|
233
|
+
await checkpoint();
|
|
234
|
+
const after = regular(fstatSync(fd, { bigint: true }), file);
|
|
235
|
+
if (!sameIdentity(opened, after))
|
|
236
|
+
throw corruptStore(file, "query bundle descriptor identity changed");
|
|
237
|
+
sameFile(file, opened);
|
|
238
|
+
if (
|
|
239
|
+
after.size !== opened.size ||
|
|
240
|
+
after.mtimeNs !== opened.mtimeNs ||
|
|
241
|
+
after.ctimeNs !== opened.ctimeNs
|
|
242
|
+
)
|
|
243
|
+
throw corruptBundle(file, "file changed while reading");
|
|
244
|
+
} catch (error) {
|
|
245
|
+
if (fd !== undefined) {
|
|
246
|
+
// Content errors are repairable only while the pathname still names the
|
|
247
|
+
// inode we opened. Otherwise a failed read could authorize replacing an
|
|
248
|
+
// unrelated file that appeared during a cooperative checkpoint.
|
|
249
|
+
const current = regular(fstatSync(fd, { bigint: true }), file);
|
|
250
|
+
if (opened && !sameIdentity(current, opened))
|
|
251
|
+
throw corruptStore(file, "query bundle descriptor identity changed");
|
|
252
|
+
sameFile(file, current);
|
|
253
|
+
}
|
|
254
|
+
throw error;
|
|
255
|
+
} finally {
|
|
256
|
+
if (fd !== undefined) closeSync(fd);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** Caller holds the authority lock throughout construction, publication, and cleanup. */
|
|
261
|
+
export async function writeQueryBundle(
|
|
262
|
+
file,
|
|
263
|
+
plan,
|
|
264
|
+
{ checkpoint = noop, getFrame, checkDirectories } = {},
|
|
265
|
+
) {
|
|
266
|
+
if (typeof getFrame !== "function" || typeof checkDirectories !== "function")
|
|
267
|
+
throw new TypeError(
|
|
268
|
+
"query bundle write requires getFrame and checkDirectories",
|
|
269
|
+
);
|
|
270
|
+
if (basename(file) !== plan.name)
|
|
271
|
+
throw corruptStore(file, "query bundle target does not match its plan");
|
|
272
|
+
await checkpoint();
|
|
273
|
+
await checkDirectories();
|
|
274
|
+
const directory = dirname(file);
|
|
275
|
+
const parent = lstatSync(directory, { bigint: true });
|
|
276
|
+
sameDirectory(directory, parent);
|
|
277
|
+
const originalTarget = targetStat(file);
|
|
278
|
+
const temporary = join(directory, `query-rebuild-${randomUUID()}.tmp`);
|
|
279
|
+
let fd, created;
|
|
280
|
+
let published = false;
|
|
281
|
+
try {
|
|
282
|
+
fd = openSync(
|
|
283
|
+
temporary,
|
|
284
|
+
constants.O_WRONLY |
|
|
285
|
+
constants.O_CREAT |
|
|
286
|
+
constants.O_EXCL |
|
|
287
|
+
(constants.O_NOFOLLOW || 0),
|
|
288
|
+
0o600,
|
|
289
|
+
);
|
|
290
|
+
created = regular(fstatSync(fd, { bigint: true }), temporary);
|
|
291
|
+
async function writeBytes(bytes, hash) {
|
|
292
|
+
let offset = 0;
|
|
293
|
+
while (offset < bytes.length) {
|
|
294
|
+
const count = writeSync(
|
|
295
|
+
fd,
|
|
296
|
+
bytes,
|
|
297
|
+
offset,
|
|
298
|
+
Math.min(CHUNK_BYTES, bytes.length - offset),
|
|
299
|
+
);
|
|
300
|
+
if (!count)
|
|
301
|
+
throw Object.assign(
|
|
302
|
+
new Error("query bundle write made no progress"),
|
|
303
|
+
{ code: "EIO" },
|
|
304
|
+
);
|
|
305
|
+
hash?.update(bytes.subarray(offset, offset + count));
|
|
306
|
+
offset += count;
|
|
307
|
+
await checkpoint();
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
await writeBytes(plan.header);
|
|
311
|
+
for (const frame of plan.frames) {
|
|
312
|
+
const bytes = await getFrame(frame.bucket);
|
|
313
|
+
if (!Buffer.isBuffer(bytes) || bytes.length !== frame.byteLength)
|
|
314
|
+
throw corruptBundle(
|
|
315
|
+
file,
|
|
316
|
+
`source frame does not match bucket ${frame.bucket}`,
|
|
317
|
+
);
|
|
318
|
+
const sourceHash = createHash("sha256");
|
|
319
|
+
for (let offset = 0; offset < bytes.length; offset += CHUNK_BYTES) {
|
|
320
|
+
sourceHash.update(bytes.subarray(offset, offset + CHUNK_BYTES));
|
|
321
|
+
await checkpoint();
|
|
322
|
+
}
|
|
323
|
+
if (`sha256:${sourceHash.digest("hex")}` !== frame.digest)
|
|
324
|
+
throw corruptBundle(
|
|
325
|
+
file,
|
|
326
|
+
`source frame does not match bucket ${frame.bucket}`,
|
|
327
|
+
);
|
|
328
|
+
const writtenHash = createHash("sha256");
|
|
329
|
+
await writeBytes(bytes, writtenHash);
|
|
330
|
+
if (`sha256:${writtenHash.digest("hex")}` !== frame.digest)
|
|
331
|
+
throw corruptBundle(
|
|
332
|
+
file,
|
|
333
|
+
`source frame changed while writing bucket ${frame.bucket}`,
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
const written = regular(fstatSync(fd, { bigint: true }), temporary);
|
|
337
|
+
if (!sameIdentity(created, written))
|
|
338
|
+
throw corruptStore(temporary, "query bundle temporary identity changed");
|
|
339
|
+
if (written.size !== BigInt(plan.byteLength))
|
|
340
|
+
throw corruptBundle(file, "written byte length does not match plan");
|
|
341
|
+
fsyncSync(fd);
|
|
342
|
+
await checkpoint();
|
|
343
|
+
closeSync(fd);
|
|
344
|
+
fd = undefined;
|
|
345
|
+
await checkDirectories();
|
|
346
|
+
sameDirectory(directory, parent);
|
|
347
|
+
sameFile(temporary, created);
|
|
348
|
+
const currentTarget = targetStat(file);
|
|
349
|
+
if (
|
|
350
|
+
Boolean(originalTarget) !== Boolean(currentTarget) ||
|
|
351
|
+
(originalTarget && !sameIdentity(originalTarget, currentTarget))
|
|
352
|
+
)
|
|
353
|
+
throw corruptStore(
|
|
354
|
+
file,
|
|
355
|
+
"query bundle target identity changed before publication",
|
|
356
|
+
);
|
|
357
|
+
renameSync(temporary, file);
|
|
358
|
+
published = true;
|
|
359
|
+
syncDirectory(directory);
|
|
360
|
+
} finally {
|
|
361
|
+
if (fd !== undefined) closeSync(fd);
|
|
362
|
+
if (!published && created) {
|
|
363
|
+
// An unsafe directory or a replaced temp path is not ours to delete.
|
|
364
|
+
// Preserve the original failure rather than hiding it with cleanup errors.
|
|
365
|
+
try {
|
|
366
|
+
await checkDirectories();
|
|
367
|
+
sameDirectory(directory, parent);
|
|
368
|
+
sameFile(temporary, created);
|
|
369
|
+
unlinkSync(temporary);
|
|
370
|
+
} catch {
|
|
371
|
+
/* Leave an untrusted/redirected temporary path untouched. */
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { performance } from "node:perf_hooks";
|
|
2
|
+
import { setImmediate, setTimeout } from "node:timers/promises";
|
|
3
|
+
|
|
4
|
+
// These are host control signals, not serialized MemoryRecallRequest fields.
|
|
5
|
+
export function checkMemoryQueryAborted(signal) {
|
|
6
|
+
signal?.throwIfAborted();
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function memoryLockWait(signal) {
|
|
10
|
+
return async (milliseconds) => {
|
|
11
|
+
checkMemoryQueryAborted(signal);
|
|
12
|
+
await setTimeout(milliseconds, undefined, { signal });
|
|
13
|
+
checkMemoryQueryAborted(signal);
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Yield between bounded shards while retaining the authority lock/snapshot. */
|
|
18
|
+
export function createMemoryQueryCheckpoint(signal) {
|
|
19
|
+
let yieldedAt = performance.now();
|
|
20
|
+
return async (force = false) => {
|
|
21
|
+
checkMemoryQueryAborted(signal);
|
|
22
|
+
if (force || performance.now() - yieldedAt >= 8) {
|
|
23
|
+
await setImmediate(undefined, { signal });
|
|
24
|
+
yieldedAt = performance.now();
|
|
25
|
+
}
|
|
26
|
+
checkMemoryQueryAborted(signal);
|
|
27
|
+
};
|
|
28
|
+
}
|