chainlesschain 0.163.7 → 0.164.0
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/package.json +5 -1
- package/scripts/macos-mcp-launcher-build.mjs +317 -0
- package/scripts/macos-mcp-launcher-postinstall.sh +54 -0
- package/scripts/macos-mcp-launcher-preinstall.sh +61 -0
- package/src/assets/web-panel/assets/{AIOps-axqQfwv8.js → AIOps-D2MEn7fI.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-DV-Ro0By.js → ActionButton-lCW_4Gf0.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-Bt72WEVu.js → Analytics-Bs7i-nsS.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-BtepG55E.js → AppLayout-CK7B6S_j.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-B7KaJ7S_.js → Artifacts-C8ILjpyo.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-FNFaUg7A.js → Audit-Bb9cNaWc.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-DFb6J2wQ.js → BackgroundAgents-sC9ooXIf.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-CC7YBhyj.js → Backup-D-DrsplT.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-RkgTNVtj.js → BaseInput-uCNZpwSK.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-hHEmGZy-.js → Chat-CsDK1uE9.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-CAP9YhHv.js → ChatBubbleRenderer-OqSDt50w.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-z5wXOQP1.js → Checkbox-JhTXM1-K.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-DVaDJnxy.js → Codegen-BbzZLnyD.js} +1 -1
- package/src/assets/web-panel/assets/{Col-CJmaRDR5.js → Col-D4VW4m4j.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DF29_2bI.js → Community-BXrYawxV.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DtkQkBzn.js → Compact-DCihGy1u.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-xoHDxp7I.js → Compliance-DlyZ-lk8.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-BUm-R7ht.js → Cowork-DvGZrhbO.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-Cgl14ZkB.js → Cron-DUncZi8h.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BNcbmoqh.js → Crosschain-C_hLuUcm.js} +1 -1
- package/src/assets/web-panel/assets/{DID-Bwja0Zo9.js → DID-b6YSUqxr.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-Bk5XjEdJ.js → Dashboard-uvM15Cfb.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-Ci36Oitq.js → Dropdown-D1-Nd4qY.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer--U04ZN4q.js → EmailListRenderer-8ApvL6Zc.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-B2gNPR2s.js → FamilyGuardDashboard-LYJt8811.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-C4KghYn7.js → Federation-BbI3HGpv.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-QL7x_Q_0.js → FormItemContext-DSoEKuFu.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-F3Ryltwm.js → GenericCardRenderer-B0S9OWd5.js} +1 -1
- package/src/assets/web-panel/assets/{Git-2HassK5k.js → Git-DIs9Zhf3.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DoBIp7oe.js → Governance-jzZXrxcl.js} +1 -1
- package/src/assets/web-panel/assets/{Inference--W01QhZ-.js → Inference-JUPjf2ZI.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DmvwqGpT.js → KnowledgeGraph-DxnfJvlP.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BBJ4yAel.js → Logs-iXiz8BEE.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-BLCZMzhJ.js → MarkdownRenderer-GmB6DOr6.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-D5lNngSI.js → Marketplace-Y3Xch312.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CkEVOMKH.js → McpTools-D7kGGbO7.js} +4 -4
- package/src/assets/web-panel/assets/{Memory-B1Ow1xVE.js → Memory-Do_hVxzh.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-SgYbUfb6.js → MobileBridge-CtrR0Tas.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-BL0Czcoj.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-DcTXSSma.js → Mtc-qo5QCTGd.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-Dt3WG4oj.js → MtcAudit-cq5mnjYj.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-B9B38UZx.js → Multisig-Bq0MAQHw.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-B0S4GGvG.js → NLProgramming-DdWE6Vi2.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-DZ5U58Ng.js → Notes-BxMBFcIp.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-PjL5ZW34.js → NotificationSettings-RTrAcbUe.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DrAX2ESt.js → OrderTableRenderer-DJbpGqzT.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-Cv1GYs-c.js → Organization-SQzIPdqC.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Bbkp_PL3.js → Overflow-02yECh22.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-BD8QUgoZ.js → P2P-BNg4pNCM.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-BO-2PeaB.js → PdhVaultBrowser-BxPJZsD3.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-D_OPVa02.js → Permissions-CLnDnPAz.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-mh-pEmaB.js → PersonalDataHub-C5m0AjGf.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-6JC2EDdb.js → Pipeline-VwOf5Dhv.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-CUshzUAG.js → Privacy-CC0W2hZd.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-Cs2Aalri.js → ProjectInit-Dz893Bob.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-1ak49tcj.js → ProjectSettings-CxQkvl0k.js} +2 -2
- package/src/assets/web-panel/assets/Projects-DDAjkUkT.js +1 -0
- package/src/assets/web-panel/assets/{Providers-CXXxvafH.js → Providers-DeB9IkxK.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-PTcDsF58.js → QrScannerModal-OCeoaswn.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-CDwucrJw.js → QuickAsk-DenotaAj.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-CJlLVRXR.js → Recommend-Cies_jjI.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-DlN-ETsO.js → RemoteSession-Dxzl5n2T.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-DI23LR6m.js → Reputation-CW0mvxgZ.js} +1 -1
- package/src/assets/web-panel/assets/{Row-Cl7UQMrM.js → Row-SEd32qZU.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CexHNfh8.js → RssFeed-BSwnJ3Lm.js} +3 -3
- package/src/assets/web-panel/assets/{Search-BneBWvRN.js → Search-xe2m8bkC.js} +1 -1
- package/src/assets/web-panel/assets/{Security-DX7Phgrp.js → Security-Mq2F9Nro.js} +4 -4
- package/src/assets/web-panel/assets/{Services-BWXO8Mte.js → Services-BKGw2V3P.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DCyOjKPJ.js → Skeleton-DW95-Rxf.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CXqERsTB.js → Skills-CHgChCv_.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-bhbrbz8E.js → Sla-tKh6k3R7.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-3IPU0HBZ.js → SpeechSettings-D6UL3dA5.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DBNTQLbM.js → SyncSettings-D0Fw8fVL.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-quP0bkN-.js → Tasks-20x1GB3D.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BouWmgho.js → Templates-DJ-lts-a.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-qv0D9s7z.js → Tenant-BFdGpbs7.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-BxvbE8BB.js → Terminal-Xpx61vHL.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-D-IeLnJ2.js → TimelineRenderer-C6UIvyZQ.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-CFMKKyVG.js → Tokens-Dellq08f.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-L8as3UuJ.js → Trigger-VKw8d0J-.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-MxmA4VZG.js → Trust-DNftdKT5.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-C0VvJYRi.js → UkeySign-DX9VAKJI.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-Bf5QZj8N.js → VideoEditing-B2h3jO8q.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BIJ9riRz.js → Wallet-CjGkof7f.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-B8p9Mhkw.js → WebAuthn-2Zfcu55P.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-BVsuaPen.js → WorkflowEditor-B9eZ8UxZ.js} +1 -1
- package/src/assets/web-panel/assets/{chat-BfkjoKpV.js → chat-CQNfD-YO.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DeAlsWK8.js → colors-D4usyFT2.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-Cs97bz5j.js → compact-item-s4TpjvjX.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BqbG60LH.js → createContext-BRCSvYxj.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DKJjSWRn.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-i_RY0b1X.js → hasIn-AdkUbkV-.js} +1 -1
- package/src/assets/web-panel/assets/{index-BOVkf1K3.js → index--00U6vXZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-B-3tEpTc.js → index-B2V-eKfK.js} +1 -1
- package/src/assets/web-panel/assets/{index-D2B4VPyP.js → index-B4JJCfQ2.js} +1 -1
- package/src/assets/web-panel/assets/{index-BkBi5TmC.js → index-BIoG5yYf.js} +1 -1
- package/src/assets/web-panel/assets/{index-79V_zv1s.js → index-BMcimU-2.js} +1 -1
- package/src/assets/web-panel/assets/{index-U4f5izHz.js → index-BPhkFZ1I.js} +1 -1
- package/src/assets/web-panel/assets/{index-DiSkx4UB.js → index-BQ3DXBtD.js} +3 -3
- package/src/assets/web-panel/assets/{index-dIHr4B_u.js → index-Bad4VNvz.js} +1 -1
- package/src/assets/web-panel/assets/{index-CIG8fQ2_.js → index-BgiXR_-_.js} +1 -1
- package/src/assets/web-panel/assets/{index-DqBgBpgp.js → index-BtobShro.js} +1 -1
- package/src/assets/web-panel/assets/{index-ZxO_-E8a.js → index-Bw2MEnUk.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUUrv141.js → index-C1mJtE6q.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bm7lLR4c.js → index-C484EJiS.js} +1 -1
- package/src/assets/web-panel/assets/{index-COdGA-8n.js → index-C5KAQFPQ.js} +1 -1
- package/src/assets/web-panel/assets/index-C61cnl3K.js +1 -0
- package/src/assets/web-panel/assets/{index-CED2PL_y.js → index-C7Y8Aluc.js} +1 -1
- package/src/assets/web-panel/assets/{index-YXgLng0K.js → index-CCsM_Ybx.js} +1 -1
- package/src/assets/web-panel/assets/{index-0-agYlWL.js → index-CJCFe2Qf.js} +1 -1
- package/src/assets/web-panel/assets/{index-B5UkyA3c.js → index-CJVEOa4i.js} +1 -1
- package/src/assets/web-panel/assets/{index-B1CbOH1i.js → index-CJdQrZth.js} +1 -1
- package/src/assets/web-panel/assets/{index-s1opAL-M.js → index-CKC1t3Ic.js} +1 -1
- package/src/assets/web-panel/assets/{index-yObj1O4n.js → index-CQhAVU5t.js} +1 -1
- package/src/assets/web-panel/assets/{index-CgsqdnRV.js → index-CYdoQsa1.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dk7-v4hP.js → index-Cduu2Hhr.js} +1 -1
- package/src/assets/web-panel/assets/{index-B-JVTrpr.js → index-CkwiSLhU.js} +1 -1
- package/src/assets/web-panel/assets/{index-CeWoNHau.js → index-Cvyt-zhm.js} +1 -1
- package/src/assets/web-panel/assets/{index-CE2VtTlp.js → index-D2GjI2oe.js} +1 -1
- package/src/assets/web-panel/assets/index-D4XFHxBr.js +1 -0
- package/src/assets/web-panel/assets/{index-DmbfhJUP.js → index-DARsAyUp.js} +1 -1
- package/src/assets/web-panel/assets/{index-BESLFt4q.js → index-DVKfQ0Ux.js} +1 -1
- package/src/assets/web-panel/assets/{index-PT_5sBMA.js → index-DZT36ZYq.js} +1 -1
- package/src/assets/web-panel/assets/{index-gyFpvL7l.js → index-D_XBHopw.js} +1 -1
- package/src/assets/web-panel/assets/{index-BYUVuwKt.js → index-DdCB70SS.js} +1 -1
- package/src/assets/web-panel/assets/{index-BcUXAB2s.js → index-DzRjHxEv.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dk2qouAz.js → index-MMN9V6JF.js} +1 -1
- package/src/assets/web-panel/assets/{index-D9evtvg2.js → index-RfMr79MW.js} +1 -1
- package/src/assets/web-panel/assets/{index-BuLQobzW.js → index-_IRVsV9X.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cf3WCLmy.js → index-nXyk8GZ9.js} +1 -1
- package/src/assets/web-panel/assets/{index-CG3PRyAL.js → index-s_buFMEG.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-C9h9yKL3.js → initDefaultProps-Blmpk7HL.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BvmLsPdu.js → motion-DPBJMv1n.js} +1 -1
- package/src/assets/web-panel/assets/{move-CoL4ekU1.js → move-ButdzCM7.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-C4pMy6xV.js → mtc-parser-cyRC_QCe.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DPuJfNxx.js → omit-1epSV7hz.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-D0KEeaK2.js → pickAttrs-DuPY8xJs.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BpkyINxt.js → placementArrow-6XZqarhe.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-DQI_wOq8.js → responsiveObserve-B40pXBWM.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DYfdDiRg.js → slide-jbZ9Wu4n.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-B5dtvb0D.js → statusUtils-BKQQcVy4.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-CF310mSj.js → styleChecker-NiKfWjUT.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-D1Qp4BLp.js → useFlexGapSupport-bQUCvPeb.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-C7_iyvJK.js → useFs-CUGji7ph.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-DZUt_fIm.js → usePersonalDataHub-4veyN2N2.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-D3dsi0lZ.js → vnode-1-nLug-Z.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-WdbOlvdQ.js → zoom-dhCeRDMo.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +6 -6
- package/src/commands/automation.js +103 -1
- package/src/commands/cowork.js +174 -19
- package/src/commands/permissions.js +240 -16
- package/src/commands/plugin.js +1293 -56
- package/src/commands/session-location.js +276 -0
- package/src/commands/session.js +2 -0
- package/src/commands/team-merge-review.js +937 -0
- package/src/commands/team.js +2 -0
- package/src/data/changelog.json +27 -1
- package/src/gateways/ws/action-protocol.js +35 -10
- package/src/gateways/ws/remote-session-protocol.js +24 -1
- package/src/gateways/ws/ws-agent-handler.js +12 -0
- package/src/gateways/ws/ws-server.js +48 -12
- package/src/harness/jsonl-session-store.js +341 -24
- package/src/harness/mcp-client.js +8 -1
- package/src/harness/remote-session-audit.js +1 -0
- package/src/harness/remote-session-crypto.js +210 -2
- package/src/harness/remote-session-registry.js +159 -6
- package/src/harness/session-list-index.js +233 -14
- package/src/lib/agent-authority.js +6 -0
- package/src/lib/agent-schedule-store.js +139 -28
- package/src/lib/agent-team/team-merge-review-store.js +765 -0
- package/src/lib/agent-team/team-merge-review-transaction.js +1223 -0
- package/src/lib/agent-team/team-merge-review.js +1847 -0
- package/src/lib/automation-center-incidents.js +314 -0
- package/src/lib/automation-center-runtime.js +448 -0
- package/src/lib/automation-center.js +182 -38
- package/src/lib/automation-engine.js +41 -0
- package/src/lib/automation-execution-authority.js +241 -12
- package/src/lib/automation-execution-incident.js +737 -0
- package/src/lib/background-agent-keeper-client.js +248 -0
- package/src/lib/background-agent-keeper-protocol.js +147 -0
- package/src/lib/background-agent-supervisor.js +520 -40
- package/src/lib/background-interaction-resolver.js +12 -0
- package/src/lib/background-turn-bootstrap-protocol.js +126 -0
- package/src/lib/cowork-cron.js +85 -14
- package/src/lib/cowork-workflow.js +336 -16
- package/src/lib/dynamic-workflow-facade.js +648 -0
- package/src/lib/execution-location-contract.js +551 -0
- package/src/lib/execution-location-runtime.js +130 -0
- package/src/lib/ide-context.js +94 -6
- package/src/lib/mcp-stdio-package-materialization.js +166 -14
- package/src/lib/packer/pkg-config-generator.js +2 -0
- package/src/lib/permission-authority.js +77 -0
- package/src/lib/permission-side-effect-center.js +495 -0
- package/src/lib/plugin-runtime/install.js +514 -13
- package/src/lib/plugin-runtime/marketplace-artifact-readback.js +900 -0
- package/src/lib/plugin-runtime/marketplace-catalog.js +1181 -0
- package/src/lib/plugin-runtime/marketplace-impact.js +408 -0
- package/src/lib/plugin-runtime/marketplace-remote-artifacts.js +1567 -0
- package/src/lib/plugin-security.js +60 -3
- package/src/lib/process-execution-broker/index.js +1095 -57
- package/src/lib/process-execution-broker/linux-bwrap-descriptor-launch.js +375 -0
- package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +90 -16
- package/src/lib/process-execution-broker/linux-generic-bwrap.js +159 -18
- package/src/lib/process-execution-broker/macos-mcp-launcher-contract.js +278 -0
- package/src/lib/process-execution-broker/macos-mcp-launcher-protocol.json +23 -0
- package/src/lib/process-execution-broker/macos-mcp-launcher.c +1497 -0
- package/src/lib/process-execution-broker/mcp-fd-entry-bootstrap.js +37 -0
- package/src/lib/process-execution-broker/platform-sandbox.js +2330 -279
- package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
- package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
- package/src/lib/process-execution-broker/windows-sandbox.cs +50 -4
- package/src/lib/public-ide-capability-manifest.js +3 -0
- package/src/lib/remote-approval-bridge.js +123 -17
- package/src/lib/remote-membership-authority.js +632 -0
- package/src/lib/remote-membership-coordinator.js +2409 -0
- package/src/lib/remote-membership-host-store.js +1750 -0
- package/src/lib/scheduler-kernel/agenda-adapter.js +17 -7
- package/src/lib/scheduler-kernel/automation-adapter.js +105 -11
- package/src/lib/scheduler-kernel/automation-event-adapter.js +87 -11
- package/src/lib/scheduler-kernel/contract.js +91 -0
- package/src/lib/scheduler-kernel/cowork-cron-adapter.js +12 -1
- package/src/lib/scheduler-kernel/loop-adapter.js +7 -1
- package/src/lib/scheduler-kernel/routine-adapter.js +7 -1
- package/src/lib/scheduler-kernel/runtime-control-capabilities.js +31 -0
- package/src/lib/scheduler-kernel/runtime.js +176 -3
- package/src/lib/scheduler-kernel/store.js +1253 -45
- package/src/lib/scoped-permission-store.js +369 -0
- package/src/lib/session-anti-rollback-anchor.js +262 -5
- package/src/lib/sub-agent-context.js +4 -0
- package/src/lib/workflow-definition-contract.js +149 -0
- package/src/repl/agent-repl.js +41 -7
- package/src/repl/chat-repl.js +2 -0
- package/src/repl/clipboard-image.js +735 -16
- package/src/repl/ide-status.js +1 -1
- package/src/repl/prompt-interactions.js +59 -6
- package/src/runtime/agent-core.js +93 -3
- package/src/runtime/headless-runner.js +30 -25
- package/src/runtime/headless-stream.js +32 -25
- package/src/runtime/mcp-config.js +81 -10
- package/src/workers/background-agent-keeper.js +498 -0
- package/src/workers/background-agent-worker.js +358 -13
- package/src/workers/background-turn-bootstrap.js +143 -0
- package/src/assets/web-panel/assets/MobileProjects-BWdOvQAj.js +0 -1
- package/src/assets/web-panel/assets/Projects-BV4oApsm.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DPty0mGN.js +0 -1
- package/src/assets/web-panel/assets/index-Bt7g0Vq_.js +0 -1
- package/src/assets/web-panel/assets/index-ChVT0p9u.js +0 -1
|
@@ -70,6 +70,7 @@ import {
|
|
|
70
70
|
import { createSessionPersistenceFailure } from "../lib/session-persistence-failure.js";
|
|
71
71
|
import { withSessionHostWriteAuthority } from "../lib/session-host-lease.js";
|
|
72
72
|
import { createSessionTranscriptStructureProjection } from "../lib/session-transcript-structure.js";
|
|
73
|
+
import { normalizeExecutionLocationBinding } from "../lib/execution-location-contract.js";
|
|
73
74
|
import {
|
|
74
75
|
listSessionAntiRollbackIds,
|
|
75
76
|
publishSessionAntiRollbackAnchor,
|
|
@@ -90,11 +91,22 @@ export const _sessionScaleFaultHooks = Object.seal({
|
|
|
90
91
|
beforeTranscriptDirectoryFsync: null,
|
|
91
92
|
afterTranscriptDirectoryFsync: null,
|
|
92
93
|
afterTranscriptAppend: null,
|
|
94
|
+
beforeTailRepairFsync: null,
|
|
95
|
+
afterTailRepairFsync: null,
|
|
93
96
|
beforeVerifiedProjectionRepair: null,
|
|
94
97
|
afterForkCopy: null,
|
|
98
|
+
beforeForkCopyFsync: null,
|
|
99
|
+
afterForkCopyFsync: null,
|
|
95
100
|
afterForkLineage: null,
|
|
101
|
+
beforeForkLineageFsync: null,
|
|
102
|
+
afterForkLineageFsync: null,
|
|
96
103
|
afterForkPublish: null,
|
|
104
|
+
beforeForkDirectoryFsync: null,
|
|
105
|
+
afterForkDirectoryFsync: null,
|
|
97
106
|
afterForkMeta: null,
|
|
107
|
+
beforeDeleteDirectoryFsync: null,
|
|
108
|
+
afterDeleteDirectoryFsync: null,
|
|
109
|
+
afterAntiRollbackPublish: null,
|
|
98
110
|
});
|
|
99
111
|
|
|
100
112
|
export const WS_TURN_EVENT = "ws_turn";
|
|
@@ -575,6 +587,48 @@ function runSessionScaleFaultHook(name, payload) {
|
|
|
575
587
|
if (typeof hook === "function") hook(payload);
|
|
576
588
|
}
|
|
577
589
|
|
|
590
|
+
function fsyncRegularFilePath(filePath, payload, beforeHook, afterHook) {
|
|
591
|
+
runSessionScaleFaultHook(beforeHook, payload);
|
|
592
|
+
let descriptor = null;
|
|
593
|
+
try {
|
|
594
|
+
const flags = fsConstants.O_RDWR | Number(fsConstants.O_NOFOLLOW ?? 0);
|
|
595
|
+
descriptor = openSync(filePath, flags);
|
|
596
|
+
const stats = fstatSync(descriptor);
|
|
597
|
+
if (!stats.isFile()) {
|
|
598
|
+
throw new Error(`Session durability target is not a file: ${filePath}`);
|
|
599
|
+
}
|
|
600
|
+
fsyncSync(descriptor);
|
|
601
|
+
runSessionScaleFaultHook(afterHook, payload);
|
|
602
|
+
} finally {
|
|
603
|
+
if (descriptor !== null) closeSync(descriptor);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
function fsyncParentDirectory(filePath, payload, beforeHook, afterHook) {
|
|
608
|
+
// Node does not expose a usable directory FlushFileBuffers handle on
|
|
609
|
+
// Windows. The file itself is still flushed before publication there.
|
|
610
|
+
if (process.platform === "win32") return;
|
|
611
|
+
runSessionScaleFaultHook(beforeHook, payload);
|
|
612
|
+
let descriptor = null;
|
|
613
|
+
try {
|
|
614
|
+
const flags =
|
|
615
|
+
fsConstants.O_RDONLY |
|
|
616
|
+
Number(fsConstants.O_DIRECTORY ?? 0) |
|
|
617
|
+
Number(fsConstants.O_NOFOLLOW ?? 0);
|
|
618
|
+
descriptor = openSync(dirname(filePath), flags);
|
|
619
|
+
const stats = fstatSync(descriptor);
|
|
620
|
+
if (!stats.isDirectory()) {
|
|
621
|
+
throw new Error(
|
|
622
|
+
`Session durability parent is not a directory: ${dirname(filePath)}`,
|
|
623
|
+
);
|
|
624
|
+
}
|
|
625
|
+
fsyncSync(descriptor);
|
|
626
|
+
runSessionScaleFaultHook(afterHook, payload);
|
|
627
|
+
} finally {
|
|
628
|
+
if (descriptor !== null) closeSync(descriptor);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
578
632
|
function getSessionsDir() {
|
|
579
633
|
const dir = join(getHomeDir(), "sessions");
|
|
580
634
|
let current = null;
|
|
@@ -740,7 +794,6 @@ function inspectPhysicalTail(filePath, { dryRun = false } = {}) {
|
|
|
740
794
|
};
|
|
741
795
|
if (!existsSync(filePath)) return result;
|
|
742
796
|
const fd = openSync(filePath, "r+");
|
|
743
|
-
let normalizeNewline = false;
|
|
744
797
|
try {
|
|
745
798
|
const size = fstatSync(fd).size;
|
|
746
799
|
result.fileSize = size;
|
|
@@ -778,7 +831,15 @@ function inspectPhysicalTail(filePath, { dryRun = false } = {}) {
|
|
|
778
831
|
// it and normalize before appending the next chained event.
|
|
779
832
|
result.action = "normalize-newline";
|
|
780
833
|
result.changed = true;
|
|
781
|
-
|
|
834
|
+
if (!dryRun) {
|
|
835
|
+
const newline = Buffer.from("\n", "utf8");
|
|
836
|
+
const written = writeSync(fd, newline, 0, newline.length, size);
|
|
837
|
+
if (written !== newline.length) {
|
|
838
|
+
throw new Error(
|
|
839
|
+
"Session transcript tail repair made no forward progress",
|
|
840
|
+
);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
782
843
|
} catch (error) {
|
|
783
844
|
rethrowCanonicalJsonlRecordLimit(error);
|
|
784
845
|
// Crash tail: discard only the one incomplete physical record.
|
|
@@ -790,12 +851,20 @@ function inspectPhysicalTail(filePath, { dryRun = false } = {}) {
|
|
|
790
851
|
}
|
|
791
852
|
}
|
|
792
853
|
}
|
|
854
|
+
if (!dryRun && result.changed) {
|
|
855
|
+
const payload = Object.freeze({
|
|
856
|
+
filePath,
|
|
857
|
+
action: result.action,
|
|
858
|
+
discardedBytes: result.discardedBytes,
|
|
859
|
+
discardedRecords: result.discardedRecords,
|
|
860
|
+
});
|
|
861
|
+
runSessionScaleFaultHook("beforeTailRepairFsync", payload);
|
|
862
|
+
fsyncSync(fd);
|
|
863
|
+
runSessionScaleFaultHook("afterTailRepairFsync", payload);
|
|
864
|
+
}
|
|
793
865
|
} finally {
|
|
794
866
|
closeSync(fd);
|
|
795
867
|
}
|
|
796
|
-
if (normalizeNewline) {
|
|
797
|
-
appendFileSync(filePath, "\n", { encoding: "utf8", mode: 0o600 });
|
|
798
|
-
}
|
|
799
868
|
if (!dryRun && result.changed) ensurePrivateFile(filePath);
|
|
800
869
|
return result;
|
|
801
870
|
}
|
|
@@ -904,6 +973,17 @@ function appendVerifiedWsAuthorityEventLocked(
|
|
|
904
973
|
},
|
|
905
974
|
);
|
|
906
975
|
publishSessionAntiRollbackWitness(sessionId, nextMeta, filePath, "live");
|
|
976
|
+
runSessionScaleFaultHook(
|
|
977
|
+
"afterAntiRollbackPublish",
|
|
978
|
+
Object.freeze({
|
|
979
|
+
sessionId,
|
|
980
|
+
type,
|
|
981
|
+
event,
|
|
982
|
+
hash,
|
|
983
|
+
meta: nextMeta,
|
|
984
|
+
filePath,
|
|
985
|
+
}),
|
|
986
|
+
);
|
|
907
987
|
} catch (cause) {
|
|
908
988
|
const error = new Error(
|
|
909
989
|
`Session authority anchor could not be persisted: ${sessionId}`,
|
|
@@ -1536,6 +1616,17 @@ function appendEventLocked(
|
|
|
1536
1616
|
filePath,
|
|
1537
1617
|
"live",
|
|
1538
1618
|
);
|
|
1619
|
+
runSessionScaleFaultHook(
|
|
1620
|
+
"afterAntiRollbackPublish",
|
|
1621
|
+
Object.freeze({
|
|
1622
|
+
sessionId,
|
|
1623
|
+
type,
|
|
1624
|
+
event,
|
|
1625
|
+
hash,
|
|
1626
|
+
meta: nextMeta,
|
|
1627
|
+
filePath,
|
|
1628
|
+
}),
|
|
1629
|
+
);
|
|
1539
1630
|
} catch (cause) {
|
|
1540
1631
|
const error = new Error(
|
|
1541
1632
|
`Session authority anchor could not be persisted: ${sessionId}`,
|
|
@@ -2205,13 +2296,21 @@ export function verifyAllSessions(options = {}) {
|
|
|
2205
2296
|
.map((sessionId) => verifySession(sessionId));
|
|
2206
2297
|
}
|
|
2207
2298
|
|
|
2208
|
-
function indexedProjectionMatchesTranscript(
|
|
2299
|
+
function indexedProjectionMatchesTranscript(
|
|
2300
|
+
meta,
|
|
2301
|
+
verification,
|
|
2302
|
+
validation,
|
|
2303
|
+
transcriptState,
|
|
2304
|
+
) {
|
|
2209
2305
|
return (
|
|
2210
2306
|
verification.status === TRANSCRIPT_CHAIN_STATUS.VERIFIED &&
|
|
2211
2307
|
validation.valid === true &&
|
|
2212
2308
|
meta?.deleted !== true &&
|
|
2213
2309
|
Number(meta?.event_count) === validation.eventCount &&
|
|
2214
|
-
(meta?.last_hash ?? null) === (verification.lastHash ?? null)
|
|
2310
|
+
(meta?.last_hash ?? null) === (verification.lastHash ?? null) &&
|
|
2311
|
+
meta?.transcript != null &&
|
|
2312
|
+
transcriptState != null &&
|
|
2313
|
+
samePhysicalTranscriptState(meta.transcript, transcriptState)
|
|
2215
2314
|
);
|
|
2216
2315
|
}
|
|
2217
2316
|
|
|
@@ -2263,6 +2362,10 @@ export function repairSession(sessionId, options = {}) {
|
|
|
2263
2362
|
indexRepairRequired: false,
|
|
2264
2363
|
indexRebuilt: false,
|
|
2265
2364
|
indexRepairError: null,
|
|
2365
|
+
authorityAnchorRequired: false,
|
|
2366
|
+
authorityAnchored: false,
|
|
2367
|
+
authorityAnchorChanged: false,
|
|
2368
|
+
authorityAnchorError: null,
|
|
2266
2369
|
discardedBytes: 0,
|
|
2267
2370
|
discardedRecords: 0,
|
|
2268
2371
|
healthy: false,
|
|
@@ -2288,6 +2391,9 @@ export function repairSession(sessionId, options = {}) {
|
|
|
2288
2391
|
? before.truncatedTail || repair.changed
|
|
2289
2392
|
: after.truncatedTail) &&
|
|
2290
2393
|
effectiveValidation.valid;
|
|
2394
|
+
const effectiveTranscriptState = transcriptHealthy
|
|
2395
|
+
? readPhysicalTranscriptState(filePath)
|
|
2396
|
+
: null;
|
|
2291
2397
|
const currentMeta = readSessionMeta(dir, sessionId);
|
|
2292
2398
|
const currentActivity = readLatestSessionActivity(dir, sessionId);
|
|
2293
2399
|
const indexRepairRequired =
|
|
@@ -2296,11 +2402,13 @@ export function repairSession(sessionId, options = {}) {
|
|
|
2296
2402
|
currentMeta,
|
|
2297
2403
|
effective,
|
|
2298
2404
|
effectiveValidation,
|
|
2405
|
+
effectiveTranscriptState,
|
|
2299
2406
|
) ||
|
|
2300
2407
|
!indexedProjectionMatchesTranscript(
|
|
2301
2408
|
currentActivity,
|
|
2302
2409
|
effective,
|
|
2303
2410
|
effectiveValidation,
|
|
2411
|
+
effectiveTranscriptState,
|
|
2304
2412
|
));
|
|
2305
2413
|
let indexRebuilt = false;
|
|
2306
2414
|
let indexRepairError = null;
|
|
@@ -2315,25 +2423,64 @@ export function repairSession(sessionId, options = {}) {
|
|
|
2315
2423
|
};
|
|
2316
2424
|
}
|
|
2317
2425
|
}
|
|
2426
|
+
const authorityAnchorRequired =
|
|
2427
|
+
transcriptHealthy &&
|
|
2428
|
+
effective.status === TRANSCRIPT_CHAIN_STATUS.VERIFIED;
|
|
2429
|
+
let authorityAnchored = !authorityAnchorRequired;
|
|
2430
|
+
let authorityAnchorChanged = false;
|
|
2431
|
+
let authorityAnchorError = null;
|
|
2432
|
+
if (
|
|
2433
|
+
!dryRun &&
|
|
2434
|
+
authorityAnchorRequired &&
|
|
2435
|
+
(!indexRepairRequired || indexRebuilt)
|
|
2436
|
+
) {
|
|
2437
|
+
try {
|
|
2438
|
+
const anchorBefore = readSessionAntiRollbackAnchor(sessionId);
|
|
2439
|
+
assertVerifiedTranscriptAnchor(
|
|
2440
|
+
sessionId,
|
|
2441
|
+
effective,
|
|
2442
|
+
effectiveTranscriptState,
|
|
2443
|
+
);
|
|
2444
|
+
const anchorAfter = readSessionAntiRollbackAnchor(sessionId);
|
|
2445
|
+
authorityAnchored = true;
|
|
2446
|
+
authorityAnchorChanged =
|
|
2447
|
+
JSON.stringify(anchorBefore) !== JSON.stringify(anchorAfter);
|
|
2448
|
+
} catch (cause) {
|
|
2449
|
+
authorityAnchorError = {
|
|
2450
|
+
code: cause?.code || null,
|
|
2451
|
+
message: String(cause?.message || cause),
|
|
2452
|
+
};
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2318
2455
|
const healthy = dryRun
|
|
2319
2456
|
? transcriptHealthy && !repair.changed && !indexRepairRequired
|
|
2320
|
-
: transcriptHealthy &&
|
|
2457
|
+
: transcriptHealthy &&
|
|
2458
|
+
(!indexRepairRequired || indexRebuilt) &&
|
|
2459
|
+
authorityAnchored;
|
|
2321
2460
|
return {
|
|
2322
2461
|
sessionId,
|
|
2323
2462
|
dryRun,
|
|
2324
|
-
changed: repair.changed || indexRebuilt,
|
|
2463
|
+
changed: repair.changed || indexRebuilt || authorityAnchorChanged,
|
|
2325
2464
|
physicalChanged: repair.changed,
|
|
2326
2465
|
indexChanged: indexRebuilt,
|
|
2327
2466
|
wouldChange: dryRun && (repair.changed || indexRepairRequired),
|
|
2328
2467
|
action:
|
|
2329
|
-
repair.action
|
|
2330
|
-
?
|
|
2331
|
-
:
|
|
2468
|
+
repair.action !== "none"
|
|
2469
|
+
? repair.action
|
|
2470
|
+
: indexRepairRequired
|
|
2471
|
+
? "rebuild-index"
|
|
2472
|
+
: authorityAnchorChanged
|
|
2473
|
+
? "repair-anchor"
|
|
2474
|
+
: "none",
|
|
2332
2475
|
physicalAction: repair.action,
|
|
2333
2476
|
indexAction: indexRepairRequired ? "rebuild-index" : "none",
|
|
2334
2477
|
indexRepairRequired,
|
|
2335
2478
|
indexRebuilt,
|
|
2336
2479
|
indexRepairError,
|
|
2480
|
+
authorityAnchorRequired,
|
|
2481
|
+
authorityAnchored,
|
|
2482
|
+
authorityAnchorChanged,
|
|
2483
|
+
authorityAnchorError,
|
|
2337
2484
|
discardedBytes: repair.discardedBytes,
|
|
2338
2485
|
discardedRecords: repair.discardedRecords,
|
|
2339
2486
|
healthy,
|
|
@@ -2351,9 +2498,11 @@ export function repairSession(sessionId, options = {}) {
|
|
|
2351
2498
|
"transcript remains structurally invalid"
|
|
2352
2499
|
: indexRepairError
|
|
2353
2500
|
? `session metadata index rebuild failed: ${indexRepairError.message}`
|
|
2354
|
-
:
|
|
2355
|
-
?
|
|
2356
|
-
:
|
|
2501
|
+
: authorityAnchorError
|
|
2502
|
+
? `session external authority anchor repair failed: ${authorityAnchorError.message}`
|
|
2503
|
+
: indexRepairRequired && dryRun
|
|
2504
|
+
? "session metadata index requires rebuild"
|
|
2505
|
+
: null,
|
|
2357
2506
|
};
|
|
2358
2507
|
},
|
|
2359
2508
|
{ failIfUnavailable: true },
|
|
@@ -2464,11 +2613,59 @@ export function startSession(sessionId, meta = {}) {
|
|
|
2464
2613
|
usageTelemetryVersion: 1,
|
|
2465
2614
|
}
|
|
2466
2615
|
: {}),
|
|
2616
|
+
...(meta.executionLocation != null
|
|
2617
|
+
? {
|
|
2618
|
+
executionLocation: normalizeExecutionLocationBinding(
|
|
2619
|
+
meta.executionLocation,
|
|
2620
|
+
),
|
|
2621
|
+
}
|
|
2622
|
+
: {}),
|
|
2467
2623
|
});
|
|
2468
2624
|
|
|
2469
2625
|
return id;
|
|
2470
2626
|
}
|
|
2471
2627
|
|
|
2628
|
+
/** Return the immutable execution-location facts anchored by session_start. */
|
|
2629
|
+
export function getVerifiedSessionExecutionLocationAuthority(sessionId) {
|
|
2630
|
+
return readVerifiedProjection(sessionId, () => {
|
|
2631
|
+
let sessionStartSeen = false;
|
|
2632
|
+
let hasExecutionLocation = false;
|
|
2633
|
+
let executionLocation = null;
|
|
2634
|
+
return {
|
|
2635
|
+
accept(event) {
|
|
2636
|
+
if (event?.type === "session_start" && !sessionStartSeen) {
|
|
2637
|
+
sessionStartSeen = true;
|
|
2638
|
+
if (Object.hasOwn(event.data || {}, "executionLocation")) {
|
|
2639
|
+
hasExecutionLocation = true;
|
|
2640
|
+
executionLocation = event.data.executionLocation;
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
},
|
|
2644
|
+
finish(authority) {
|
|
2645
|
+
if (!authority.headHash || authority.eventCount <= 0) {
|
|
2646
|
+
throw unverifiedTranscriptError(sessionId, {
|
|
2647
|
+
status: "empty",
|
|
2648
|
+
reason: "session has no anchored transcript events",
|
|
2649
|
+
});
|
|
2650
|
+
}
|
|
2651
|
+
if (!hasExecutionLocation) {
|
|
2652
|
+
const error = new Error(
|
|
2653
|
+
`session ${sessionId} has no execution-location binding`,
|
|
2654
|
+
);
|
|
2655
|
+
error.code = "SESSION_EXECUTION_LOCATION_MISSING";
|
|
2656
|
+
throw error;
|
|
2657
|
+
}
|
|
2658
|
+
return Object.freeze({
|
|
2659
|
+
sessionId,
|
|
2660
|
+
headHash: authority.headHash,
|
|
2661
|
+
eventCount: authority.eventCount,
|
|
2662
|
+
binding: normalizeExecutionLocationBinding(executionLocation),
|
|
2663
|
+
});
|
|
2664
|
+
},
|
|
2665
|
+
};
|
|
2666
|
+
});
|
|
2667
|
+
}
|
|
2668
|
+
|
|
2472
2669
|
/** Return the anchored transcript revision used by delivery causality bindings. */
|
|
2473
2670
|
export function getVerifiedSessionObservabilityAuthority(sessionId) {
|
|
2474
2671
|
return readVerifiedProjection(sessionId, () => {
|
|
@@ -3666,7 +3863,13 @@ export function renameSession(sessionId, title) {
|
|
|
3666
3863
|
export function deleteJsonlSession(sessionId) {
|
|
3667
3864
|
if (isUnsafeSessionId(sessionId)) return false;
|
|
3668
3865
|
const filePath = sessionPath(sessionId);
|
|
3669
|
-
if (
|
|
3866
|
+
if (
|
|
3867
|
+
!existsSync(filePath) &&
|
|
3868
|
+
readSessionPersistenceWitness(sessionId)?.deleted !== true &&
|
|
3869
|
+
!hasLiveSessionWitness(sessionId)
|
|
3870
|
+
) {
|
|
3871
|
+
return false;
|
|
3872
|
+
}
|
|
3670
3873
|
return withSessionHostWriterLock(
|
|
3671
3874
|
sessionId,
|
|
3672
3875
|
filePath,
|
|
@@ -3675,10 +3878,32 @@ export function deleteJsonlSession(sessionId) {
|
|
|
3675
3878
|
let existingMeta = readSessionPersistenceWitness(sessionId);
|
|
3676
3879
|
const marker = readSessionTombstoneMarker(getSessionsDir(), sessionId);
|
|
3677
3880
|
const externalAnchor = readSessionAntiRollbackAnchor(sessionId);
|
|
3678
|
-
if (
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3881
|
+
if (!transcriptExists && existingMeta?.deleted === true) {
|
|
3882
|
+
// recordSessionDeleted publishes meta before the independent witness.
|
|
3883
|
+
// Re-emit the exact tombstone to settle its file/directory barriers,
|
|
3884
|
+
// then advance the external anchor before an interrupted delete retry
|
|
3885
|
+
// reports success.
|
|
3886
|
+
const timestamp =
|
|
3887
|
+
Math.max(
|
|
3888
|
+
0,
|
|
3889
|
+
Number(existingMeta.deleted_at_ms) ||
|
|
3890
|
+
Number(existingMeta.updated_at_ms) ||
|
|
3891
|
+
Date.now(),
|
|
3892
|
+
) || Date.now();
|
|
3893
|
+
const tombstone = recordSessionDeleted(
|
|
3894
|
+
getSessionsDir(),
|
|
3895
|
+
sessionId,
|
|
3896
|
+
timestamp,
|
|
3897
|
+
);
|
|
3898
|
+
publishSessionAntiRollbackWitness(
|
|
3899
|
+
sessionId,
|
|
3900
|
+
tombstone,
|
|
3901
|
+
filePath,
|
|
3902
|
+
"deleted",
|
|
3903
|
+
);
|
|
3904
|
+
return externalAnchor?.status !== "deleted";
|
|
3905
|
+
}
|
|
3906
|
+
if (!transcriptExists && existingMeta === null) {
|
|
3682
3907
|
return false;
|
|
3683
3908
|
}
|
|
3684
3909
|
const deletionWitness =
|
|
@@ -3728,6 +3953,15 @@ export function deleteJsonlSession(sessionId) {
|
|
|
3728
3953
|
});
|
|
3729
3954
|
}
|
|
3730
3955
|
if (transcriptExists) rmSync(filePath, { force: true });
|
|
3956
|
+
// The external tombstone is published only after the absent transcript
|
|
3957
|
+
// directory entry is durable. A retry after an interrupted unlink must
|
|
3958
|
+
// repeat this barrier even though the path is already absent in memory.
|
|
3959
|
+
fsyncParentDirectory(
|
|
3960
|
+
filePath,
|
|
3961
|
+
Object.freeze({ sessionId, filePath, operation: "delete" }),
|
|
3962
|
+
"beforeDeleteDirectoryFsync",
|
|
3963
|
+
"afterDeleteDirectoryFsync",
|
|
3964
|
+
);
|
|
3731
3965
|
try {
|
|
3732
3966
|
const tombstone = recordSessionDeleted(getSessionsDir(), sessionId);
|
|
3733
3967
|
publishSessionAntiRollbackWitness(
|
|
@@ -3737,15 +3971,23 @@ export function deleteJsonlSession(sessionId) {
|
|
|
3737
3971
|
"deleted",
|
|
3738
3972
|
);
|
|
3739
3973
|
} catch (error) {
|
|
3740
|
-
//
|
|
3741
|
-
//
|
|
3742
|
-
//
|
|
3974
|
+
// A complete anti-rollback record is readable before its fsync. If
|
|
3975
|
+
// rollback also fails, readback alone cannot prove durability. Only
|
|
3976
|
+
// swallow a post-meta failure after an exact replay has settled the
|
|
3977
|
+
// deleted record through the production persistence path.
|
|
3978
|
+
const tombstone = readSessionMeta(getSessionsDir(), sessionId);
|
|
3743
3979
|
if (
|
|
3744
|
-
|
|
3980
|
+
tombstone?.deleted !== true ||
|
|
3745
3981
|
readSessionAntiRollbackAnchor(sessionId)?.status !== "deleted"
|
|
3746
3982
|
) {
|
|
3747
3983
|
throw error;
|
|
3748
3984
|
}
|
|
3985
|
+
publishSessionAntiRollbackWitness(
|
|
3986
|
+
sessionId,
|
|
3987
|
+
tombstone,
|
|
3988
|
+
filePath,
|
|
3989
|
+
"deleted",
|
|
3990
|
+
);
|
|
3749
3991
|
}
|
|
3750
3992
|
return true;
|
|
3751
3993
|
},
|
|
@@ -3943,6 +4185,17 @@ export function forkSession(sourceId, options = {}) {
|
|
|
3943
4185
|
sessionId: newId,
|
|
3944
4186
|
filePath: workingPath,
|
|
3945
4187
|
});
|
|
4188
|
+
fsyncRegularFilePath(
|
|
4189
|
+
workingPath,
|
|
4190
|
+
Object.freeze({
|
|
4191
|
+
sourceId,
|
|
4192
|
+
sessionId: newId,
|
|
4193
|
+
filePath: workingPath,
|
|
4194
|
+
phase: "copy",
|
|
4195
|
+
}),
|
|
4196
|
+
"beforeForkCopyFsync",
|
|
4197
|
+
"afterForkCopyFsync",
|
|
4198
|
+
);
|
|
3946
4199
|
} else {
|
|
3947
4200
|
const prefix = compareFilePrefix(workingPath, sourcePath);
|
|
3948
4201
|
if (prefix.matches && prefix.candidateSize < prefix.fullSize) {
|
|
@@ -3963,6 +4216,17 @@ export function forkSession(sourceId, options = {}) {
|
|
|
3963
4216
|
sessionId: newId,
|
|
3964
4217
|
filePath: workingPath,
|
|
3965
4218
|
});
|
|
4219
|
+
fsyncRegularFilePath(
|
|
4220
|
+
workingPath,
|
|
4221
|
+
Object.freeze({
|
|
4222
|
+
sourceId,
|
|
4223
|
+
sessionId: newId,
|
|
4224
|
+
filePath: workingPath,
|
|
4225
|
+
phase: "copy",
|
|
4226
|
+
}),
|
|
4227
|
+
"beforeForkCopyFsync",
|
|
4228
|
+
"afterForkCopyFsync",
|
|
4229
|
+
);
|
|
3966
4230
|
}
|
|
3967
4231
|
}
|
|
3968
4232
|
|
|
@@ -4027,6 +4291,7 @@ export function forkSession(sourceId, options = {}) {
|
|
|
4027
4291
|
target.verification.chainedEvents ===
|
|
4028
4292
|
sourceVerification.chainedEvents;
|
|
4029
4293
|
|
|
4294
|
+
let lineageFsynced = false;
|
|
4030
4295
|
if (exactSourceCopy) {
|
|
4031
4296
|
if (targetMeta !== null) {
|
|
4032
4297
|
throw unverifiedTranscriptError(newId, target.verification);
|
|
@@ -4079,6 +4344,19 @@ export function forkSession(sourceId, options = {}) {
|
|
|
4079
4344
|
filePath: workingPath,
|
|
4080
4345
|
event: lineageEvent,
|
|
4081
4346
|
});
|
|
4347
|
+
fsyncRegularFilePath(
|
|
4348
|
+
workingPath,
|
|
4349
|
+
Object.freeze({
|
|
4350
|
+
sourceId,
|
|
4351
|
+
sessionId: newId,
|
|
4352
|
+
filePath: workingPath,
|
|
4353
|
+
phase: "lineage",
|
|
4354
|
+
event: lineageEvent,
|
|
4355
|
+
}),
|
|
4356
|
+
"beforeForkLineageFsync",
|
|
4357
|
+
"afterForkLineageFsync",
|
|
4358
|
+
);
|
|
4359
|
+
lineageFsynced = true;
|
|
4082
4360
|
target = inspectTarget();
|
|
4083
4361
|
targetMeta = readSessionMeta(sessionsDir, newId);
|
|
4084
4362
|
}
|
|
@@ -4133,12 +4411,35 @@ export function forkSession(sourceId, options = {}) {
|
|
|
4133
4411
|
throw unverifiedTranscriptError(newId, target.verification);
|
|
4134
4412
|
}
|
|
4135
4413
|
|
|
4414
|
+
// A retry may inherit a complete lineage record from a process that
|
|
4415
|
+
// exited at the pre-fsync hook. Flush that exact verified candidate
|
|
4416
|
+
// before it can cross the rename/publication boundary.
|
|
4417
|
+
if (!lineageFsynced && targetMeta === null) {
|
|
4418
|
+
fsyncRegularFilePath(
|
|
4419
|
+
workingPath,
|
|
4420
|
+
Object.freeze({
|
|
4421
|
+
sourceId,
|
|
4422
|
+
sessionId: newId,
|
|
4423
|
+
filePath: workingPath,
|
|
4424
|
+
phase: "lineage-recovery",
|
|
4425
|
+
event: target.lineageEvent,
|
|
4426
|
+
}),
|
|
4427
|
+
"beforeForkLineageFsync",
|
|
4428
|
+
"afterForkLineageFsync",
|
|
4429
|
+
);
|
|
4430
|
+
lineageFsynced = true;
|
|
4431
|
+
}
|
|
4432
|
+
|
|
4136
4433
|
const anchorMatchesTarget =
|
|
4137
4434
|
targetMeta?.deleted !== true &&
|
|
4138
4435
|
targetMeta?.last_hash === target.verification.lastHash &&
|
|
4139
4436
|
Number(targetMeta?.event_count) ===
|
|
4140
4437
|
target.verification.chainedEvents;
|
|
4141
4438
|
if (anchorMatchesTarget) {
|
|
4439
|
+
// Meta publication precedes the independent machine-local witness.
|
|
4440
|
+
// A process can die in that exact window, so an idempotent fork
|
|
4441
|
+
// retry must settle the external anchor before reporting success.
|
|
4442
|
+
assertVerifiedTranscriptAnchor(newId, target.verification);
|
|
4142
4443
|
const activity = readLatestSessionActivity(sessionsDir, newId);
|
|
4143
4444
|
if (
|
|
4144
4445
|
activity?.deleted === true ||
|
|
@@ -4199,6 +4500,22 @@ export function forkSession(sourceId, options = {}) {
|
|
|
4199
4500
|
});
|
|
4200
4501
|
}
|
|
4201
4502
|
|
|
4503
|
+
// The sidecar and anti-rollback witness below may only advance after
|
|
4504
|
+
// the final transcript directory entry is durable on POSIX. This is
|
|
4505
|
+
// also required on a retry that inherited the final path from a crash
|
|
4506
|
+
// immediately after rename.
|
|
4507
|
+
fsyncParentDirectory(
|
|
4508
|
+
filePath,
|
|
4509
|
+
Object.freeze({
|
|
4510
|
+
sourceId,
|
|
4511
|
+
sessionId: newId,
|
|
4512
|
+
filePath,
|
|
4513
|
+
operation: "fork-publish",
|
|
4514
|
+
}),
|
|
4515
|
+
"beforeForkDirectoryFsync",
|
|
4516
|
+
"afterForkDirectoryFsync",
|
|
4517
|
+
);
|
|
4518
|
+
|
|
4202
4519
|
rebuildSessionMetaUnlocked(sessionsDir, newId, filePath);
|
|
4203
4520
|
runSessionScaleFaultHook("afterForkMeta", {
|
|
4204
4521
|
sourceId,
|
|
@@ -2541,10 +2541,17 @@ export class MCPClient extends EventEmitter {
|
|
|
2541
2541
|
MCP_STDIO_CAPSULE_REQUIRED_BOUNDARIES.every((boundary) =>
|
|
2542
2542
|
effectiveRuntimeSandboxBoundaries.has(boundary),
|
|
2543
2543
|
);
|
|
2544
|
+
const capsuleUsesMacProcessTreeSandbox =
|
|
2545
|
+
Boolean(stdioCapsuleSandboxExecutionContract) &&
|
|
2546
|
+
process.platform === "darwin" &&
|
|
2547
|
+
MCP_STDIO_CAPSULE_REQUIRED_BOUNDARIES.every((boundary) =>
|
|
2548
|
+
effectiveRuntimeSandboxBoundaries.has(boundary),
|
|
2549
|
+
);
|
|
2544
2550
|
const capsuleUsesPosixProcessGroup =
|
|
2545
2551
|
Boolean(stdioCapsuleSandboxExecutionContract) &&
|
|
2546
2552
|
process.platform !== "win32" &&
|
|
2547
|
-
!capsuleUsesLinuxProcessTreeSandbox
|
|
2553
|
+
!capsuleUsesLinuxProcessTreeSandbox &&
|
|
2554
|
+
!capsuleUsesMacProcessTreeSandbox;
|
|
2548
2555
|
const launchOptions = {
|
|
2549
2556
|
...spawnOptions,
|
|
2550
2557
|
detached:
|