chainlesschain 0.162.188 → 0.162.193
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -11
- package/bin/chainlesschain.js +7 -52
- package/completions/_cc +209 -0
- package/completions/cc.bash +18 -0
- package/completions/cc.fish +13 -0
- package/completions/cc.ps1 +226 -0
- package/package.json +10 -2
- package/src/assets/web-panel/assets/{AIOps-Brr1LVcE.js → AIOps-DBLkaTje.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-DQU74DKG.js → ActionButton-BAy-Qebo.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-CYp9178y.js → Analytics-Dfb1Mlau.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DW4SCYsW.js → AppLayout-BbFkN8m0.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-CYlD_ed1.js → Artifacts-kM4-cEEH.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CWl1rZOi.js → Audit-BSQfYWf3.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-BOR-LPsa.js → BackgroundAgents-CWDbI_fG.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-DLpG7j1X.js → Backup-BxLPbq_Q.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-B35K9wdr.js → BaseInput-DuIbdrp6.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CwUJb9gB.js → Chat-NEmjGahU.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-1v6aMS1m.js → ChatBubbleRenderer-DfJEo-5_.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-pi3-tPNW.js → Checkbox-CaoeG3Ns.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-FyNF35eL.js → Codegen-BFf_g3xY.js} +1 -1
- package/src/assets/web-panel/assets/{Col-tGt_JDEr.js → Col-CNOd8mdQ.js} +1 -1
- package/src/assets/web-panel/assets/{Community-CC7LonQX.js → Community-BhpDqz-i.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BGXrHHjE.js → Compact-CQ42T7Z6.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-DSW0TBZ8.js → Compliance-DI5PcLMN.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-Bhk7rbvE.js → Cowork-wYYZe0wR.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-DxyiQ2NZ.js → Cron-Dlq03DD_.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-B2ZkxHok.js → Crosschain-BzqS8PP3.js} +1 -1
- package/src/assets/web-panel/assets/{DID-yOJV99eJ.js → DID-It55Yem7.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-CKsttz7D.js → Dashboard-9HkH6oxn.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-CVFldXSL.js → Dropdown-00e2YWRB.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-Bufv638J.js → EmailListRenderer-By-ugRDL.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-4ncjoIjL.js → FamilyGuardDashboard-C396yu5m.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-DsknEDoX.js → Federation-BME5sbZY.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-Cqe5jWXA.js → FormItemContext-B4TEZCr-.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-NAJaFKxc.js → GenericCardRenderer-_9CX9ieY.js} +1 -1
- package/src/assets/web-panel/assets/{Git-CszKQpnl.js → Git-BrS6WVSr.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BXGodXi6.js → Governance-BMdCWnKF.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CkoYuG2c.js → Inference-Bcp3vzcA.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-DFlEr_T0.js → KnowledgeGraph-DlLuqGY5.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CVaENddA.js → Logs-D-W_6x09.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-DElGPxCZ.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-CDlLT0fw.js → Marketplace-Dzn2guvI.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DdwOyszN.js → McpTools-uPict-KL.js} +6 -6
- package/src/assets/web-panel/assets/{Memory-DKQnkKuG.js → Memory-BCw43kOb.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-DGseqlzJ.js → MobileBridge-DmV8Wv7F.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-COBbEOlj.js → MobileProjects-C-HaCmSM.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-O61Vwyli.js → Mtc-C6jxJ34Y.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-Dw2SyasS.js → MtcAudit-Za8ExwhQ.js} +5 -5
- package/src/assets/web-panel/assets/{Multisig-hSu_l8kf.js → Multisig-KKDbuEgb.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-CX1Epurr.js → NLProgramming-Dj97zbCk.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-R9xX8o8_.js → Notes-DBXvMraU.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-jtSNLCuK.js → NotificationSettings-DOxITLYl.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-7DVjZwMM.js +1 -0
- package/src/assets/web-panel/assets/{Organization-Pu2WO-U3.js → Organization-D1i73mjb.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-BjnqUyFp.js → Overflow-kW6Q3rvg.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-jjkvz44c.js → P2P-C-v_8p2v.js} +2 -2
- package/src/assets/web-panel/assets/PdhVaultBrowser-tUbbY64W.js +7 -0
- package/src/assets/web-panel/assets/{Permissions-D4yDpivd.js → Permissions-DkHxEZ58.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-0qsL6iH1.js → PersonalDataHub-DWuMPGrK.js} +5 -5
- package/src/assets/web-panel/assets/{Pipeline-Cx7Ybrk2.js → Pipeline-30IYXWWm.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-PbfR_M_V.js → Privacy-DZNQ4RrH.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-CyV6Gsub.js → ProjectInit-De2MCElf.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-C7KZ2Wdk.js → ProjectSettings-5uHk9wsC.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-DQDjO-yK.js → Projects-XjDfrFLb.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-DyFVBBMX.js → Providers-Bgwj6gcE.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-CzB1BC9_.js → QrScannerModal-gKql9umv.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-Bk636mC1.js → QuickAsk-BWvmwkh7.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DoWxHIT3.js → Recommend-Uok4hZPd.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-oOVIv9wq.js → RemoteSession-DLJzTk9a.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-BucoReGG.js → Reputation-ZVwIPMSO.js} +1 -1
- package/src/assets/web-panel/assets/{Row-DzmOdJU7.js → Row-CN04HxWR.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-C1tK7KGU.js → RssFeed-BdSrEG4g.js} +3 -3
- package/src/assets/web-panel/assets/{Search-CSnInOqk.js → Search-5PwVd0IR.js} +1 -1
- package/src/assets/web-panel/assets/{Security-dlejr15l.js → Security-DdBo4zjN.js} +3 -3
- package/src/assets/web-panel/assets/{Services-BioPZuNh.js → Services-D3letU7M.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DWMibwpC.js → Skeleton--Jb83f1v.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-BAAnx1B2.js → Skills-Bg-CulHX.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-jWNp4hNO.js → Sla-7QOa7S-X.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-y5kqKha-.js → SpeechSettings-DQwppjRw.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-B9GNsc3e.js → SyncSettings-dNPQGL-s.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-BDBYKRen.js → Tasks-Ggs-Z48q.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-DRiE5eaN.js → Templates-78TYHgRO.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-BGlAvExF.js → Tenant-xHwwv9vO.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-B8uzrbNY.js → Terminal-BJXSJfm4.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-Df48iveY.js → TimelineRenderer-fLbjRhJw.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-CcmHndN6.js → Tokens-oMSBSBmB.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-DPkWxmQ2.js → Trigger-CfnY_wX_.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DTb5a5AV.js → Trust-AdyTgYKO.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CBmg5vch.js → UkeySign-C5K_81dS.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-B0mZrz4O.js → VideoEditing-vcGVDqki.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-Bxs7_mpd.js → Wallet-hhOc3hlY.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-C8x3cMxU.js → WebAuthn-CVloC11s.js} +3 -3
- package/src/assets/web-panel/assets/{WorkflowEditor-DPrNznrP.js → WorkflowEditor-CYeE32R5.js} +1 -1
- package/src/assets/web-panel/assets/{chat-D3bYWu7S.js → chat-CNROR5bN.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DY-PwMu4.js → colors-Cjx-cnwU.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-LDk10Kw6.js → compact-item-DOIfelvD.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-C-2MZnFq.js → createContext-DfA7UZ8u.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-ChcCBGs7.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-BQIBjcnB.js → hasIn-BMSCzcfM.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQVb2dWp.js → index-5-HXgOX5.js} +1 -1
- package/src/assets/web-panel/assets/{index-BdXnYMCZ.js → index-AWg-0M1S.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cx6D_dx2.js → index-B4iYzpkL.js} +1 -1
- package/src/assets/web-panel/assets/{index-_HRO_cIu.js → index-B5Udeb_6.js} +1 -1
- package/src/assets/web-panel/assets/{index-DlRYqt3S.js → index-B7gf77CJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BrnRO9yE.js → index-BEMwBBHk.js} +1 -1
- package/src/assets/web-panel/assets/{index-VCh5zNJo.js → index-BM1y_9hM.js} +1 -1
- package/src/assets/web-panel/assets/{index-BRI3ngNg.js → index-BUonmKSE.js} +1 -1
- package/src/assets/web-panel/assets/{index-C3GNvExG.js → index-BbQ2eQ8H.js} +1 -1
- package/src/assets/web-panel/assets/{index-DSvo_bp0.js → index-BemJ2u_E.js} +1 -1
- package/src/assets/web-panel/assets/{index-L6qixyLc.js → index-BolaOQxx.js} +1 -1
- package/src/assets/web-panel/assets/{index-BI4KgcYC.js → index-BxOk9vkG.js} +1 -1
- package/src/assets/web-panel/assets/{index-CY4KnaO9.js → index-By61ojUx.js} +1 -1
- package/src/assets/web-panel/assets/{index-L3smcoQX.js → index-C2K9SNVX.js} +1 -1
- package/src/assets/web-panel/assets/{index-BX2b9Orc.js → index-C3L5gdiD.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cz4b6Z_7.js → index-C7xn0Nub.js} +1 -1
- package/src/assets/web-panel/assets/{index-COG61sRv.js → index-CAnvhwg6.js} +1 -1
- package/src/assets/web-panel/assets/{index-C7FC8cP2.js → index-CEKMcOyU.js} +1 -1
- package/src/assets/web-panel/assets/{index-BN-xdSWZ.js → index-CNC5onm4.js} +1 -1
- package/src/assets/web-panel/assets/{index-DY2FIrmz.js → index-CVL27kXC.js} +1 -1
- package/src/assets/web-panel/assets/{index-CiTvBAr-.js → index-CVm1_i3t.js} +1 -1
- package/src/assets/web-panel/assets/{index-DhRt9cYJ.js → index-CdYBye8B.js} +1 -1
- package/src/assets/web-panel/assets/{index-B5pgtZnY.js → index-ClNMrqEY.js} +1 -1
- package/src/assets/web-panel/assets/{index-7xKu7Fns.js → index-Cs6l7uRu.js} +1 -1
- package/src/assets/web-panel/assets/{index-D4K1weKc.js → index-CshQbilz.js} +1 -1
- package/src/assets/web-panel/assets/{index-k7C_oDCO.js → index-Cyweh0Hy.js} +1 -1
- package/src/assets/web-panel/assets/{index-D3Oq-DLL.js → index-DBpWXFed.js} +3 -3
- package/src/assets/web-panel/assets/{index-DYyLJPlF.js → index-DHtpHZAQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dh-tkpKQ.js → index-DLmn0BoK.js} +1 -1
- package/src/assets/web-panel/assets/{index-8JC9BJa1.js → index-DPAWBrMf.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dd2Km97U.js → index-DjEsxO5h.js} +1 -1
- package/src/assets/web-panel/assets/{index-KFZO_lcx.js → index-FBc_CJBd.js} +1 -1
- package/src/assets/web-panel/assets/{index-DTIZpPtG.js → index-Icdoqmzt.js} +1 -1
- package/src/assets/web-panel/assets/index-Q2IajL54.js +1 -0
- package/src/assets/web-panel/assets/index-bRkHgOMc.js +1 -0
- package/src/assets/web-panel/assets/{index-lmm9p-jm.js → index-dCd8cSUq.js} +1 -1
- package/src/assets/web-panel/assets/{index-HasPt4-h.js → index-m2vG9gG_.js} +1 -1
- package/src/assets/web-panel/assets/{index-CaslYch6.js → index-mTpHoEzr.js} +1 -1
- package/src/assets/web-panel/assets/{index-CbR6ROOa.js → index-ti_lnTWl.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-zQPSHf2C.js → initDefaultProps-Bu8k7H1Y.js} +1 -1
- package/src/assets/web-panel/assets/{motion-CKCStGVk.js → motion-s3iVK41k.js} +1 -1
- package/src/assets/web-panel/assets/{move-BufVDGYF.js → move-B6B-E5Jz.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-DcaFxy5D.js → mtc-parser-BiYgTidA.js} +1 -1
- package/src/assets/web-panel/assets/{omit-EScpkGdo.js → omit-pU1RdUDA.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-72hG_qfT.js → pickAttrs-Cdoq_SeM.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-CMFWiH20.js → placementArrow-DIuvAn2K.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-DKQHS41p.js → responsiveObserve-8w16YR2D.js} +1 -1
- package/src/assets/web-panel/assets/{slide-QVAFHTIQ.js → slide-VZ01cZe3.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-DIz38e2G.js → statusUtils-lh8YMN8Z.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-zK5cyLby.js → styleChecker-CmDyreec.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-DhZngk62.js → useFlexGapSupport-hiJWMU5y.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-BvV2cvkg.js → useFs-Thnu-Iaj.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-CRmxb9l3.js → usePersonalDataHub-LBdOxjwY.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-CgQIbobP.js → vnode-Cg6lFY_X.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-D4XrrO0R.js → zoom-DVfsR1YO.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/cli-help.js +181 -0
- package/src/command-help-index.json +181 -0
- package/src/command-manifest.json +1107 -175
- package/src/command-surface-policy.js +197 -0
- package/src/commands/agent.js +98 -33
- package/src/commands/artifacts.js +400 -2
- package/src/commands/background-session.js +41 -3
- package/src/commands/checkpoint-managed.js +1059 -0
- package/src/commands/checkpoint-restore-recovery.js +1476 -0
- package/src/commands/checkpoint.js +950 -22
- package/src/commands/compact.js +101 -25
- package/src/commands/config.js +506 -20
- package/src/commands/doctor.js +4 -1
- package/src/commands/hub.js +1 -1
- package/src/commands/mcp.js +688 -24
- package/src/commands/pack.js +16 -2
- package/src/commands/plugin.js +20 -12
- package/src/commands/session-mcp-recovery.js +218 -0
- package/src/commands/session.js +470 -110
- package/src/commands/setup.js +36 -10
- package/src/commands/skill.js +181 -110
- package/src/commands/status.js +21 -5
- package/src/commands/team-distributed.js +3324 -0
- package/src/commands/team.js +1130 -74
- package/src/commands/update.js +68 -6
- package/src/constants.js +11 -0
- package/src/data/changelog.json +26 -0
- package/src/gateways/ws/action-protocol.js +10 -0
- package/src/gateways/ws/session-protocol.js +555 -27
- package/src/gateways/ws/ws-agent-handler.js +541 -14
- package/src/gateways/ws/ws-session-gateway.js +129 -22
- package/src/gateways/ws/ws-session-state.js +431 -0
- package/src/harness/background-task-manager.js +233 -36
- package/src/harness/jsonl-session-store.js +2551 -167
- package/src/harness/mcp-client.js +802 -61
- package/src/harness/prompt-compressor.js +227 -27
- package/src/harness/session-index.js +89 -38
- package/src/harness/session-list-index.js +254 -0
- package/src/harness/structured-handoff.js +410 -0
- package/src/lazy-dispatch.js +747 -84
- package/src/lib/__tests__/logger.test.js +50 -2
- package/src/lib/advisor-runtime.js +1047 -0
- package/src/lib/agent-core.js +2 -0
- package/src/lib/agent-sandbox.js +120 -26
- package/src/lib/agent-session-export.js +20 -0
- package/src/lib/agent-team/task-lease.js +271 -3
- package/src/lib/agent-team/team-adjudication.js +1501 -0
- package/src/lib/agent-team/team-budget.js +4 -1
- package/src/lib/agent-team/team-control-store.js +582 -0
- package/src/lib/agent-team/team-distributed-queue.js +5246 -0
- package/src/lib/agent-team/team-process-checkpoint.js +211 -0
- package/src/lib/agent-team/team-runner.js +543 -24
- package/src/lib/agent-team/team-worktree.js +1403 -95
- package/src/lib/artifact-store.js +131 -8
- package/src/lib/background-agent-supervisor.js +185 -13
- package/src/lib/background-interaction-journal.js +37 -9
- package/src/lib/background-launch-profile.js +1058 -0
- package/src/lib/checkpoint-restore-already-completed-controller.js +902 -0
- package/src/lib/checkpoint-restore-orchestrator.js +987 -0
- package/src/lib/checkpoint-restore-partial-rollback-controller.js +1953 -0
- package/src/lib/checkpoint-restore-recovery-controller.js +689 -0
- package/src/lib/checkpoint-restore-recovery.js +884 -0
- package/src/lib/checkpoint-restore-retention.js +126 -0
- package/src/lib/checkpoint-restore-saga.js +5079 -0
- package/src/lib/checkpoint-restore-session-recovery.js +1178 -0
- package/src/lib/checkpoint-restore-workspace-target-verifier.js +270 -0
- package/src/lib/checkpoint-store.js +1688 -97
- package/src/lib/checkpoint-timeline-authority.js +522 -0
- package/src/lib/checkpoint-timeline.js +642 -0
- package/src/lib/config-keys.js +18 -119
- package/src/lib/config-manager.js +446 -27
- package/src/lib/config-redaction.js +57 -0
- package/src/lib/config-schema.js +853 -0
- package/src/lib/cowork-mcp-tools.js +5 -0
- package/src/lib/cowork-task-runner.js +458 -63
- package/src/lib/delivery-coordinator.js +1234 -0
- package/src/lib/delivery-evidence.js +450 -0
- package/src/lib/doctor-checkup.js +199 -14
- package/src/lib/executable-path.js +34 -0
- package/src/lib/fatal-handler.js +16 -0
- package/src/lib/file-checkpoint.js +4909 -186
- package/src/lib/file-lines.js +125 -0
- package/src/lib/headless-config-command.js +16 -5
- package/src/lib/hook-runner.cjs +139 -38
- package/src/lib/hooks-v2-workspace-context.js +10 -0
- package/src/lib/impacted-gate-selector.js +424 -0
- package/src/lib/interaction-adapter.js +62 -0
- package/src/lib/jsonl-session-store.js +1 -35
- package/src/lib/logger.js +66 -14
- package/src/lib/managed-checkpoint-render.js +60 -0
- package/src/lib/managed-tool-checkpoint.js +194 -0
- package/src/lib/mcp-call-ledger-store.js +1069 -0
- package/src/lib/mcp-call-ledger.js +747 -0
- package/src/lib/mcp-client.js +5 -0
- package/src/lib/mcp-conflict-scheduler.js +468 -0
- package/src/lib/mcp-effect-contract.js +102 -0
- package/src/lib/mcp-headers-helper-trust.js +145 -0
- package/src/lib/mcp-headers-helper.js +616 -0
- package/src/lib/mcp-host-recovery-runtime.js +131 -0
- package/src/lib/mcp-ledger-recovery-admission.js +1065 -0
- package/src/lib/mcp-recovery-adjudication.js +443 -0
- package/src/lib/output-context.js +86 -0
- package/src/lib/packer/file-identity.js +170 -0
- package/src/lib/packer/index.js +3 -0
- package/src/lib/packer/native-update-state.js +277 -0
- package/src/lib/packer/pack-update-applier.js +1983 -136
- package/src/lib/packer/pack-update-checker.js +34 -0
- package/src/lib/packer/pack-update-downloader.js +875 -86
- package/src/lib/packer/pack-update-signature.js +86 -0
- package/src/lib/packer/pkg-config-generator.js +6 -0
- package/src/lib/paths.js +65 -10
- package/src/lib/plan-mode.js +831 -14
- package/src/lib/plan-persistence.js +540 -0
- package/src/lib/plugin-runtime/hooks.js +227 -69
- package/src/lib/plugin-runtime/plugin-options.js +189 -44
- package/src/lib/pr-automation-policy.js +146 -8
- package/src/lib/process-execution-broker/credential-agent.js +7 -0
- package/src/lib/process-execution-broker/index.js +491 -13
- package/src/lib/process-execution-broker/linux-generic-bwrap-runtime.js +28 -1
- package/src/lib/process-execution-broker/linux-generic-bwrap.js +28 -4
- package/src/lib/process-execution-broker/platform-sandbox.js +92 -70
- 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 +284 -19
- package/src/lib/process-execution-broker/workspace-transaction.js +4459 -0
- package/src/lib/project-instructions.js +165 -29
- package/src/lib/project-mcp-trust.js +67 -0
- package/src/lib/public-ide-capability-manifest.js +272 -0
- package/src/lib/public-ide-capability-validation.js +351 -0
- package/src/lib/secret-store.js +267 -43
- package/src/lib/secure-file-identity.js +433 -0
- package/src/lib/secure-fs.js +1089 -0
- package/src/lib/security-audit.js +58 -0
- package/src/lib/service-manager.js +34 -13
- package/src/lib/session-budget-runtime.js +1452 -0
- package/src/lib/session-host-snapshot.js +388 -0
- package/src/lib/session-message-provenance.js +429 -0
- package/src/lib/session-projection.js +804 -0
- package/src/lib/session-resource-budget.js +1495 -0
- package/src/lib/settings-hooks.cjs +138 -22
- package/src/lib/settings-loader.cjs +25 -2
- package/src/lib/side-effect-ledger-store.js +45 -23
- package/src/lib/skill-execution-identity.js +217 -0
- package/src/lib/skill-loader.js +299 -18
- package/src/lib/sub-agent-context.js +236 -28
- package/src/lib/sub-agent-registry.js +5 -0
- package/src/lib/subagent-contract.js +94 -0
- package/src/lib/todo-manager.js +185 -18
- package/src/lib/todo-persistence.js +417 -0
- package/src/lib/turn-binding-store.js +41 -23
- package/src/lib/turn-binding.js +160 -2
- package/src/lib/with-file-lock.js +165 -24
- package/src/lib/ws-chat-handler.js +21 -0
- package/src/program-base.js +18 -0
- package/src/repl/advisor-command.js +103 -0
- package/src/repl/agent-repl.js +2175 -146
- package/src/repl/btw-command.js +93 -10
- package/src/repl/clipboard-image.js +119 -0
- package/src/repl/config-summary.js +64 -108
- package/src/repl/prompt-editor.js +233 -0
- package/src/repl/prompt-interactions.js +344 -0
- package/src/repl/prompt-stash.js +354 -0
- package/src/repl/prompt-suggestions.js +312 -0
- package/src/repl/repl-keybindings.js +227 -0
- package/src/repl/session-recap.js +217 -0
- package/src/repl/slash-command-registry.js +22 -0
- package/src/repl/terminal-layout.js +88 -0
- package/src/runtime/agent-core.js +1630 -447
- package/src/runtime/coding-agent-contract-shared.cjs +13 -1
- package/src/runtime/coding-agent-managed-tool-policy.cjs +7 -2
- package/src/runtime/diagnostics.js +32 -13
- package/src/runtime/headless-runner.js +310 -118
- package/src/runtime/headless-stream.js +356 -95
- package/src/runtime/mcp-config.js +148 -14
- package/src/runtime/policies/agent-policy.js +14 -0
- package/src/runtime/status-diagnostics-lite.js +137 -0
- package/src/assets/web-panel/assets/MarkdownRenderer-7iWGwZ-r.js +0 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-BU2Yqq5H.js +0 -1
- package/src/assets/web-panel/assets/PdhVaultBrowser-69ca_WeR.js +0 -7
- package/src/assets/web-panel/assets/devWarning-B4dXIJqD.js +0 -1
- package/src/assets/web-panel/assets/index-C-C7DaG6.js +0 -1
- package/src/assets/web-panel/assets/index-DkfWzWtd.js +0 -1
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
import { randomUUID as nodeRandomUUID } from "node:crypto";
|
|
2
|
+
import { appendAuthorityEventIfHead as storeAppendAuthorityEventIfHead } from "../harness/jsonl-session-store.js";
|
|
3
|
+
import {
|
|
4
|
+
MCP_CALL_RECOVERY_ADJUDICATION_EVENT,
|
|
5
|
+
MCP_CALL_RECOVERY_ADJUDICATION_SCHEMA_VERSION,
|
|
6
|
+
MCP_CALL_RECOVERY_AUTHORITY,
|
|
7
|
+
MCP_CALL_RECOVERY_CONFIRMATION,
|
|
8
|
+
McpCallRecoveryDecision,
|
|
9
|
+
deriveMcpExactReplayDenies,
|
|
10
|
+
loadMcpLedgerRecovery,
|
|
11
|
+
} from "./mcp-call-ledger-store.js";
|
|
12
|
+
import {
|
|
13
|
+
MCP_CALL_LEDGER_PROTOCOL_LIMITS,
|
|
14
|
+
normalizeMcpLedgerProtocolText,
|
|
15
|
+
sha256PayloadDigest,
|
|
16
|
+
snapshotMcpJsonRpcInput,
|
|
17
|
+
} from "./mcp-call-ledger.js";
|
|
18
|
+
|
|
19
|
+
const PAYLOAD_DIGEST = /^sha256:[0-9a-f]{64}$/;
|
|
20
|
+
const RAW_AUTHORITY_HASH = /^[0-9a-f]{64}$/;
|
|
21
|
+
const MAX_REASON_LENGTH = 4096;
|
|
22
|
+
const MCP_EFFECTS = new Set(["read", "unknown", "write", "destructive"]);
|
|
23
|
+
const MCP_RECOVERY_REMEDIATIONS = new Set([
|
|
24
|
+
"inspect_transcript",
|
|
25
|
+
"adjudicate_started_calls",
|
|
26
|
+
"exact_replay_denied",
|
|
27
|
+
]);
|
|
28
|
+
const PUBLIC_REPLAY_DENY_FIELDS = new Set([
|
|
29
|
+
"ledgerId",
|
|
30
|
+
"serverName",
|
|
31
|
+
"toolName",
|
|
32
|
+
"inputBytes",
|
|
33
|
+
"replayDigest",
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
export class McpRecoveryAdjudicationError extends Error {
|
|
37
|
+
constructor(code, message, options = {}) {
|
|
38
|
+
super(message, options.cause ? { cause: options.cause } : undefined);
|
|
39
|
+
this.name = "McpRecoveryAdjudicationError";
|
|
40
|
+
this.code = code;
|
|
41
|
+
this.sessionId = options.sessionId || null;
|
|
42
|
+
this.ledgerId = options.ledgerId || null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function canonicalLedgerId(value) {
|
|
47
|
+
if (typeof value !== "string") return null;
|
|
48
|
+
const normalized = normalizeMcpLedgerProtocolText(
|
|
49
|
+
value,
|
|
50
|
+
null,
|
|
51
|
+
MCP_CALL_LEDGER_PROTOCOL_LIMITS.ledgerId,
|
|
52
|
+
);
|
|
53
|
+
return normalized === value ? normalized : null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function canonicalIdentifier(value) {
|
|
57
|
+
if (typeof value !== "string") return null;
|
|
58
|
+
const normalized = normalizeMcpLedgerProtocolText(
|
|
59
|
+
value,
|
|
60
|
+
null,
|
|
61
|
+
MCP_CALL_LEDGER_PROTOCOL_LIMITS.identifier,
|
|
62
|
+
);
|
|
63
|
+
return normalized === value ? normalized : null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function requireDigest(value, label, pattern, options = {}) {
|
|
67
|
+
if (typeof value === "string" && pattern.test(value)) return value;
|
|
68
|
+
throw new McpRecoveryAdjudicationError(
|
|
69
|
+
"CC_MCP_RECOVERY_ADJUDICATION_INPUT_INVALID",
|
|
70
|
+
`${label} has an invalid digest format`,
|
|
71
|
+
options,
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function requireDecision(value, options = {}) {
|
|
76
|
+
if (Object.values(McpCallRecoveryDecision).includes(value)) return value;
|
|
77
|
+
throw new McpRecoveryAdjudicationError(
|
|
78
|
+
"CC_MCP_RECOVERY_ADJUDICATION_INPUT_INVALID",
|
|
79
|
+
"MCP recovery decision must be confirmed_applied or confirmed_not_applied",
|
|
80
|
+
options,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function requireReason(value, options = {}) {
|
|
85
|
+
if (typeof value !== "string") {
|
|
86
|
+
throw new McpRecoveryAdjudicationError(
|
|
87
|
+
"CC_MCP_RECOVERY_ADJUDICATION_INPUT_INVALID",
|
|
88
|
+
"MCP recovery adjudication requires a reason",
|
|
89
|
+
options,
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
const reason = value.trim();
|
|
93
|
+
if (!reason || reason.length > MAX_REASON_LENGTH) {
|
|
94
|
+
throw new McpRecoveryAdjudicationError(
|
|
95
|
+
"CC_MCP_RECOVERY_ADJUDICATION_INPUT_INVALID",
|
|
96
|
+
`MCP recovery reason must contain 1-${MAX_REASON_LENGTH} characters`,
|
|
97
|
+
options,
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
return reason;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function readMcpRecoveryAuthority(sessionId, dependencies = {}) {
|
|
104
|
+
try {
|
|
105
|
+
return loadMcpLedgerRecovery(sessionId, {
|
|
106
|
+
...(Object.prototype.hasOwnProperty.call(
|
|
107
|
+
dependencies,
|
|
108
|
+
"readVerifiedProjection",
|
|
109
|
+
)
|
|
110
|
+
? { readVerifiedProjection: dependencies.readVerifiedProjection }
|
|
111
|
+
: {}),
|
|
112
|
+
...(Object.prototype.hasOwnProperty.call(
|
|
113
|
+
dependencies,
|
|
114
|
+
"readVerifiedEvents",
|
|
115
|
+
)
|
|
116
|
+
? { readVerifiedEvents: dependencies.readVerifiedEvents }
|
|
117
|
+
: {}),
|
|
118
|
+
});
|
|
119
|
+
} catch (cause) {
|
|
120
|
+
throw new McpRecoveryAdjudicationError(
|
|
121
|
+
"CC_MCP_RECOVERY_ADJUDICATION_UNVERIFIED",
|
|
122
|
+
"MCP recovery adjudication requires a fully verified transcript",
|
|
123
|
+
{ sessionId, cause },
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function publicMcpRecoveryAuthority(sessionId, recovery) {
|
|
129
|
+
let snapshot;
|
|
130
|
+
try {
|
|
131
|
+
snapshot = snapshotMcpJsonRpcInput(recovery);
|
|
132
|
+
} catch (cause) {
|
|
133
|
+
throw new McpRecoveryAdjudicationError(
|
|
134
|
+
"CC_MCP_RECOVERY_ADJUDICATION_UNVERIFIED",
|
|
135
|
+
"MCP recovery authority is not strict synchronous plain data",
|
|
136
|
+
{ sessionId, cause },
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
const canonicalSessionId = canonicalIdentifier(sessionId);
|
|
140
|
+
if (
|
|
141
|
+
!canonicalSessionId ||
|
|
142
|
+
!snapshot ||
|
|
143
|
+
Array.isArray(snapshot) ||
|
|
144
|
+
snapshot.verified !== true ||
|
|
145
|
+
snapshot.sessionId !== canonicalSessionId ||
|
|
146
|
+
!Array.isArray(snapshot.unsettled) ||
|
|
147
|
+
!Array.isArray(snapshot.incidents) ||
|
|
148
|
+
!Array.isArray(snapshot.adjudications) ||
|
|
149
|
+
!Array.isArray(snapshot.replayDenied) ||
|
|
150
|
+
(snapshot.headHash !== null &&
|
|
151
|
+
!RAW_AUTHORITY_HASH.test(String(snapshot.headHash || ""))) ||
|
|
152
|
+
!PAYLOAD_DIGEST.test(String(snapshot.recoveryDigest || "")) ||
|
|
153
|
+
(snapshot.remediation !== null &&
|
|
154
|
+
!MCP_RECOVERY_REMEDIATIONS.has(snapshot.remediation))
|
|
155
|
+
) {
|
|
156
|
+
throw new McpRecoveryAdjudicationError(
|
|
157
|
+
"CC_MCP_RECOVERY_ADJUDICATION_UNVERIFIED",
|
|
158
|
+
"MCP recovery authority projection is malformed",
|
|
159
|
+
{ sessionId: canonicalSessionId || null },
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const invalidProjection = () => {
|
|
164
|
+
throw new McpRecoveryAdjudicationError(
|
|
165
|
+
"CC_MCP_RECOVERY_ADJUDICATION_UNVERIFIED",
|
|
166
|
+
"MCP recovery authority contains malformed public fields",
|
|
167
|
+
{ sessionId: canonicalSessionId },
|
|
168
|
+
);
|
|
169
|
+
};
|
|
170
|
+
const unsettled = snapshot.unsettled.map((record) => {
|
|
171
|
+
const ledgerId = canonicalLedgerId(record?.ledgerId);
|
|
172
|
+
const serverName = canonicalIdentifier(record?.serverName);
|
|
173
|
+
const toolName = canonicalIdentifier(record?.toolName);
|
|
174
|
+
const effect = record?.effectContract?.effect;
|
|
175
|
+
if (
|
|
176
|
+
!ledgerId ||
|
|
177
|
+
!serverName ||
|
|
178
|
+
!toolName ||
|
|
179
|
+
!MCP_EFFECTS.has(effect) ||
|
|
180
|
+
record?.status !== "started"
|
|
181
|
+
) {
|
|
182
|
+
return invalidProjection();
|
|
183
|
+
}
|
|
184
|
+
return Object.freeze({
|
|
185
|
+
ledgerId,
|
|
186
|
+
serverName,
|
|
187
|
+
toolName,
|
|
188
|
+
effect,
|
|
189
|
+
status: "outcome_unknown",
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
const incidents = snapshot.incidents.map((incident) => {
|
|
193
|
+
const code = canonicalIdentifier(incident?.code);
|
|
194
|
+
const ledgerId =
|
|
195
|
+
incident?.ledgerId === null
|
|
196
|
+
? null
|
|
197
|
+
: canonicalLedgerId(incident?.ledgerId);
|
|
198
|
+
if (!code || (incident?.ledgerId !== null && !ledgerId)) {
|
|
199
|
+
return invalidProjection();
|
|
200
|
+
}
|
|
201
|
+
return Object.freeze({ code, ledgerId });
|
|
202
|
+
});
|
|
203
|
+
const replayDenied = snapshot.replayDenied.map((entry) => {
|
|
204
|
+
const fields = Object.keys(entry || {});
|
|
205
|
+
const ledgerId = canonicalLedgerId(entry?.ledgerId);
|
|
206
|
+
const serverName = canonicalIdentifier(entry?.serverName);
|
|
207
|
+
const toolName = canonicalIdentifier(entry?.toolName);
|
|
208
|
+
if (
|
|
209
|
+
fields.length !== PUBLIC_REPLAY_DENY_FIELDS.size ||
|
|
210
|
+
fields.some((field) => !PUBLIC_REPLAY_DENY_FIELDS.has(field)) ||
|
|
211
|
+
!ledgerId ||
|
|
212
|
+
!serverName ||
|
|
213
|
+
!toolName ||
|
|
214
|
+
!Number.isSafeInteger(entry?.inputBytes) ||
|
|
215
|
+
entry.inputBytes < 0 ||
|
|
216
|
+
!PAYLOAD_DIGEST.test(String(entry?.replayDigest || ""))
|
|
217
|
+
) {
|
|
218
|
+
return invalidProjection();
|
|
219
|
+
}
|
|
220
|
+
return Object.freeze({
|
|
221
|
+
ledgerId,
|
|
222
|
+
serverName,
|
|
223
|
+
toolName,
|
|
224
|
+
inputBytes: entry.inputBytes,
|
|
225
|
+
replayDigest: entry.replayDigest,
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
const adjudications = snapshot.adjudications.map((entry) => {
|
|
229
|
+
const requestId = canonicalIdentifier(entry?.requestId);
|
|
230
|
+
const ledgerId = canonicalLedgerId(entry?.ledgerId);
|
|
231
|
+
if (
|
|
232
|
+
!requestId ||
|
|
233
|
+
!ledgerId ||
|
|
234
|
+
!Object.values(McpCallRecoveryDecision).includes(entry?.decision) ||
|
|
235
|
+
entry?.authority !== MCP_CALL_RECOVERY_AUTHORITY ||
|
|
236
|
+
entry?.confirmation !== MCP_CALL_RECOVERY_CONFIRMATION ||
|
|
237
|
+
!PAYLOAD_DIGEST.test(String(entry?.reasonDigest || ""))
|
|
238
|
+
) {
|
|
239
|
+
return invalidProjection();
|
|
240
|
+
}
|
|
241
|
+
return Object.freeze({
|
|
242
|
+
requestId,
|
|
243
|
+
ledgerId,
|
|
244
|
+
decision: entry.decision,
|
|
245
|
+
authority: entry.authority,
|
|
246
|
+
confirmation: entry.confirmation,
|
|
247
|
+
reasonDigest: entry.reasonDigest,
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
return Object.freeze({
|
|
251
|
+
schemaVersion: 1,
|
|
252
|
+
sessionId: canonicalSessionId,
|
|
253
|
+
verified: true,
|
|
254
|
+
headHash: snapshot.headHash,
|
|
255
|
+
recoveryDigest: snapshot.recoveryDigest,
|
|
256
|
+
blockMode:
|
|
257
|
+
incidents.length > 0 ? "all" : unsettled.length > 0 ? "unsafe" : null,
|
|
258
|
+
unsettled: Object.freeze(unsettled),
|
|
259
|
+
incidents: Object.freeze(incidents),
|
|
260
|
+
adjudications: Object.freeze(adjudications),
|
|
261
|
+
replayDenied: Object.freeze(replayDenied),
|
|
262
|
+
remediation: snapshot.remediation,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export function buildMcpRecoveryAdjudicationChallenge({
|
|
267
|
+
sessionId,
|
|
268
|
+
ledgerId,
|
|
269
|
+
decision,
|
|
270
|
+
recoveryDigest,
|
|
271
|
+
} = {}) {
|
|
272
|
+
const canonicalSessionId = canonicalIdentifier(sessionId);
|
|
273
|
+
const canonicalId = canonicalLedgerId(ledgerId);
|
|
274
|
+
const canonicalDecision = requireDecision(decision, { ledgerId });
|
|
275
|
+
const canonicalDigest = requireDigest(
|
|
276
|
+
recoveryDigest,
|
|
277
|
+
"recoveryDigest",
|
|
278
|
+
PAYLOAD_DIGEST,
|
|
279
|
+
{ ledgerId },
|
|
280
|
+
);
|
|
281
|
+
if (!canonicalSessionId || !canonicalId) {
|
|
282
|
+
throw new McpRecoveryAdjudicationError(
|
|
283
|
+
"CC_MCP_RECOVERY_ADJUDICATION_INPUT_INVALID",
|
|
284
|
+
"MCP recovery sessionId or ledgerId is invalid",
|
|
285
|
+
{ sessionId, ledgerId },
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
return (
|
|
289
|
+
`HOST STOPPED; ADJUDICATE ${canonicalSessionId} ${canonicalId} ` +
|
|
290
|
+
`${canonicalDecision} ${canonicalDigest}`
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Append exactly one human adjudication authority event under a verified-head
|
|
296
|
+
* CAS. A stale comparison is returned to the caller and is never retried.
|
|
297
|
+
*/
|
|
298
|
+
export async function adjudicateMcpRecovery(request, dependencies = {}) {
|
|
299
|
+
let safeRequest;
|
|
300
|
+
try {
|
|
301
|
+
safeRequest = snapshotMcpJsonRpcInput(request);
|
|
302
|
+
} catch (cause) {
|
|
303
|
+
throw new McpRecoveryAdjudicationError(
|
|
304
|
+
"CC_MCP_RECOVERY_ADJUDICATION_INPUT_INVALID",
|
|
305
|
+
"MCP recovery adjudication request must be strict plain data",
|
|
306
|
+
{ cause },
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
const sessionId = canonicalIdentifier(safeRequest?.sessionId);
|
|
310
|
+
const ledgerId = canonicalLedgerId(safeRequest?.ledgerId);
|
|
311
|
+
const context = {
|
|
312
|
+
sessionId,
|
|
313
|
+
ledgerId: ledgerId || null,
|
|
314
|
+
};
|
|
315
|
+
if (!sessionId || !ledgerId) {
|
|
316
|
+
throw new McpRecoveryAdjudicationError(
|
|
317
|
+
"CC_MCP_RECOVERY_ADJUDICATION_INPUT_INVALID",
|
|
318
|
+
"MCP recovery adjudication requires canonical sessionId and ledgerId",
|
|
319
|
+
context,
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
const decision = requireDecision(safeRequest.decision, context);
|
|
323
|
+
const expectedHeadHash = requireDigest(
|
|
324
|
+
safeRequest.expectedHeadHash,
|
|
325
|
+
"expectedHeadHash",
|
|
326
|
+
RAW_AUTHORITY_HASH,
|
|
327
|
+
context,
|
|
328
|
+
);
|
|
329
|
+
const expectedRecoveryDigest = requireDigest(
|
|
330
|
+
safeRequest.expectedRecoveryDigest,
|
|
331
|
+
"expectedRecoveryDigest",
|
|
332
|
+
PAYLOAD_DIGEST,
|
|
333
|
+
context,
|
|
334
|
+
);
|
|
335
|
+
const reason = requireReason(safeRequest.reason, context);
|
|
336
|
+
const recovery = readMcpRecoveryAuthority(sessionId, dependencies);
|
|
337
|
+
|
|
338
|
+
if (
|
|
339
|
+
recovery.headHash !== expectedHeadHash ||
|
|
340
|
+
recovery.recoveryDigest !== expectedRecoveryDigest
|
|
341
|
+
) {
|
|
342
|
+
throw new McpRecoveryAdjudicationError(
|
|
343
|
+
"CC_MCP_RECOVERY_ADJUDICATION_STALE",
|
|
344
|
+
"MCP recovery authority changed; run show again before adjudicating",
|
|
345
|
+
context,
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
if (recovery.incidents.length > 0) {
|
|
349
|
+
throw new McpRecoveryAdjudicationError(
|
|
350
|
+
"CC_MCP_RECOVERY_ADJUDICATION_INCIDENTS_PRESENT",
|
|
351
|
+
"MCP recovery incidents require transcript inspection before adjudication",
|
|
352
|
+
context,
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
const target = recovery.unsettled.find(
|
|
356
|
+
(record) => record.ledgerId === ledgerId,
|
|
357
|
+
);
|
|
358
|
+
if (!target || target.status !== "started") {
|
|
359
|
+
throw new McpRecoveryAdjudicationError(
|
|
360
|
+
"CC_MCP_RECOVERY_ADJUDICATION_TARGET_INVALID",
|
|
361
|
+
"Only a verified started-only MCP call can be adjudicated",
|
|
362
|
+
context,
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const reasonDigest = sha256PayloadDigest(reason);
|
|
367
|
+
const randomUUID = dependencies.randomUUID || nodeRandomUUID;
|
|
368
|
+
const requestId = canonicalIdentifier(
|
|
369
|
+
safeRequest.requestId || `mcp-recovery-${randomUUID()}`,
|
|
370
|
+
);
|
|
371
|
+
if (!requestId) {
|
|
372
|
+
throw new McpRecoveryAdjudicationError(
|
|
373
|
+
"CC_MCP_RECOVERY_ADJUDICATION_INPUT_INVALID",
|
|
374
|
+
"MCP recovery requestId is invalid",
|
|
375
|
+
context,
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
const data = Object.freeze({
|
|
379
|
+
schemaVersion: MCP_CALL_RECOVERY_ADJUDICATION_SCHEMA_VERSION,
|
|
380
|
+
requestId,
|
|
381
|
+
sessionId,
|
|
382
|
+
ledgerId,
|
|
383
|
+
decision,
|
|
384
|
+
expectedHeadHash: recovery.headHash,
|
|
385
|
+
expectedRecoveryDigest: recovery.recoveryDigest,
|
|
386
|
+
authority: MCP_CALL_RECOVERY_AUTHORITY,
|
|
387
|
+
confirmation: MCP_CALL_RECOVERY_CONFIRMATION,
|
|
388
|
+
reasonDigest,
|
|
389
|
+
});
|
|
390
|
+
const appendAuthorityEventIfHead =
|
|
391
|
+
dependencies.appendAuthorityEventIfHead || storeAppendAuthorityEventIfHead;
|
|
392
|
+
let appended;
|
|
393
|
+
try {
|
|
394
|
+
appended = snapshotMcpJsonRpcInput(
|
|
395
|
+
await appendAuthorityEventIfHead(
|
|
396
|
+
sessionId,
|
|
397
|
+
MCP_CALL_RECOVERY_ADJUDICATION_EVENT,
|
|
398
|
+
data,
|
|
399
|
+
recovery.headHash,
|
|
400
|
+
),
|
|
401
|
+
);
|
|
402
|
+
} catch (cause) {
|
|
403
|
+
if (cause?.code === "SESSION_REVISION_STALE") {
|
|
404
|
+
throw new McpRecoveryAdjudicationError(
|
|
405
|
+
"CC_MCP_RECOVERY_ADJUDICATION_STALE",
|
|
406
|
+
"MCP recovery authority changed; run show again before adjudicating",
|
|
407
|
+
{ ...context, cause },
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
throw new McpRecoveryAdjudicationError(
|
|
411
|
+
"CC_MCP_RECOVERY_ADJUDICATION_PERSIST_FAILED",
|
|
412
|
+
"MCP recovery adjudication was not persisted",
|
|
413
|
+
{ ...context, cause },
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
if (!appended || !RAW_AUTHORITY_HASH.test(String(appended.hash || ""))) {
|
|
417
|
+
throw new McpRecoveryAdjudicationError(
|
|
418
|
+
"CC_MCP_RECOVERY_ADJUDICATION_PERSIST_FAILED",
|
|
419
|
+
"MCP recovery adjudication did not return a durable authority hash",
|
|
420
|
+
context,
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
return Object.freeze({
|
|
425
|
+
schemaVersion: MCP_CALL_RECOVERY_ADJUDICATION_SCHEMA_VERSION,
|
|
426
|
+
requestId,
|
|
427
|
+
sessionId,
|
|
428
|
+
ledgerId,
|
|
429
|
+
decision,
|
|
430
|
+
previousHeadHash: recovery.headHash,
|
|
431
|
+
headHash: appended.hash,
|
|
432
|
+
expectedRecoveryDigest: recovery.recoveryDigest,
|
|
433
|
+
reasonDigest,
|
|
434
|
+
replayDigests: Object.freeze(
|
|
435
|
+
decision === McpCallRecoveryDecision.CONFIRMED_APPLIED
|
|
436
|
+
? deriveMcpExactReplayDenies(target).map((deny) => deny.replayDigest)
|
|
437
|
+
: [],
|
|
438
|
+
),
|
|
439
|
+
replayDenied: decision === McpCallRecoveryDecision.CONFIRMED_APPLIED,
|
|
440
|
+
runtimeReloadRequired: true,
|
|
441
|
+
remediation: "restart_or_resume_before_mcp_calls",
|
|
442
|
+
});
|
|
443
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process-wide CLI output contract.
|
|
3
|
+
*
|
|
4
|
+
* Command actions historically import a singleton logger, so the context is
|
|
5
|
+
* intentionally mutable and bound once by Commander's preAction lifecycle.
|
|
6
|
+
* New code may use OutputContext directly; legacy logger calls are adapted by
|
|
7
|
+
* src/lib/logger.js.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export class OutputContext {
|
|
11
|
+
constructor({
|
|
12
|
+
quiet = false,
|
|
13
|
+
verbose = false,
|
|
14
|
+
machineReadable = false,
|
|
15
|
+
} = {}) {
|
|
16
|
+
this.quiet = quiet === true;
|
|
17
|
+
this.verbose = verbose === true;
|
|
18
|
+
this.machineReadable = machineReadable === true;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let currentContext = new OutputContext();
|
|
23
|
+
const MACHINE_READABLE_FORMATS = new Set([
|
|
24
|
+
"json",
|
|
25
|
+
"jsonl",
|
|
26
|
+
"ndjson",
|
|
27
|
+
"stream-json",
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
|
+
export function getOutputContext() {
|
|
31
|
+
return currentContext;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function bindOutputContext(options = {}) {
|
|
35
|
+
currentContext =
|
|
36
|
+
options instanceof OutputContext ? options : new OutputContext(options);
|
|
37
|
+
return currentContext;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function resetOutputContext() {
|
|
41
|
+
return bindOutputContext();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function isMachineReadableOptions(options = {}) {
|
|
45
|
+
if (options.json === true) return true;
|
|
46
|
+
if (options.jsonSchema) return true;
|
|
47
|
+
const format = String(
|
|
48
|
+
options.outputFormat || options.format || "",
|
|
49
|
+
).toLowerCase();
|
|
50
|
+
return MACHINE_READABLE_FORMATS.has(format);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function bindProgramOutputContext(program, actionCommand) {
|
|
54
|
+
const current = getOutputContext();
|
|
55
|
+
const globalOptions = program?.opts?.() || {};
|
|
56
|
+
const commandOptions = actionCommand?.opts?.() || {};
|
|
57
|
+
return bindOutputContext({
|
|
58
|
+
quiet: current.quiet || globalOptions.quiet === true,
|
|
59
|
+
verbose: current.verbose || globalOptions.verbose === true,
|
|
60
|
+
machineReadable:
|
|
61
|
+
current.machineReadable || isMachineReadableOptions(commandOptions),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function argvRequestsMachineReadableOutput(argv = process.argv) {
|
|
66
|
+
const args = Array.isArray(argv) ? argv : [];
|
|
67
|
+
for (let index = 0; index < args.length; index++) {
|
|
68
|
+
const arg = String(args[index]);
|
|
69
|
+
if (arg === "--") break;
|
|
70
|
+
if (
|
|
71
|
+
arg === "--json" ||
|
|
72
|
+
arg === "--json-schema" ||
|
|
73
|
+
arg.startsWith("--json-schema=")
|
|
74
|
+
) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
const separator = arg.indexOf("=");
|
|
78
|
+
const flag = separator === -1 ? arg : arg.slice(0, separator);
|
|
79
|
+
if (flag !== "--output-format" && flag !== "--format") continue;
|
|
80
|
+
const value = separator === -1 ? args[index + 1] : arg.slice(separator + 1);
|
|
81
|
+
if (MACHINE_READABLE_FORMATS.has(String(value || "").toLowerCase())) {
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable file identity checks for packer transactions.
|
|
3
|
+
*
|
|
4
|
+
* Node 22.12 ships libuv 1.49.1. On affected Windows hosts, lstat(path)
|
|
5
|
+
* can project a different device value than fstat(fd) for the same file.
|
|
6
|
+
* Never drop the volume/file-index check to bridge that incompatibility.
|
|
7
|
+
* Instead, reopen the pathname and compare the two handle identities exactly;
|
|
8
|
+
* the path API is then used to prove that the non-link pathname stayed stable
|
|
9
|
+
* around that second open. Only the known libuv 1.49/1.50 device projection
|
|
10
|
+
* mismatch is tolerated between path and handle samples.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import fs from "node:fs";
|
|
14
|
+
import {
|
|
15
|
+
samePathHandleFileIdentity,
|
|
16
|
+
withTrustedFileParentSync,
|
|
17
|
+
} from "../secure-file-identity.js";
|
|
18
|
+
|
|
19
|
+
const BIGINT_STAT_OPTIONS = Object.freeze({ bigint: true });
|
|
20
|
+
const FULL_STATE_FIELDS = Object.freeze([
|
|
21
|
+
"mode",
|
|
22
|
+
"nlink",
|
|
23
|
+
"size",
|
|
24
|
+
"mtimeNs",
|
|
25
|
+
"ctimeNs",
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
export function hasPreciseFileIdentity(stat) {
|
|
29
|
+
return Boolean(
|
|
30
|
+
stat &&
|
|
31
|
+
typeof stat.dev === "bigint" &&
|
|
32
|
+
stat.dev >= 0n &&
|
|
33
|
+
typeof stat.ino === "bigint" &&
|
|
34
|
+
stat.ino > 0n,
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function sameOpenedFileIdentity(left, right, stateFields = []) {
|
|
39
|
+
return Boolean(
|
|
40
|
+
hasPreciseFileIdentity(left) &&
|
|
41
|
+
hasPreciseFileIdentity(right) &&
|
|
42
|
+
left.dev === right.dev &&
|
|
43
|
+
left.ino === right.ino &&
|
|
44
|
+
stateFields.every(
|
|
45
|
+
(field) =>
|
|
46
|
+
FULL_STATE_FIELDS.includes(field) && left[field] === right[field],
|
|
47
|
+
),
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function isRegularNonLink(stat) {
|
|
52
|
+
return Boolean(
|
|
53
|
+
stat &&
|
|
54
|
+
typeof stat.isSymbolicLink === "function" &&
|
|
55
|
+
!stat.isSymbolicLink() &&
|
|
56
|
+
typeof stat.isFile === "function" &&
|
|
57
|
+
stat.isFile(),
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Prove that filePath still names expectedIdentity.
|
|
63
|
+
*
|
|
64
|
+
* expectedIdentity must come from an opened descriptor. On Windows, the
|
|
65
|
+
* pathname is reopened and its fstat identity is compared exactly with that
|
|
66
|
+
* descriptor identity, retaining both the volume serial (dev) and file index
|
|
67
|
+
* (ino). Path samples before and after the open must also remain byte-for-byte
|
|
68
|
+
* stable across all identity/mutation fields.
|
|
69
|
+
*/
|
|
70
|
+
export function pathMatchesOpenedFileIdentitySync(
|
|
71
|
+
filePath,
|
|
72
|
+
expectedIdentity,
|
|
73
|
+
{ fileSystem = fs, runtime = undefined, stateFields = [] } = {},
|
|
74
|
+
) {
|
|
75
|
+
if (!hasPreciseFileIdentity(expectedIdentity)) return false;
|
|
76
|
+
if (
|
|
77
|
+
!Array.isArray(stateFields) ||
|
|
78
|
+
stateFields.some((field) => !FULL_STATE_FIELDS.includes(field))
|
|
79
|
+
) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
return withTrustedFileParentSync(
|
|
85
|
+
fileSystem,
|
|
86
|
+
filePath,
|
|
87
|
+
({ canonicalPath, parentDevice }) => {
|
|
88
|
+
// The independently opened parent/volume-root authority prevents the
|
|
89
|
+
// affected Windows bridge from accepting an attacker-selected device.
|
|
90
|
+
if (String(expectedIdentity.dev) !== String(parentDevice)) return false;
|
|
91
|
+
|
|
92
|
+
const noFollow = Number(fileSystem.constants?.O_NOFOLLOW || 0);
|
|
93
|
+
const readOnly = Number(
|
|
94
|
+
fileSystem.constants?.O_RDONLY ?? fs.constants.O_RDONLY,
|
|
95
|
+
);
|
|
96
|
+
let descriptor = null;
|
|
97
|
+
try {
|
|
98
|
+
const pathBefore = fileSystem.lstatSync(
|
|
99
|
+
canonicalPath,
|
|
100
|
+
BIGINT_STAT_OPTIONS,
|
|
101
|
+
);
|
|
102
|
+
if (!isRegularNonLink(pathBefore)) return false;
|
|
103
|
+
|
|
104
|
+
descriptor = fileSystem.openSync(canonicalPath, readOnly | noFollow);
|
|
105
|
+
const openedBefore = fileSystem.fstatSync(
|
|
106
|
+
descriptor,
|
|
107
|
+
BIGINT_STAT_OPTIONS,
|
|
108
|
+
);
|
|
109
|
+
if (
|
|
110
|
+
!openedBefore.isFile() ||
|
|
111
|
+
!sameOpenedFileIdentity(
|
|
112
|
+
expectedIdentity,
|
|
113
|
+
openedBefore,
|
|
114
|
+
stateFields,
|
|
115
|
+
) ||
|
|
116
|
+
!samePathHandleFileIdentity(
|
|
117
|
+
pathBefore,
|
|
118
|
+
openedBefore,
|
|
119
|
+
parentDevice,
|
|
120
|
+
runtime,
|
|
121
|
+
)
|
|
122
|
+
) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const openedAfter = fileSystem.fstatSync(
|
|
127
|
+
descriptor,
|
|
128
|
+
BIGINT_STAT_OPTIONS,
|
|
129
|
+
);
|
|
130
|
+
const pathAfter = fileSystem.lstatSync(
|
|
131
|
+
canonicalPath,
|
|
132
|
+
BIGINT_STAT_OPTIONS,
|
|
133
|
+
);
|
|
134
|
+
return Boolean(
|
|
135
|
+
openedAfter.isFile() &&
|
|
136
|
+
isRegularNonLink(pathAfter) &&
|
|
137
|
+
sameOpenedFileIdentity(
|
|
138
|
+
openedBefore,
|
|
139
|
+
openedAfter,
|
|
140
|
+
FULL_STATE_FIELDS,
|
|
141
|
+
) &&
|
|
142
|
+
sameOpenedFileIdentity(
|
|
143
|
+
expectedIdentity,
|
|
144
|
+
openedAfter,
|
|
145
|
+
stateFields,
|
|
146
|
+
) &&
|
|
147
|
+
sameOpenedFileIdentity(pathBefore, pathAfter, FULL_STATE_FIELDS) &&
|
|
148
|
+
samePathHandleFileIdentity(
|
|
149
|
+
pathAfter,
|
|
150
|
+
openedAfter,
|
|
151
|
+
parentDevice,
|
|
152
|
+
runtime,
|
|
153
|
+
),
|
|
154
|
+
);
|
|
155
|
+
} finally {
|
|
156
|
+
if (descriptor !== null) {
|
|
157
|
+
try {
|
|
158
|
+
fileSystem.closeSync(descriptor);
|
|
159
|
+
} catch {
|
|
160
|
+
/* the surrounding identity result remains authoritative */
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
{ runtime },
|
|
166
|
+
);
|
|
167
|
+
} catch {
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
}
|
package/src/lib/packer/index.js
CHANGED
|
@@ -216,6 +216,9 @@ export async function runPack(cliOpts, deps = {}) {
|
|
|
216
216
|
projectEntry: cliOpts.entry || null,
|
|
217
217
|
forceRefreshOnLaunch: Boolean(cliOpts.forceRefreshOnLaunch),
|
|
218
218
|
updateManifestUrl: cliOpts.updateManifestUrl || null,
|
|
219
|
+
updatePublicKey: cliOpts.updatePublicKey
|
|
220
|
+
? fs.readFileSync(path.resolve(cliOpts.updatePublicKey), "utf8")
|
|
221
|
+
: null,
|
|
219
222
|
});
|
|
220
223
|
steps.push({
|
|
221
224
|
phase: "pkg-config",
|