chainlesschain 0.163.8 → 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 +4 -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-CavM7W3k.js → AIOps-D2MEn7fI.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CUvZGabQ.js → ActionButton-lCW_4Gf0.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DeBnWnbe.js → Analytics-Bs7i-nsS.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DbI5kxvd.js → AppLayout-CK7B6S_j.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-D93bigKm.js → Artifacts-C8ILjpyo.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CBNvfUZa.js → Audit-Bb9cNaWc.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-CJLyh_YU.js → BackgroundAgents-sC9ooXIf.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-D_0yoehD.js → Backup-D-DrsplT.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-TJxmbObW.js → BaseInput-uCNZpwSK.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CE0dto1q.js → Chat-CsDK1uE9.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-CZ5-yYiD.js → ChatBubbleRenderer-OqSDt50w.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-Ck1RVIVo.js → Checkbox-JhTXM1-K.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-qpoyf6DK.js → Codegen-BbzZLnyD.js} +1 -1
- package/src/assets/web-panel/assets/{Col-DUyPWjIE.js → Col-D4VW4m4j.js} +1 -1
- package/src/assets/web-panel/assets/{Community-D_S1BemS.js → Community-BXrYawxV.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BjxeK-Gc.js → Compact-DCihGy1u.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-Dd3CEJsu.js → Compliance-DlyZ-lk8.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-B4QG7-ad.js → Cowork-DvGZrhbO.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-BtZnids5.js → Cron-DUncZi8h.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CHPfCBFD.js → Crosschain-C_hLuUcm.js} +1 -1
- package/src/assets/web-panel/assets/{DID-DT8DCEOK.js → DID-b6YSUqxr.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-COQab5_U.js → Dashboard-uvM15Cfb.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-BY1PsQuU.js → Dropdown-D1-Nd4qY.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-CsuAuaq3.js → EmailListRenderer-8ApvL6Zc.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-BqpinD-j.js → FamilyGuardDashboard-LYJt8811.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-D0gkfQFv.js → Federation-BbI3HGpv.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-BqgE-axK.js → FormItemContext-DSoEKuFu.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-D0hJ2KvC.js → GenericCardRenderer-B0S9OWd5.js} +1 -1
- package/src/assets/web-panel/assets/{Git-CmMB0uPY.js → Git-DIs9Zhf3.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BnVEI0Dk.js → Governance-jzZXrxcl.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-YTAMihRP.js → Inference-JUPjf2ZI.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-0ax7VHop.js → KnowledgeGraph-DxnfJvlP.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-B9TRcokL.js → Logs-iXiz8BEE.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-GmB6DOr6.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-B6CSuD_H.js → Marketplace-Y3Xch312.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-CjMXvOVU.js → McpTools-D7kGGbO7.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-CXRF71U3.js → Memory-Do_hVxzh.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-DQgNp_oS.js → MobileBridge-CtrR0Tas.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-BL0Czcoj.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-6hDTRPe1.js → Mtc-qo5QCTGd.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-BlVHU1DS.js → MtcAudit-cq5mnjYj.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-DP9pzEbV.js → Multisig-Bq0MAQHw.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-Djorh8EV.js → NLProgramming-DdWE6Vi2.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-oLZ-JkUg.js → Notes-BxMBFcIp.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-Cg288VH3.js → NotificationSettings-RTrAcbUe.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-Bb1O3Ofr.js → OrderTableRenderer-DJbpGqzT.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-CBdo-bHs.js → Organization-SQzIPdqC.js} +2 -2
- package/src/assets/web-panel/assets/{Overflow-qZdnVumx.js → Overflow-02yECh22.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-D4kNfGNQ.js → P2P-BNg4pNCM.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-DnlMemM7.js → PdhVaultBrowser-BxPJZsD3.js} +5 -5
- package/src/assets/web-panel/assets/{Permissions-DHucHFBJ.js → Permissions-CLnDnPAz.js} +3 -3
- package/src/assets/web-panel/assets/{PersonalDataHub-BovlOIPR.js → PersonalDataHub-C5m0AjGf.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-Deru3CQY.js → Pipeline-VwOf5Dhv.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-Bq5oTTbU.js → Privacy-CC0W2hZd.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-BfzxVWAz.js → ProjectInit-Dz893Bob.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CKC6XBtH.js → ProjectSettings-CxQkvl0k.js} +2 -2
- package/src/assets/web-panel/assets/Projects-DDAjkUkT.js +1 -0
- package/src/assets/web-panel/assets/{Providers-C_jx4TWX.js → Providers-DeB9IkxK.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-BdIHeVGC.js → QrScannerModal-OCeoaswn.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-BwZwAcPD.js → QuickAsk-DenotaAj.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-BNTt0L-m.js → Recommend-Cies_jjI.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-Biyn2-Ro.js → RemoteSession-Dxzl5n2T.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-D6VpG32B.js → Reputation-CW0mvxgZ.js} +1 -1
- package/src/assets/web-panel/assets/{Row-D_74OvQQ.js → Row-SEd32qZU.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-BTr0a-BQ.js → RssFeed-BSwnJ3Lm.js} +3 -3
- package/src/assets/web-panel/assets/{Search-C3MCFoNU.js → Search-xe2m8bkC.js} +1 -1
- package/src/assets/web-panel/assets/{Security-CqW9aJ6s.js → Security-Mq2F9Nro.js} +3 -3
- package/src/assets/web-panel/assets/{Services-Cw5GNaHF.js → Services-BKGw2V3P.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DZps5qeY.js → Skeleton-DW95-Rxf.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-C6NQ1znT.js → Skills-CHgChCv_.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DFP8G2Sh.js → Sla-tKh6k3R7.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-ESt6MB6v.js → SpeechSettings-D6UL3dA5.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-BHnN98aM.js → SyncSettings-D0Fw8fVL.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-NiSCaOf-.js → Tasks-20x1GB3D.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-DsKFhW2C.js → Templates-DJ-lts-a.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CQ0E0ze5.js → Tenant-BFdGpbs7.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-D_rBu_by.js → Terminal-Xpx61vHL.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-D3Vm4Po4.js → TimelineRenderer-C6UIvyZQ.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DNTxRH6q.js → Tokens-Dellq08f.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-Dgprz1ms.js → Trigger-VKw8d0J-.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-B2rUnVBD.js → Trust-DNftdKT5.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-DEGQNc6_.js → UkeySign-DX9VAKJI.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-jlsAx3Eh.js → VideoEditing-B2h3jO8q.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-8jQih1ij.js → Wallet-CjGkof7f.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-XLeO6xIB.js → WebAuthn-2Zfcu55P.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-De_dgDAG.js → WorkflowEditor-B9eZ8UxZ.js} +1 -1
- package/src/assets/web-panel/assets/{chat-CI19R_Sk.js → chat-CQNfD-YO.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DsYTOYN3.js → colors-D4usyFT2.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-CM3-t_Qr.js → compact-item-s4TpjvjX.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BjxlBRZv.js → createContext-BRCSvYxj.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DKJjSWRn.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-RDaWX_4i.js → hasIn-AdkUbkV-.js} +1 -1
- package/src/assets/web-panel/assets/{index-BN6UPD2E.js → index--00U6vXZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CiECJi-Q.js → index-B2V-eKfK.js} +1 -1
- package/src/assets/web-panel/assets/{index-CnHH7bnD.js → index-B4JJCfQ2.js} +1 -1
- package/src/assets/web-panel/assets/{index-CjTrRt13.js → index-BIoG5yYf.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dxge-xWl.js → index-BMcimU-2.js} +1 -1
- package/src/assets/web-panel/assets/{index-9R6BxAr0.js → index-BPhkFZ1I.js} +1 -1
- package/src/assets/web-panel/assets/{index-BHNYPO0b.js → index-BQ3DXBtD.js} +3 -3
- package/src/assets/web-panel/assets/{index-Cpqm1qfU.js → index-Bad4VNvz.js} +1 -1
- package/src/assets/web-panel/assets/{index-B9O9YyWE.js → index-BgiXR_-_.js} +1 -1
- package/src/assets/web-panel/assets/{index-B5REnKt8.js → index-BtobShro.js} +1 -1
- package/src/assets/web-panel/assets/{index-D6sm5-Xq.js → index-Bw2MEnUk.js} +1 -1
- package/src/assets/web-panel/assets/{index-DcPFB8qJ.js → index-C1mJtE6q.js} +1 -1
- package/src/assets/web-panel/assets/{index-BKJr-TZp.js → index-C484EJiS.js} +1 -1
- package/src/assets/web-panel/assets/{index-Drlnwr8F.js → index-C5KAQFPQ.js} +1 -1
- package/src/assets/web-panel/assets/index-C61cnl3K.js +1 -0
- package/src/assets/web-panel/assets/{index-Dsij_KsN.js → index-C7Y8Aluc.js} +1 -1
- package/src/assets/web-panel/assets/{index-IeiL9RKc.js → index-CCsM_Ybx.js} +1 -1
- package/src/assets/web-panel/assets/{index-B-Z8eFUJ.js → index-CJCFe2Qf.js} +1 -1
- package/src/assets/web-panel/assets/{index-CyOGN6a5.js → index-CJVEOa4i.js} +1 -1
- package/src/assets/web-panel/assets/{index-B0PMlbMs.js → index-CJdQrZth.js} +1 -1
- package/src/assets/web-panel/assets/{index-nAH87mQP.js → index-CKC1t3Ic.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGqqJfL0.js → index-CQhAVU5t.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cd9OJhHG.js → index-CYdoQsa1.js} +1 -1
- package/src/assets/web-panel/assets/{index-D0zcy54x.js → index-Cduu2Hhr.js} +1 -1
- package/src/assets/web-panel/assets/{index-DIUnNOjG.js → index-CkwiSLhU.js} +1 -1
- package/src/assets/web-panel/assets/{index-CVQMeiwH.js → index-Cvyt-zhm.js} +1 -1
- package/src/assets/web-panel/assets/{index-BlT2VAEK.js → index-D2GjI2oe.js} +1 -1
- package/src/assets/web-panel/assets/index-D4XFHxBr.js +1 -0
- package/src/assets/web-panel/assets/{index-C0yx-jtQ.js → index-DARsAyUp.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bi46Xu4u.js → index-DVKfQ0Ux.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cd3euP_4.js → index-DZT36ZYq.js} +1 -1
- package/src/assets/web-panel/assets/{index-BCnZyIMA.js → index-D_XBHopw.js} +1 -1
- package/src/assets/web-panel/assets/{index-C4gkzxkw.js → index-DdCB70SS.js} +1 -1
- package/src/assets/web-panel/assets/{index-B7WBt_4T.js → index-DzRjHxEv.js} +1 -1
- package/src/assets/web-panel/assets/{index-DX7tuWVJ.js → index-MMN9V6JF.js} +1 -1
- package/src/assets/web-panel/assets/{index-DoQA0-52.js → index-RfMr79MW.js} +1 -1
- package/src/assets/web-panel/assets/{index-DXXtGMUJ.js → index-_IRVsV9X.js} +1 -1
- package/src/assets/web-panel/assets/{index-pPL66J85.js → index-nXyk8GZ9.js} +1 -1
- package/src/assets/web-panel/assets/{index-DyIWssPC.js → index-s_buFMEG.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-BTL88of4.js → initDefaultProps-Blmpk7HL.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BUB2pXwB.js → motion-DPBJMv1n.js} +1 -1
- package/src/assets/web-panel/assets/{move-egCkkOMm.js → move-ButdzCM7.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-DAWhZC8c.js → mtc-parser-cyRC_QCe.js} +1 -1
- package/src/assets/web-panel/assets/{omit-CvOxe_6d.js → omit-1epSV7hz.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DZUSLZ5Z.js → pickAttrs-DuPY8xJs.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BERxGNMY.js → placementArrow-6XZqarhe.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-DZuDfZ9n.js → responsiveObserve-B40pXBWM.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DO756sgI.js → slide-jbZ9Wu4n.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BRQlIz28.js → statusUtils-BKQQcVy4.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-DCSfdybl.js → styleChecker-NiKfWjUT.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-LD8dWVve.js → useFlexGapSupport-bQUCvPeb.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-BX9uW2LK.js → useFs-CUGji7ph.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BPSlPuHU.js → usePersonalDataHub-4veyN2N2.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-BmOILC9V.js → vnode-1-nLug-Z.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-1iKowKGg.js → zoom-dhCeRDMo.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +3 -3
- 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/data/changelog.json +15 -2
- 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/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-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/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 +83 -3
- package/src/runtime/headless-runner.js +30 -25
- package/src/runtime/headless-stream.js +32 -25
- 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/MarkdownRenderer-yySN5YNM.js +0 -1
- package/src/assets/web-panel/assets/MobileProjects-DlPwcCbq.js +0 -1
- package/src/assets/web-panel/assets/Projects-CMolGhae.js +0 -1
- package/src/assets/web-panel/assets/devWarning-S1ld2LwU.js +0 -1
- package/src/assets/web-panel/assets/index-Drz6yq0m.js +0 -1
- package/src/assets/web-panel/assets/index-uWiUs7S_.js +0 -1
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { TextDecoder } from "node:util";
|
|
4
|
+
import {
|
|
5
|
+
buildExecutionLocationCatalog,
|
|
6
|
+
buildExecutionLocationHandoffPreview,
|
|
7
|
+
} from "../lib/execution-location-contract.js";
|
|
8
|
+
import { captureAmbientExecutionLocation } from "../lib/execution-location-runtime.js";
|
|
9
|
+
import { getVerifiedSessionExecutionLocationAuthority } from "../harness/jsonl-session-store.js";
|
|
10
|
+
import {
|
|
11
|
+
sameFileStatIdentity,
|
|
12
|
+
samePathHandleFileIdentity,
|
|
13
|
+
withTrustedFileParentSync,
|
|
14
|
+
} from "../lib/secure-file-identity.js";
|
|
15
|
+
|
|
16
|
+
const MAX_HANDOFF_FACTS_BYTES = 1024 * 1024;
|
|
17
|
+
export const SESSION_EXECUTION_LOCATION_AUTHORITY_SCHEMA =
|
|
18
|
+
"cc-session-execution-location-authority/v1";
|
|
19
|
+
|
|
20
|
+
function readHandoffFacts(filePath, deps = {}) {
|
|
21
|
+
const runtimeFs = deps.fs || fs;
|
|
22
|
+
const withTrustedParent =
|
|
23
|
+
deps.withTrustedFileParentSync || withTrustedFileParentSync;
|
|
24
|
+
return withTrustedParent(
|
|
25
|
+
runtimeFs,
|
|
26
|
+
path.resolve(filePath),
|
|
27
|
+
({ canonicalPath, parentDevice }) => {
|
|
28
|
+
const before = runtimeFs.lstatSync(canonicalPath, { bigint: true });
|
|
29
|
+
if (
|
|
30
|
+
before.isSymbolicLink() ||
|
|
31
|
+
!before.isFile() ||
|
|
32
|
+
Number(before.nlink) !== 1
|
|
33
|
+
) {
|
|
34
|
+
throw new Error("handoff facts must be a regular, single-link file");
|
|
35
|
+
}
|
|
36
|
+
const size = Number(before.size);
|
|
37
|
+
if (size <= 0 || size > MAX_HANDOFF_FACTS_BYTES) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
`handoff facts must be 1..${MAX_HANDOFF_FACTS_BYTES} bytes`,
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
let descriptor = null;
|
|
43
|
+
try {
|
|
44
|
+
descriptor = runtimeFs.openSync(
|
|
45
|
+
canonicalPath,
|
|
46
|
+
runtimeFs.constants.O_RDONLY |
|
|
47
|
+
Number(runtimeFs.constants.O_NOFOLLOW || 0),
|
|
48
|
+
);
|
|
49
|
+
const opened = runtimeFs.fstatSync(descriptor, { bigint: true });
|
|
50
|
+
const samePathHandle =
|
|
51
|
+
deps.samePathHandleFileIdentity || samePathHandleFileIdentity;
|
|
52
|
+
if (
|
|
53
|
+
!opened.isFile() ||
|
|
54
|
+
Number(opened.nlink) !== 1 ||
|
|
55
|
+
!samePathHandle(before, opened, parentDevice, deps.runtime)
|
|
56
|
+
) {
|
|
57
|
+
throw new Error("handoff facts identity changed while opening");
|
|
58
|
+
}
|
|
59
|
+
const bounded = Buffer.allocUnsafe(MAX_HANDOFF_FACTS_BYTES + 1);
|
|
60
|
+
let bytesRead = 0;
|
|
61
|
+
while (bytesRead < bounded.length) {
|
|
62
|
+
const count = runtimeFs.readSync(
|
|
63
|
+
descriptor,
|
|
64
|
+
bounded,
|
|
65
|
+
bytesRead,
|
|
66
|
+
bounded.length - bytesRead,
|
|
67
|
+
null,
|
|
68
|
+
);
|
|
69
|
+
if (count === 0) break;
|
|
70
|
+
bytesRead += count;
|
|
71
|
+
}
|
|
72
|
+
if (bytesRead > MAX_HANDOFF_FACTS_BYTES) {
|
|
73
|
+
throw new Error(
|
|
74
|
+
`handoff facts exceed ${MAX_HANDOFF_FACTS_BYTES} bytes`,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
const after = runtimeFs.fstatSync(descriptor, { bigint: true });
|
|
78
|
+
if (
|
|
79
|
+
Number(after.size) !== bytesRead ||
|
|
80
|
+
!(deps.sameFileStatIdentity || sameFileStatIdentity)(opened, after)
|
|
81
|
+
) {
|
|
82
|
+
throw new Error("handoff facts changed while being read");
|
|
83
|
+
}
|
|
84
|
+
return JSON.parse(
|
|
85
|
+
new TextDecoder("utf-8", { fatal: true }).decode(
|
|
86
|
+
bounded.subarray(0, bytesRead),
|
|
87
|
+
),
|
|
88
|
+
);
|
|
89
|
+
} finally {
|
|
90
|
+
if (descriptor !== null) runtimeFs.closeSync(descriptor);
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
{ runtime: deps.runtime },
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function projectCurrentExecutionLocation(options = {}, deps = {}) {
|
|
98
|
+
const binding = (
|
|
99
|
+
deps.captureAmbientExecutionLocation || captureAmbientExecutionLocation
|
|
100
|
+
)(options, deps);
|
|
101
|
+
return {
|
|
102
|
+
schema: SESSION_EXECUTION_LOCATION_AUTHORITY_SCHEMA,
|
|
103
|
+
authority: "current-process-observation",
|
|
104
|
+
binding,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function projectSessionExecutionLocation(sessionId, deps = {}) {
|
|
109
|
+
const authority = (
|
|
110
|
+
deps.getVerifiedSessionExecutionLocationAuthority ||
|
|
111
|
+
getVerifiedSessionExecutionLocationAuthority
|
|
112
|
+
)(sessionId);
|
|
113
|
+
return {
|
|
114
|
+
schema: SESSION_EXECUTION_LOCATION_AUTHORITY_SCHEMA,
|
|
115
|
+
authority: "verified-session-start",
|
|
116
|
+
sessionId: authority.sessionId,
|
|
117
|
+
headHash: authority.headHash,
|
|
118
|
+
eventCount: authority.eventCount,
|
|
119
|
+
binding: authority.binding,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function projectExecutionLocationComparison(options = {}, deps = {}) {
|
|
124
|
+
return buildExecutionLocationCatalog(
|
|
125
|
+
(deps.captureAmbientExecutionLocation || captureAmbientExecutionLocation)(
|
|
126
|
+
options,
|
|
127
|
+
deps,
|
|
128
|
+
),
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function projectExecutionLocationHandoff(
|
|
133
|
+
sessionId,
|
|
134
|
+
target,
|
|
135
|
+
factsPath,
|
|
136
|
+
deps = {},
|
|
137
|
+
) {
|
|
138
|
+
const source = projectSessionExecutionLocation(sessionId, deps);
|
|
139
|
+
const facts = (deps.readHandoffFacts || readHandoffFacts)(factsPath, deps);
|
|
140
|
+
return {
|
|
141
|
+
...buildExecutionLocationHandoffPreview({
|
|
142
|
+
sourceBinding: source.binding,
|
|
143
|
+
sourceAuthority: {
|
|
144
|
+
sessionId: source.sessionId,
|
|
145
|
+
headHash: source.headHash,
|
|
146
|
+
eventCount: source.eventCount,
|
|
147
|
+
},
|
|
148
|
+
target,
|
|
149
|
+
facts,
|
|
150
|
+
}),
|
|
151
|
+
session: {
|
|
152
|
+
sessionId: source.sessionId,
|
|
153
|
+
headHash: source.headHash,
|
|
154
|
+
eventCount: source.eventCount,
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function renderBinding(binding) {
|
|
160
|
+
const git = binding.source.git;
|
|
161
|
+
return [
|
|
162
|
+
`Location: ${binding.location}`,
|
|
163
|
+
`Observed: ${binding.observed ? "yes" : "no"}`,
|
|
164
|
+
`Working directory: ${binding.source.cwd || "unknown"}`,
|
|
165
|
+
`Git root: ${git.root || "not detected"}`,
|
|
166
|
+
`Git head: ${git.head || "unknown"}`,
|
|
167
|
+
`Git commit: ${git.commit || "unknown"}`,
|
|
168
|
+
`Tools: ${binding.runtime.tools.join(", ") || "none observed"}`,
|
|
169
|
+
`Model: ${binding.model.provider || "unknown"}/${binding.model.name || "unknown"}`,
|
|
170
|
+
`Credential source: ${binding.model.credentialSource}`,
|
|
171
|
+
`Network policy: ${binding.policy.network}`,
|
|
172
|
+
`Sandbox strength: ${binding.policy.sandbox}`,
|
|
173
|
+
`Data boundary: ${binding.policy.dataBoundary.kind} (${binding.policy.dataBoundary.root || "unknown"})`,
|
|
174
|
+
"Remote Control: controls this host; it is not a remote execution location",
|
|
175
|
+
].join("\n");
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function writeProjection(projection, options = {}) {
|
|
179
|
+
if (options.json) {
|
|
180
|
+
process.stdout.write(`${JSON.stringify(projection, null, 2)}\n`);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
if (projection.binding) {
|
|
184
|
+
process.stdout.write(`${renderBinding(projection.binding)}\n`);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (Array.isArray(projection.locations)) {
|
|
188
|
+
process.stdout.write(
|
|
189
|
+
`${projection.locations
|
|
190
|
+
.map(
|
|
191
|
+
(entry) =>
|
|
192
|
+
`${entry.location.padEnd(10)} ${entry.availability.padEnd(24)} launch=${entry.capabilities.launch} resume=${entry.capabilities.resume} sandbox=${entry.policy.sandbox} network=${entry.policy.network}`,
|
|
193
|
+
)
|
|
194
|
+
.join(
|
|
195
|
+
"\n",
|
|
196
|
+
)}\nRemote Control is a control plane, not an execution location.\n`,
|
|
197
|
+
);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
process.stdout.write(
|
|
201
|
+
`${projection.allowed ? "ALLOWED" : "BLOCKED"}\n${
|
|
202
|
+
projection.blockers.length > 0
|
|
203
|
+
? `Blockers:\n${projection.blockers.map((item) => `- ${item}`).join("\n")}\n`
|
|
204
|
+
: ""
|
|
205
|
+
}`,
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function runAction(action, options = {}) {
|
|
210
|
+
try {
|
|
211
|
+
const projection = action();
|
|
212
|
+
writeProjection(projection, options);
|
|
213
|
+
return projection.allowed === false ? 2 : 0;
|
|
214
|
+
} catch (error) {
|
|
215
|
+
process.stderr.write(`Execution location failed: ${error.message}\n`);
|
|
216
|
+
return 1;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export function registerSessionLocationSubcommands(session) {
|
|
221
|
+
const location = session
|
|
222
|
+
.command("location")
|
|
223
|
+
.description(
|
|
224
|
+
"Inspect verified execution location, capabilities, and handoff safety",
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
location
|
|
228
|
+
.command("current")
|
|
229
|
+
.description("Observe where this CLI process is executing")
|
|
230
|
+
.option("--json", "Machine-readable JSON output")
|
|
231
|
+
.action((options) => {
|
|
232
|
+
process.exitCode = runAction(
|
|
233
|
+
() => projectCurrentExecutionLocation({}, {}),
|
|
234
|
+
options,
|
|
235
|
+
);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
location
|
|
239
|
+
.command("show <id>")
|
|
240
|
+
.description("Show the execution location anchored by session_start")
|
|
241
|
+
.option("--json", "Machine-readable JSON output")
|
|
242
|
+
.action((id, options) => {
|
|
243
|
+
process.exitCode = runAction(
|
|
244
|
+
() => projectSessionExecutionLocation(id),
|
|
245
|
+
options,
|
|
246
|
+
);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
location
|
|
250
|
+
.command("compare")
|
|
251
|
+
.description(
|
|
252
|
+
"Compare current and declared Local/WSL/SSH/Container/Cloud capabilities",
|
|
253
|
+
)
|
|
254
|
+
.option("--json", "Machine-readable JSON output")
|
|
255
|
+
.action((options) => {
|
|
256
|
+
process.exitCode = runAction(
|
|
257
|
+
() => projectExecutionLocationComparison({}, {}),
|
|
258
|
+
options,
|
|
259
|
+
);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
location
|
|
263
|
+
.command("handoff <id> <target>")
|
|
264
|
+
.description("Preview a fail-closed, secret-free session handoff")
|
|
265
|
+
.requiredOption(
|
|
266
|
+
"--facts <path>",
|
|
267
|
+
"Versioned Git/summary/artifact/permission/target evidence JSON",
|
|
268
|
+
)
|
|
269
|
+
.option("--json", "Machine-readable JSON output")
|
|
270
|
+
.action((id, target, options) => {
|
|
271
|
+
process.exitCode = runAction(
|
|
272
|
+
() => projectExecutionLocationHandoff(id, target, options.facts),
|
|
273
|
+
options,
|
|
274
|
+
);
|
|
275
|
+
});
|
|
276
|
+
}
|
package/src/commands/session.js
CHANGED
|
@@ -66,6 +66,7 @@ import { executionBroker } from "../lib/process-execution-broker/index.js";
|
|
|
66
66
|
import { registerSessionMcpRecoveryCommands } from "./session-mcp-recovery.js";
|
|
67
67
|
import { registerSessionShowSubcommand } from "./session-show.js";
|
|
68
68
|
import { registerSessionObservabilitySubcommand } from "./session-observability.js";
|
|
69
|
+
import { registerSessionLocationSubcommands } from "./session-location.js";
|
|
69
70
|
|
|
70
71
|
export const _deps = {
|
|
71
72
|
execFileSync: (...args) => executionBroker.execFileSync(...args),
|
|
@@ -222,6 +223,7 @@ export function registerSessionCommand(program) {
|
|
|
222
223
|
.description("Conversation session management");
|
|
223
224
|
|
|
224
225
|
registerSessionMcpRecoveryCommands(session);
|
|
226
|
+
registerSessionLocationSubcommands(session);
|
|
225
227
|
|
|
226
228
|
// session list
|
|
227
229
|
session
|
package/src/data/changelog.json
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"source": "CHANGELOG.md",
|
|
3
3
|
"releases": [
|
|
4
|
+
{
|
|
5
|
+
"productVersion": null,
|
|
6
|
+
"cliVersion": "0.164.0",
|
|
7
|
+
"cliVersions": ["0.163.8", "0.164.0"],
|
|
8
|
+
"date": "2026-08-15",
|
|
9
|
+
"title": "",
|
|
10
|
+
"sections": [
|
|
11
|
+
{
|
|
12
|
+
"heading": "Added — cc CLI 0.164.0: governed marketplace, execution authority, and native isolation hardening",
|
|
13
|
+
"body": "> `chainlesschain` **0.163.8 → 0.164.0** (candidate; not yet published,\n> 2026-08-15).\n> CLI-only candidate; `@chainlesschain/personal-data-hub` remains **0.4.57**\n> and `@chainlesschain/agent-sdk` remains **0.1.7**.\n\n- **Native clipboard images**: `/paste-image` can attach bounded PNG, JPEG,\n GIF, and WebP clipboard payloads to the next vision turn. Windows, macOS,\n Wayland, and X11 host adapters use literal arguments, private temporary\n files, signature checks, byte/count limits, and the Process Broker boundary.\n- **Scoped execution and context authority**: runtime permissions now expose\n exact side-effect explanations and scoped decisions, while session execution\n locations, IDE context-center evidence, prompt interactions, and durable\n workflow definitions carry versioned identities instead of ambient context.\n- **Governed plugin marketplace**: catalog, multi-registry candidate selection,\n install authority, update-impact review, artifact byte readback, and remote\n artifact verification bind publisher, digest, signature, source, policy, and\n approval evidence before plugin installation or update.\n- **Background keeper containment**: an independent keeper records Worker and\n descendant PIDs, retires interrupted turns under bounded Windows identity and\n cleanup budgets, and emits strict formal/smoke evidence contracts. The local\n real-spawn regression is green; the three-platform formal keeper aggregate is\n still required before P1-2 can be marked complete.\n- **MCP capsule boundary evidence**: materialized capsules bind the exact Node\n builtin capability set and OS execution-context requirements. Formal evidence\n now hashes and reparses each live result and schedules three independent\n fresh-isolate probes per platform across a two-hour span; smoke evidence is\n explicitly non-qualifying.\n- **Session and remote-approval hardening**: canonical session persistence gains\n additional crash and anti-rollback checks. Client-hosted remote approval uses\n durable same-machine membership epochs and fails closed on stale, revoked, or\n unavailable authority. Signed coordinator/host lease modules are included as\n a foundation only; they are not yet wired as a complete cross-host dispatch\n fence and do not claim distributed consensus or revoke closure.\n- **Linux dynamic-native isolation candidate**: strict Linux native execution\n recursively attests the ELF startup graph, snapshots caller-owned runtime and\n plugin bytes, exposes only a read-only descriptor-bound namespace, and blocks\n loader-input acquisition and nested mount namespaces with a dynamic-only\n seccomp profile. The typed claim is limited to pathname-visible loader input;\n broad `sharedLibraryClosure` remains false, JIT/custom loaders are excluded,\n and packed Linux runtimes fail closed until separately supported.\n- **macOS signed launcher candidate**: a fixed signed/root helper contract can\n copy and hash runtime and entry descriptors into root-protected snapshots,\n gate entry until the runtime pathname is removed, supervise the target, and\n fail closed when ownership, receipt, protocol, or signing evidence differs.\n It remains disabled until the protected x64/arm64 workflow proves Developer\n ID signing, notarization, root package installation, and the full live race\n matrix; it does not claim shared-library closure.\n- **Compatibility and reliability boundary**: reaching the documented\n `0.164.0` removal floor does not replace representative telemetry. All 25\n compatibility aliases remain retained because approved cohort export,\n three-platform reporting coverage, accepted points, and per-command usage are\n still absent. The scheduler campaign remains incomplete, and the uncommitted\n remote `run_shell` lease-consumption vertical is excluded after its expanded\n parallel matrix did not finish fully green.\n- **Release authority hardening**: manual npm workflow runs are dry-run only;\n production packaging and publishing require an immutable `v-npm-*` tag-push\n event. Operator-controlled version text is no longer interpolated into shell\n scripts, release Actions are commit-pinned, and independent readback validates\n a canonical numeric SemVer before resolving the tag and attested artifact.\n- **Release status**: final tag, source SHA, workflow run IDs, package digests,\n provenance, and registry readback are intentionally omitted until the exact\n `0.164.0` release merge commit passes complete `CLI CI` and\n `CLI Strict Sandbox` matrices on Linux, Windows, and macOS, followed by the\n dedicated npm release and independent public readback workflows."
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
4
17
|
{
|
|
5
18
|
"productVersion": null,
|
|
6
19
|
"cliVersion": "0.163.8",
|
|
@@ -10,7 +23,7 @@
|
|
|
10
23
|
"sections": [
|
|
11
24
|
{
|
|
12
25
|
"heading": "Added — cc CLI 0.163.8: governed recovery, merge review, and MCP resource templates",
|
|
13
|
-
"body": "> `chainlesschain` **0.163.7 → 0.163.8** (
|
|
26
|
+
"body": "> `chainlesschain` **0.163.7 → 0.163.8** (published from exact SHA\n> `a0631cb4f97f45ff7fcef9c19d346ed2b8387da6`, 2026-08-14).\n> CLI-only release; `@chainlesschain/personal-data-hub` remains **0.4.57**\n> and `@chainlesschain/agent-sdk` remains **0.1.7**.\n\n- **Crash-safe scheduler source persistence**: Agenda and Cowork authoritative\n stores now reject unreadable, malformed, and non-object records instead of\n treating them as empty state. Generation replacement uses private exclusive\n temporary files, complete short-write loops, file fsync, atomic rename, and\n POSIX directory fsync, while distinguishing pre-rename `not-committed`\n failures from post-rename durability-unknown outcomes.\n- **Deterministic scheduler disk-fault closure**: fault injection covers ENOSPC,\n partial writes, file and directory fsync failures, rename failures, corrupted\n source stores, native SQLite `SQLITE_FULL` transaction rollback, Automation\n source rollback atomicity, database truncation, and clean reopen behavior.\n Routine and Loop retain their existing durable-store and append/CAS\n protections.\n- **Governed Automation runtime recovery**: scheduler-backed Automation work can\n expose exact-fence, control-revision, capability-bound pause and resume safe\n points. Revisioned incidents support bounded retry or cancellation; retry\n revalidates the exact dead-letter occurrence, run identity, fence, and error\n evidence, while manual incidents are not silently replayed.\n- **Governed multi-agent merge review**: `cc team merge-review` subcommands\n `preview|show|apply|rollback` provide stable file and hunk selection,\n digest-bound decisions, durable conflict evidence, guarded cross-branch batch\n publication, and retained-history rollback. Git hooks, repository-local\n configuration, inherited environment, stale revisions, oversized selections,\n and changed branch identities fail closed.\n- **Read-only MCP resource templates**: templates-only MCP servers can now\n register the existing resource surface. The new\n `list_mcp_resource_templates {server?}` tool reads the bounded discovery\n cache, supports explicit server filtering, and lets the model instantiate a\n concrete URI before using the existing `read_mcp_resource` boundary. It does\n not add an implicit network request, subscription, or automatic URI\n expansion.\n- **Explicit optional-protocol decisions**: resource templates enter the\n production read-only surface; resource subscriptions, peer-controlled\n logging, and completion remain deferred pending bounded consumers and\n cancellation/recovery UX. MCP sampling remains undeclared and server\n `createMessage` requests continue to return JSON-RPC `-32601`.\n- **Transaction-time scheduler fencing**: claim, renewal, and settlement paths\n now read their lease clock inside the write transaction, preventing queue\n wait time from turning a pre-transaction timestamp into a stale lease or\n settlement decision.\n- **Formal scheduler soak evidence gate**: Linux, Windows, and macOS workflows\n now exercise two-worker contention, lease/fence recovery, heartbeat renewal,\n stale settlement rejection, outcome-unknown no-replay, DST/backlog behavior,\n SQLite integrity, descendant cleanup, and bounded resource trends. The\n campaign verifier requires at least four identity-bound formal segments whose\n authoritative starts span at least 72 natural hours, with no gap above\n 30 hours.\n- **Release boundary**: the scheduler soak implementation and smoke matrices are\n present, but the required 72-hour formal campaign has not completed; P2-4\n therefore remains partially complete. Signed native distribution,\n representative alias-removal telemetry, and the later P2-2 native\n clipboard-image host work remain outside this immutable release.\n- **Published release evidence**: immutable tag `v-npm-0-163-8` resolves to\n exact source commit `a0631cb4f97f45ff7fcef9c19d346ed2b8387da6`. Its\n three-OS `CLI CI` (`31804468633`) and `CLI Strict Sandbox` (`31804468464`)\n matrices passed; the dedicated npm release (`31806101423`) and independent\n public readback (`31807574517`) succeeded. npm reports `latest=0.163.8`;\n tarball SHA-1 is `655557b5c5b897b23a29975708abbf8d5cd31e88` and SHA-256\n is `862a0f450da013740a1c21d084233b002982b4b816f156e4949b6110eda80e12`."
|
|
14
27
|
}
|
|
15
28
|
]
|
|
16
29
|
},
|
|
@@ -23,7 +36,7 @@
|
|
|
23
36
|
"sections": [
|
|
24
37
|
{
|
|
25
38
|
"heading": "Added — cc CLI 0.163.7: governed scheduler migration and causal observability",
|
|
26
|
-
"body": "> `chainlesschain` **0.163.6 → 0.163.7** (published from exact SHA\n> `3e997168621c53708a1682868c6cc4edc9baf15b`, 2026-08-14).\n> CLI-only release; `@chainlesschain/personal-data-hub` remains **0.4.57**\n> and `@chainlesschain/agent-sdk` remains **0.1.7**.\n\n- **Five-domain migration journal**: Agenda, Cowork Cron, Routine, Automation,\n and Loop migrations use the scheduler store schema-v5 journal with\n domain-typed source locators, immutable source/target digest bindings,\n idempotent recovery, and fail-closed rejection of conflicting or ambiguous\n legacy entries.\n- **Governed rollback controls**: the new scheduler migration `list`, `show`,\n and `rollback` commands expose redacted migration status and blockers.\n Rollback requires the latest evidence digest, an interactive TTY, and the\n exact typed challenge before reopening any legacy source.\n- **Target-first recovery and CAS fencing**: rollback stops or restores the\n scheduler target before restoring the legacy source, validates target\n revision, definition and execution evidence, and makes terminal source\n restoration retry-safe across process crashes. This is not a claim of one\n atomic transaction across independent stores or filesystems.\n- **Fail-closed source identity**: Windows drive and UNC paths are canonicalized\n while relative, incomplete and device-namespace paths are rejected.\n Automation migration requires an existing native SQLite database and refuses\n the non-durable sql.js fallback; Loop restoration remains bound to its durable\n retirement fence, marker and original source digest.\n- **Windows persistence hardening**: team adjudication atomic replacement\n retries only transient Windows `EACCES`, `EBUSY`, and `EPERM` sharing\n failures with bounded backoff and authority-path revalidation. Exhausted,\n non-transient, and non-Windows replacement failures continue to fail closed.\n- **Cross-platform CI hardening**: migration fixtures verify retirement fences\n and canonical source identities consistently across operating systems, while\n distributed-queue and authority test workers use bounded lifetimes and attach\n result observers before short-lived children can exit. Terminal Skill\n authority fixtures now use an explicit parent acknowledgement before clean\n exit, removing Windows IPC exit-before-message ordering ambiguity without\n weakening concurrent revocation assertions.\n- **Verified causal delivery reports**: scoped sessions can be bound by exact\n transcript head and event count to digest-protected delivery states. The new\n session observability commands export a redacted session-to-delivery graph\n spanning diffs, gates, artifacts, pull requests, and merges, with exact\n workspace, team, and policy filters.\n- **Fail-closed call-ledger budgets**: `call-ledger@1` brackets model, retry,\n compaction, subagent, isolated-skill, and tool calls with known or unknown\n settlements. Strict budget mode rejects exceeded and unevaluable results\n instead of treating missing token, cost, retry, or tool-latency evidence as\n zero.\n- **Background recovery authority hardening**: verified transcript CAS,\n delegated recovery leases, IPC sender/nonce binding, bootstrap guards, exact\n process-group termination checks, and terminal cleanup prevent uncertain or\n still-live descendants from authorizing recovery or worktree deletion.\n- **Causal evidence boundary**: report bindings prove exact verified revisions,\n not that a model call semantically caused a source hunk. Scope labels are not\n identity or membership proofs, digests are not signatures, anti-rollback is\n machine-local, and incomplete or legacy ledgers remain partial or unknown.\n- **
|
|
39
|
+
"body": "> `chainlesschain` **0.163.6 → 0.163.7** (published from exact SHA\n> `3e997168621c53708a1682868c6cc4edc9baf15b`, 2026-08-14).\n> CLI-only release; `@chainlesschain/personal-data-hub` remains **0.4.57**\n> and `@chainlesschain/agent-sdk` remains **0.1.7**.\n\n- **Five-domain migration journal**: Agenda, Cowork Cron, Routine, Automation,\n and Loop migrations use the scheduler store schema-v5 journal with\n domain-typed source locators, immutable source/target digest bindings,\n idempotent recovery, and fail-closed rejection of conflicting or ambiguous\n legacy entries.\n- **Governed rollback controls**: the new scheduler migration `list`, `show`,\n and `rollback` commands expose redacted migration status and blockers.\n Rollback requires the latest evidence digest, an interactive TTY, and the\n exact typed challenge before reopening any legacy source.\n- **Target-first recovery and CAS fencing**: rollback stops or restores the\n scheduler target before restoring the legacy source, validates target\n revision, definition and execution evidence, and makes terminal source\n restoration retry-safe across process crashes. This is not a claim of one\n atomic transaction across independent stores or filesystems.\n- **Fail-closed source identity**: Windows drive and UNC paths are canonicalized\n while relative, incomplete and device-namespace paths are rejected.\n Automation migration requires an existing native SQLite database and refuses\n the non-durable sql.js fallback; Loop restoration remains bound to its durable\n retirement fence, marker and original source digest.\n- **Windows persistence hardening**: team adjudication atomic replacement\n retries only transient Windows `EACCES`, `EBUSY`, and `EPERM` sharing\n failures with bounded backoff and authority-path revalidation. Exhausted,\n non-transient, and non-Windows replacement failures continue to fail closed.\n- **Cross-platform CI hardening**: migration fixtures verify retirement fences\n and canonical source identities consistently across operating systems, while\n distributed-queue and authority test workers use bounded lifetimes and attach\n result observers before short-lived children can exit. Terminal Skill\n authority fixtures now use an explicit parent acknowledgement before clean\n exit, removing Windows IPC exit-before-message ordering ambiguity without\n weakening concurrent revocation assertions.\n- **Verified causal delivery reports**: scoped sessions can be bound by exact\n transcript head and event count to digest-protected delivery states. The new\n session observability commands export a redacted session-to-delivery graph\n spanning diffs, gates, artifacts, pull requests, and merges, with exact\n workspace, team, and policy filters.\n- **Fail-closed call-ledger budgets**: `call-ledger@1` brackets model, retry,\n compaction, subagent, isolated-skill, and tool calls with known or unknown\n settlements. Strict budget mode rejects exceeded and unevaluable results\n instead of treating missing token, cost, retry, or tool-latency evidence as\n zero.\n- **Background recovery authority hardening**: verified transcript CAS,\n delegated recovery leases, IPC sender/nonce binding, bootstrap guards, exact\n process-group termination checks, and terminal cleanup prevent uncertain or\n still-live descendants from authorizing recovery or worktree deletion.\n- **Causal evidence boundary**: report bindings prove exact verified revisions,\n not that a model call semantically caused a source hunk. Scope labels are not\n identity or membership proofs, digests are not signatures, anti-rollback is\n machine-local, and incomplete or legacy ledgers remain partial or unknown.\n- **Published release evidence**: immutable tag `v-npm-0-163-7` resolves to\n exact source commit `3e997168621c53708a1682868c6cc4edc9baf15b`. Its\n three-OS `CLI CI` (`31745391661`, attempt 2) and `CLI Strict Sandbox`\n (`31745391321`) matrices passed; the dedicated npm release (`31748153519`)\n completed exact-SHA gating, immutable artifact, CycloneDX SBOM, Trusted\n Publishing, signed provenance, registry byte verification, and npmmirror\n synchronization. Independent readback (`31749404980`) verified the public\n tarball byte-for-byte against the immutable artifact. npm reports\n `latest=0.163.7`; tarball SHA-1 is\n `5bfb7471643cfe4d4cd0b0a382b31c63fc1efdff` and SHA-256 is\n `d7ca295e6cdb4e442ee7ad6bb9cc0b9d923f40de4eae395974d91b4dfab83a9d`.\n- **Release boundary**: deterministic scheduler disk-fault closure landed\n after this immutable release and must not be attributed to its tarball. The\n three-OS long-soak exit campaign, signed native distribution, and\n representative alias-removal telemetry remain open."
|
|
27
40
|
}
|
|
28
41
|
]
|
|
29
42
|
},
|
|
@@ -310,9 +310,21 @@ export async function handleWorkflowGet(server, id, ws, message) {
|
|
|
310
310
|
const { id: wfId } = message || {};
|
|
311
311
|
if (!wfId) return _sendError(server, ws, id, "MISSING_ID", "id required");
|
|
312
312
|
try {
|
|
313
|
-
const {
|
|
314
|
-
const
|
|
315
|
-
server._send(ws, {
|
|
313
|
+
const { getWorkflowRecord } = await import("../../lib/cowork-workflow.js");
|
|
314
|
+
const record = getWorkflowRecord(_cwd(server), wfId);
|
|
315
|
+
server._send(ws, {
|
|
316
|
+
id,
|
|
317
|
+
type: "workflow:get",
|
|
318
|
+
workflow: record?.definition || null,
|
|
319
|
+
definitionAuthority: record
|
|
320
|
+
? {
|
|
321
|
+
status: record.status,
|
|
322
|
+
recordSchema: record.recordSchema,
|
|
323
|
+
definitionSchema: record.definitionSchema,
|
|
324
|
+
definitionDigest: record.definitionDigest,
|
|
325
|
+
}
|
|
326
|
+
: null,
|
|
327
|
+
});
|
|
316
328
|
} catch (err) {
|
|
317
329
|
_sendError(server, ws, id, "WORKFLOW_GET_FAILED", err.message);
|
|
318
330
|
}
|
|
@@ -330,7 +342,7 @@ export async function handleWorkflowSave(server, id, ws, message) {
|
|
|
330
342
|
);
|
|
331
343
|
}
|
|
332
344
|
try {
|
|
333
|
-
const { validateWorkflow, saveWorkflow } =
|
|
345
|
+
const { getWorkflowRecord, validateWorkflow, saveWorkflow } =
|
|
334
346
|
await import("../../lib/cowork-workflow.js");
|
|
335
347
|
const result = validateWorkflow(workflow);
|
|
336
348
|
if (!result.valid) {
|
|
@@ -343,11 +355,14 @@ export async function handleWorkflowSave(server, id, ws, message) {
|
|
|
343
355
|
);
|
|
344
356
|
}
|
|
345
357
|
saveWorkflow(_cwd(server), workflow);
|
|
358
|
+
const record = getWorkflowRecord(_cwd(server), workflow.id);
|
|
346
359
|
server._send(ws, {
|
|
347
360
|
id,
|
|
348
361
|
type: "workflow:save",
|
|
349
362
|
saved: true,
|
|
350
363
|
workflowId: workflow.id,
|
|
364
|
+
definitionDigest: record.definitionDigest,
|
|
365
|
+
definitionSchema: record.definitionSchema,
|
|
351
366
|
});
|
|
352
367
|
} catch (err) {
|
|
353
368
|
_sendError(server, ws, id, "WORKFLOW_SAVE_FAILED", err.message);
|
|
@@ -367,14 +382,16 @@ export async function handleWorkflowRemove(server, id, ws, message) {
|
|
|
367
382
|
}
|
|
368
383
|
|
|
369
384
|
export async function handleWorkflowRun(server, id, ws, message) {
|
|
370
|
-
const { id: wfId } = message || {};
|
|
385
|
+
const { id: wfId, definitionDigest } = message || {};
|
|
371
386
|
if (!wfId) return _sendError(server, ws, id, "MISSING_ID", "id required");
|
|
372
387
|
|
|
373
388
|
try {
|
|
374
|
-
const {
|
|
389
|
+
const { getWorkflowRecord, getWorkflowVersion, executeWorkflow } =
|
|
375
390
|
await import("../../lib/cowork-workflow.js");
|
|
376
|
-
const
|
|
377
|
-
|
|
391
|
+
const definitionRecord = definitionDigest
|
|
392
|
+
? getWorkflowVersion(_cwd(server), wfId, definitionDigest)
|
|
393
|
+
: getWorkflowRecord(_cwd(server), wfId);
|
|
394
|
+
if (!definitionRecord) {
|
|
378
395
|
return _sendError(
|
|
379
396
|
server,
|
|
380
397
|
ws,
|
|
@@ -385,7 +402,13 @@ export async function handleWorkflowRun(server, id, ws, message) {
|
|
|
385
402
|
}
|
|
386
403
|
|
|
387
404
|
const runId = `wf-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
388
|
-
server._send(ws, {
|
|
405
|
+
server._send(ws, {
|
|
406
|
+
id,
|
|
407
|
+
type: "workflow:started",
|
|
408
|
+
runId,
|
|
409
|
+
workflowId: wfId,
|
|
410
|
+
definitionDigest: definitionRecord.definitionDigest,
|
|
411
|
+
});
|
|
389
412
|
|
|
390
413
|
const onStepStart = ({ stepId, message: stepMessage }) => {
|
|
391
414
|
server._send(ws, {
|
|
@@ -408,7 +431,8 @@ export async function handleWorkflowRun(server, id, ws, message) {
|
|
|
408
431
|
};
|
|
409
432
|
|
|
410
433
|
const record = await executeWorkflow({
|
|
411
|
-
workflow,
|
|
434
|
+
workflow: definitionRecord.definition,
|
|
435
|
+
definitionDigest: definitionRecord.definitionDigest,
|
|
412
436
|
cwd: _cwd(server),
|
|
413
437
|
onStepStart,
|
|
414
438
|
onStepComplete,
|
|
@@ -420,6 +444,7 @@ export async function handleWorkflowRun(server, id, ws, message) {
|
|
|
420
444
|
runId,
|
|
421
445
|
status: record?.status || "completed",
|
|
422
446
|
steps: record?.steps || [],
|
|
447
|
+
definitionDigest: record?.definitionDigest,
|
|
423
448
|
});
|
|
424
449
|
} catch (err) {
|
|
425
450
|
_sendError(server, ws, id, "WORKFLOW_RUN_FAILED", err.message);
|
|
@@ -129,6 +129,10 @@ export function handleRemoteSessionCreate(server, clientId, ws, message) {
|
|
|
129
129
|
agentSessionId: message.sessionId,
|
|
130
130
|
name: message.name,
|
|
131
131
|
scopes: message.scopes,
|
|
132
|
+
// A local/headless approval bridge asks the server to persist a
|
|
133
|
+
// principal/session epoch before it exposes pairing credentials. Older
|
|
134
|
+
// or ordinary server-hosted sessions remain on their in-memory path.
|
|
135
|
+
durableMembership: message.requireDurableMembershipAuthority === true,
|
|
132
136
|
});
|
|
133
137
|
audit(server, {
|
|
134
138
|
sessionId: result.session.sessionId,
|
|
@@ -446,7 +450,7 @@ export async function handleRemoteSessionPublish(
|
|
|
446
450
|
return;
|
|
447
451
|
}
|
|
448
452
|
const requiredScope = CLIENT_EVENT_SCOPES[message.event.type];
|
|
449
|
-
const { session } = server.remoteSessions.authorize(
|
|
453
|
+
const { session, membership } = server.remoteSessions.authorize(
|
|
450
454
|
message.remoteSessionId,
|
|
451
455
|
clientId,
|
|
452
456
|
requiredScope || "observe",
|
|
@@ -508,6 +512,13 @@ export async function handleRemoteSessionPublish(
|
|
|
508
512
|
scopes: ["approve"],
|
|
509
513
|
principalId: clientId,
|
|
510
514
|
sessionId: message.remoteSessionId,
|
|
515
|
+
...(membership
|
|
516
|
+
? {
|
|
517
|
+
remoteSessionId: membership.sessionId,
|
|
518
|
+
sessionEpoch: membership.sessionEpoch,
|
|
519
|
+
membershipEpoch: membership.membershipEpoch,
|
|
520
|
+
}
|
|
521
|
+
: {}),
|
|
511
522
|
};
|
|
512
523
|
const approved = message.event.answer ?? message.event.approved;
|
|
513
524
|
if (approved === true || approved === "true" || approved === "yes") {
|
|
@@ -538,6 +549,11 @@ export async function handleRemoteSessionPublish(
|
|
|
538
549
|
"Remote session host is not reachable for this control event",
|
|
539
550
|
);
|
|
540
551
|
}
|
|
552
|
+
if (message.event.type === "approval.resolve" && !membership) {
|
|
553
|
+
throw new Error(
|
|
554
|
+
"Durable Remote membership authority is required before forwarding an approval",
|
|
555
|
+
);
|
|
556
|
+
}
|
|
541
557
|
}
|
|
542
558
|
// Idempotent forward: a control event with a stable commandId runs its
|
|
543
559
|
// side effect (audit + dispatch into the host agent) AT MOST ONCE, so a
|
|
@@ -594,6 +610,13 @@ export async function handleRemoteSessionPublish(
|
|
|
594
610
|
remoteSessionId: message.remoteSessionId,
|
|
595
611
|
agentSessionId: session.agentSessionId,
|
|
596
612
|
from: clientId,
|
|
613
|
+
...(membership
|
|
614
|
+
? {
|
|
615
|
+
membershipAuthority: membership.authorityVersion,
|
|
616
|
+
sessionEpoch: membership.sessionEpoch,
|
|
617
|
+
membershipEpoch: membership.membershipEpoch,
|
|
618
|
+
}
|
|
619
|
+
: {}),
|
|
597
620
|
event: message.event,
|
|
598
621
|
});
|
|
599
622
|
reply(server, ws, message.id, "remote-session-published", {
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
persistSideEffectLedger,
|
|
21
21
|
} from "../../lib/side-effect-ledger-store.js";
|
|
22
22
|
import { operationIdempotencyKey } from "../../lib/idempotency.js";
|
|
23
|
+
import { collectToolResourceIdentifiers } from "../../lib/permission-side-effect-center.js";
|
|
23
24
|
import {
|
|
24
25
|
detectTaskType,
|
|
25
26
|
selectModelForTask,
|
|
@@ -1289,6 +1290,12 @@ export class WSAgentHandler {
|
|
|
1289
1290
|
key: se.key,
|
|
1290
1291
|
meta: {
|
|
1291
1292
|
tool: event.tool,
|
|
1293
|
+
toolUseId: event.tool_use_id || null,
|
|
1294
|
+
turnId: event.turn_id || null,
|
|
1295
|
+
resources: collectToolResourceIdentifiers(
|
|
1296
|
+
event.tool,
|
|
1297
|
+
event.args,
|
|
1298
|
+
),
|
|
1292
1299
|
idempotencyKey: operationIdempotencyKey({
|
|
1293
1300
|
tool: event.tool,
|
|
1294
1301
|
args: event.args,
|
|
@@ -1329,6 +1336,11 @@ export class WSAgentHandler {
|
|
|
1329
1336
|
currentTodoWrite = null;
|
|
1330
1337
|
if (currentSideEffectOpId) {
|
|
1331
1338
|
const err = event.error || event.result?.error || null;
|
|
1339
|
+
if (event.permission_decision) {
|
|
1340
|
+
sideEffectLedger.annotate(currentSideEffectOpId, {
|
|
1341
|
+
permissionDecision: event.permission_decision,
|
|
1342
|
+
});
|
|
1343
|
+
}
|
|
1332
1344
|
if (event.result?._diffReviewAudit) {
|
|
1333
1345
|
diffReviewFollowUps.observe(
|
|
1334
1346
|
sideEffectLedger,
|
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
isApprovalRequestEvent,
|
|
38
38
|
} from "../../harness/remote-session-push.js";
|
|
39
39
|
import { createRemoteSessionPushSender } from "../../harness/remote-session-push-senders.js";
|
|
40
|
+
import { DurableRemoteMembershipAuthority } from "../../lib/remote-membership-authority.js";
|
|
40
41
|
import { RemoteSessionRelay } from "../remote-session-relay.js";
|
|
41
42
|
import { handleRemoteSessionPublish } from "./remote-session-protocol.js";
|
|
42
43
|
import { handleTaskDetail, handleTaskHistory } from "./task-protocol.js";
|
|
@@ -273,7 +274,19 @@ export class ChainlessChainWSServer extends EventEmitter {
|
|
|
273
274
|
/** Local authorization state for multi-device Remote Sessions. */
|
|
274
275
|
this.remoteSessions =
|
|
275
276
|
options.remoteSessionRegistry ||
|
|
276
|
-
new RemoteSessionRegistry({
|
|
277
|
+
new RemoteSessionRegistry({
|
|
278
|
+
policy: this.remoteSessionPolicy,
|
|
279
|
+
membershipAuthority:
|
|
280
|
+
options.remoteMembershipAuthority === null
|
|
281
|
+
? null
|
|
282
|
+
: () =>
|
|
283
|
+
options.remoteMembershipAuthority ||
|
|
284
|
+
new DurableRemoteMembershipAuthority(
|
|
285
|
+
options.remoteMembershipStateFile
|
|
286
|
+
? { filePath: options.remoteMembershipStateFile }
|
|
287
|
+
: {},
|
|
288
|
+
),
|
|
289
|
+
});
|
|
277
290
|
/**
|
|
278
291
|
* Optional durable sink (JSONL) for the audit trail. Enabled only when a
|
|
279
292
|
* sink is injected or CHAINLESSCHAIN_REMOTE_SESSION_AUDIT_FILE is set; the
|
|
@@ -502,16 +515,36 @@ export class ChainlessChainWSServer extends EventEmitter {
|
|
|
502
515
|
// remaining clients finalizes itself).
|
|
503
516
|
cleanupBgAttachments(client);
|
|
504
517
|
this.clients.delete(clientId);
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
518
|
+
try {
|
|
519
|
+
for (const affected of this.remoteSessions.removeClient(clientId)) {
|
|
520
|
+
if (affected.closed)
|
|
521
|
+
this.remoteSessionCrypto.delete(affected.sessionId);
|
|
522
|
+
if (affected.closed)
|
|
523
|
+
this.remoteSessionPairingSecrets.delete(affected.sessionId);
|
|
524
|
+
this.remoteSessionAudit?.record({
|
|
525
|
+
sessionId: affected.sessionId,
|
|
526
|
+
actor: clientId,
|
|
527
|
+
action: affected.closed ? "session.closed" : "device.disconnected",
|
|
528
|
+
detail: { reason: "disconnect" },
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
} catch (error) {
|
|
532
|
+
// A durable membership transition that cannot be committed must never
|
|
533
|
+
// be represented as a successful revoke/close. The socket is already
|
|
534
|
+
// gone (so this principal cannot send another frame), and every future
|
|
535
|
+
// durable authorization still re-checks the authority store.
|
|
510
536
|
this.remoteSessionAudit?.record({
|
|
511
|
-
sessionId:
|
|
537
|
+
sessionId: null,
|
|
512
538
|
actor: clientId,
|
|
513
|
-
action:
|
|
514
|
-
detail: {
|
|
539
|
+
action: "membership.state-error",
|
|
540
|
+
detail: {
|
|
541
|
+
reason: "disconnect-transition-failed",
|
|
542
|
+
errorCode: error?.code || null,
|
|
543
|
+
},
|
|
544
|
+
});
|
|
545
|
+
this.emit("client-error", {
|
|
546
|
+
clientId,
|
|
547
|
+
error: error?.message || String(error),
|
|
515
548
|
});
|
|
516
549
|
}
|
|
517
550
|
this.emit("disconnection", { clientId });
|
|
@@ -539,11 +572,12 @@ export class ChainlessChainWSServer extends EventEmitter {
|
|
|
539
572
|
return this._dispatcher.dispatch(clientId, ws, message);
|
|
540
573
|
}
|
|
541
574
|
|
|
542
|
-
/** Read the same
|
|
575
|
+
/** Read the same static + scoped authority used by the Agent Core. */
|
|
543
576
|
async _handlePermissionRulesGet(id, ws) {
|
|
544
577
|
try {
|
|
545
|
-
const {
|
|
546
|
-
|
|
578
|
+
const { loadPermissionAuthority } =
|
|
579
|
+
await import("../../lib/permission-authority.js");
|
|
580
|
+
const loaded = loadPermissionAuthority({ cwd: this.projectRoot });
|
|
547
581
|
this._send(ws, {
|
|
548
582
|
id,
|
|
549
583
|
type: "permission-rules",
|
|
@@ -551,6 +585,8 @@ export class ChainlessChainWSServer extends EventEmitter {
|
|
|
551
585
|
sources: loaded.sources,
|
|
552
586
|
files: loaded.files,
|
|
553
587
|
managed: loaded.managed || null,
|
|
588
|
+
managedFile: loaded.managedFile || null,
|
|
589
|
+
scoped: loaded.scoped || null,
|
|
554
590
|
});
|
|
555
591
|
} catch (error) {
|
|
556
592
|
this._send(ws, {
|