chainlesschain 0.165.3 → 0.165.5
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 +151 -29
- package/package.json +2 -2
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-BiHNUlbU.js → AIOps-CEeYTeDB.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-D-UFjDRQ.js → ActionButton-BeRUQ3V2.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DazVsDgW.js → Analytics-DrV718XF.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DXh9UfNJ.js → AppLayout-Cd2Frt7Q.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-CZ6tsceY.js → Artifacts-CUJMlORU.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-RyxnBr_h.js → Audit-CXJcfT6p.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-BWS51Q6X.js → BackgroundAgents-DOv6Z7H9.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-BRtPcUul.js → Backup-BwdDyBI0.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-CGd4vZYY.js → BaseInput-BmLn4kYH.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-h8ijVwCg.js → Chat-COg8pAW2.js} +4 -4
- package/src/assets/web-panel/assets/ChatBubbleRenderer-4gGkdGgA.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-NyF6dPl8.js → Checkbox-BCP4uoU8.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-Ci4OOxr5.js → Codegen-pRt6Y9JI.js} +1 -1
- package/src/assets/web-panel/assets/{Col-CwTkc9BM.js → Col-DLaprKhS.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DW_tM82m.js → Community-DyATsz5f.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DEvHRV4S.js → Compact-BXAaupZK.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-BbjBEEfD.js → Compliance-DpcJBELr.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-10IXBaBa.js → Cowork-DG4EFWyd.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-BZkbpd5I.js → Cron-F6Oy5n2P.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CFQ8L_6v.js → Crosschain-BOdgtalX.js} +1 -1
- package/src/assets/web-panel/assets/{DID-BDF6AkXe.js → DID-DT1dSkjH.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-CoOdWMi4.js → Dashboard-NBUIqWzC.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DEsGmu8Y.js → Dropdown-CSpHeMYB.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-BS89SWlK.js → EmailListRenderer-CEG0xISr.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-C1FpCHiI.js → FamilyGuardDashboard-BTZ0BZna.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BzvpVmLA.js → Federation-BuuCTn2V.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-BeC259PQ.js → FormItemContext-KAVceevk.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-azgG3bmV.js → GenericCardRenderer-DnHpcQvW.js} +1 -1
- package/src/assets/web-panel/assets/{Git-BmSSowc5.js → Git-C_B_0HwB.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CTBCSyQZ.js → Governance-DPSZuzuu.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-DA5xyk4a.js → Inference-BV-06V7q.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-D1gPHNig.js → KnowledgeGraph-wpDuupn6.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-BPmLf1AR.js → Logs-Bseca1_I.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-SVLOg49H.js → MarkdownRenderer-B4RLp2zs.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-DtUFcR0E.js → Marketplace-d3kM4DDL.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DS_kqBv-.js → McpTools-DQ_xZ23i.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-Fvh7XL7V.js → Memory-CRIeYO4L.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-C7itAP45.js → MobileBridge-BsllIa9l.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-BUuQy30X.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-B57MiNLK.js → Mtc-BOFDIzrC.js} +6 -6
- package/src/assets/web-panel/assets/{MtcAudit-BXfCUcM7.js → MtcAudit-BQg-vyvG.js} +5 -5
- package/src/assets/web-panel/assets/{Multisig-yaJ-ZcF6.js → Multisig-Bo1jrPdN.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-CoaUCKrO.js → NLProgramming-Bmod8alw.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-BKLM_65R.js → Notes-CGGFL8w-.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-DoDtK9uZ.js → NotificationSettings-BsZvCJxC.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-BJ28TGr-.js → OrderTableRenderer-C1-Quo_h.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-MuGsdoIb.js → Organization-BjOeDYOi.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-BLUN9J4R.js → Overflow-DwVV3l5A.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-DWuoBUPd.js → P2P-Cu3DQT9W.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-CUi37YPj.js → PdhVaultBrowser-Cg0gR7dH.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-BYQg2pcr.js → Permissions-CsAXxRN5.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-CAxoV2xu.js → PersonalDataHub-C-nNmnYp.js} +6 -6
- package/src/assets/web-panel/assets/{Pipeline-B33wGvIO.js → Pipeline-BOnW7nNc.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-A8yXTORP.js → Privacy-ClLSyGKt.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-D49I2I1O.js → ProjectInit-DuLvjjq7.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-Ci73jJDw.js → ProjectSettings-DQYYbDD9.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-CF-yD6Cn.js → Projects-Drw8MBGK.js} +1 -1
- package/src/assets/web-panel/assets/Providers-ckqHQe6K.js +1 -0
- package/src/assets/web-panel/assets/{QrScannerModal-Brza0ykJ.js → QrScannerModal-DW5BXk-G.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-DFydhjxL.js → QuickAsk-DDLnhNTp.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DLF8_NhA.js → Recommend-PJQ2C91U.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-dyuStW3x.js → RemoteSession-s6wmda34.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-5F3tA6yw.js → Reputation-DC2sb-I3.js} +1 -1
- package/src/assets/web-panel/assets/{Row-Ca2A57S5.js → Row-hPGk1eGj.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-B0bxBkq_.js → RssFeed-RIvfZql0.js} +3 -3
- package/src/assets/web-panel/assets/{Search-CFNvHalZ.js → Search-DFg1G1eR.js} +1 -1
- package/src/assets/web-panel/assets/{Security-DSoH3Hav.js → Security-D6H5p8Dp.js} +4 -4
- package/src/assets/web-panel/assets/{Services-BHpfEmBQ.js → Services-nxYiFV_w.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-Dsh-QNmn.js → Skeleton-BmgFNAdB.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-BhT1NkSU.js → Skills-CsaaD2av.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DY9snPeJ.js → Sla-yM5y9yvK.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-CWaX0_Cx.js → SpeechSettings-DPy1XMYh.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-B690y_TC.js → SyncSettings-CFVhEyyr.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-2N-w3zWd.js → Tasks-DdO02Inn.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BjwQOQYC.js → Templates-Eo2d8Llu.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-CUqHErxY.js → Tenant-ChESOXgy.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-C13rXvNy.js → Terminal-BJ7oDxTI.js} +2 -2
- package/src/assets/web-panel/assets/TimelineRenderer-hWX0fUvz.js +1 -0
- package/src/assets/web-panel/assets/{Tokens-BXHLGXYC.js → Tokens-DVBZQnd-.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-1e5i65o3.js → Trigger-D89cQfVq.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-FLGqNHs5.js → Trust-BIVSb4-V.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-BbaR_LJB.js → UkeySign-B58gWopl.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-NOp4RIov.js → VideoEditing-DhHI7bmG.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-B7DW7bG4.js → Wallet-C4FheWS_.js} +3 -3
- package/src/assets/web-panel/assets/{WebAuthn-BptSUWix.js → WebAuthn-DnPRq-Bx.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-CAJnDOXS.js → WorkflowEditor-BerRPjpJ.js} +1 -1
- package/src/assets/web-panel/assets/{chat-I8LgG1-Z.js → chat-BzZ52iKr.js} +1 -1
- package/src/assets/web-panel/assets/{colors-CWe7SOVD.js → colors-BI_E4BAn.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-Cx3u3CA3.js → compact-item-d50mr3yk.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-CgD5ArwY.js → createContext-C6FsQ1IH.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-CagEcIex.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-BfQWiXN8.js → hasIn-DLZEMgLP.js} +1 -1
- package/src/assets/web-panel/assets/{index-BuEQSorC.js → index-9H_M2jju.js} +1 -1
- package/src/assets/web-panel/assets/{index-BiI-xPRH.js → index-A5CDWP7y.js} +1 -1
- package/src/assets/web-panel/assets/{index-DAVy98u7.js → index-AHr7ryWf.js} +1 -1
- package/src/assets/web-panel/assets/{index-BUAR7RY-.js → index-B81mo1Et.js} +1 -1
- package/src/assets/web-panel/assets/{index-DlIyt1qF.js → index-BAE3hwev.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dcdm_Z2c.js → index-BB9SqVSt.js} +1 -1
- package/src/assets/web-panel/assets/{index-CWZ3REg6.js → index-BRGx3w6T.js} +3 -3
- package/src/assets/web-panel/assets/{index-B6yChzt1.js → index-BTpIOTfR.js} +1 -1
- package/src/assets/web-panel/assets/{index-DeizoQVZ.js → index-BZjjdQ62.js} +1 -1
- package/src/assets/web-panel/assets/{index-e8BM1yY1.js → index-BcSUl9fA.js} +1 -1
- package/src/assets/web-panel/assets/{index-CNYFQxAW.js → index-BeM4hfht.js} +1 -1
- package/src/assets/web-panel/assets/{index-DGMYTN5W.js → index-Bmr_vxXD.js} +1 -1
- package/src/assets/web-panel/assets/{index-BREnPKGo.js → index-BoNZlzhQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-B1cX4Rxu.js → index-C3k8kevG.js} +1 -1
- package/src/assets/web-panel/assets/{index-3iKP9OTJ.js → index-CLoTQr0W.js} +1 -1
- package/src/assets/web-panel/assets/{index-C1UjHdgZ.js → index-CO8DAF7U.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cy_cCJlr.js → index-CRN5TRTQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-C0nDKhWv.js → index-CUaEHfQ0.js} +1 -1
- package/src/assets/web-panel/assets/{index-DslTuqro.js → index-CVzuawCX.js} +1 -1
- package/src/assets/web-panel/assets/{index-CAUnl4Jv.js → index-CdKt9fOd.js} +1 -1
- package/src/assets/web-panel/assets/{index-CMu16vPC.js → index-CgkoH3_g.js} +1 -1
- package/src/assets/web-panel/assets/{index-C-rIKccl.js → index-CjuKZBqJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bx7BNIRH.js → index-Co7s9LsB.js} +1 -1
- package/src/assets/web-panel/assets/{index-Doc0Ftpd.js → index-D-aBumtY.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cd79NQAx.js → index-DE0V6cp-.js} +1 -1
- package/src/assets/web-panel/assets/{index-V-kIHzAV.js → index-DY4j5zkF.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bi24S7Dw.js → index-Dec0Kf_Z.js} +1 -1
- package/src/assets/web-panel/assets/{index-DCJEY2T0.js → index-DoFtCVZ7.js} +1 -1
- package/src/assets/web-panel/assets/{index-C0ztiqtB.js → index-DqkbHHg8.js} +1 -1
- package/src/assets/web-panel/assets/{index-CcX4FSPf.js → index-DsscwxPE.js} +1 -1
- package/src/assets/web-panel/assets/{index-CdRkCwm4.js → index-GXE0D8Nx.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmgtY58H.js → index-IPkwSAW_.js} +1 -1
- package/src/assets/web-panel/assets/{index-CQDKYbnv.js → index-KNGgO4Wm.js} +1 -1
- package/src/assets/web-panel/assets/{index-87gMxqhN.js → index-Pvf30m8Q.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmrdUwzU.js → index-Q5Tn735s.js} +1 -1
- package/src/assets/web-panel/assets/{index-DFb-XIKy.js → index-TWG-_D1M.js} +1 -1
- package/src/assets/web-panel/assets/{index-DsQcURkA.js → index-Y2-q7QLm.js} +1 -1
- package/src/assets/web-panel/assets/index-pzT9PpOU.js +1 -0
- package/src/assets/web-panel/assets/index-z1kFadaX.js +1 -0
- package/src/assets/web-panel/assets/{initDefaultProps-DiBszVdG.js → initDefaultProps-D-4Hzgej.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BGIFFozv.js → motion-D4Wl4xU7.js} +1 -1
- package/src/assets/web-panel/assets/{move-D5W7mp7B.js → move-Cd5eQvL0.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-JFIlxJ7F.js → mtc-parser-B4ilslCW.js} +1 -1
- package/src/assets/web-panel/assets/{omit-CQ3o6LIU.js → omit-Ckarx-tf.js} +1 -1
- package/src/assets/web-panel/assets/parsers-YNLm7sQ0.js +4 -0
- package/src/assets/web-panel/assets/{pickAttrs-R8MIlXo3.js → pickAttrs-QJ0bpCmc.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-sW7ylSky.js → placementArrow-CKHm-tq8.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-Cnl39Vbz.js → responsiveObserve-CV6a_w_Y.js} +1 -1
- package/src/assets/web-panel/assets/{slide-sn8tFd14.js → slide-mHpeQFgk.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-IKKY_QxZ.js → statusUtils-DIaQNQWA.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-BNpV4Nqs.js → styleChecker-PJpzavV8.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-BWyT_eoU.js → useFlexGapSupport-BH7zTw8S.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-D09p6_U9.js → useFs-BDNG3JDd.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-CzW3TkJZ.js → usePersonalDataHub-CY2VWdUg.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-3s3WoAKB.js → vnode-D0kw9jhz.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-Cjy_673s.js → zoom-B5g7TN7r.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +3 -3
- package/src/commands/agent.js +105 -35
- package/src/commands/artifacts.js +598 -33
- package/src/commands/cowork.js +200 -5
- package/src/commands/session-budget.js +155 -0
- package/src/commands/session-location.js +968 -1
- package/src/commands/session.js +23 -2
- package/src/data/changelog.json +28 -2
- package/src/gateways/ws/artifact-protocol.js +77 -13
- package/src/gateways/ws/message-dispatcher.js +57 -0
- package/src/gateways/ws/session-protocol.js +391 -24
- package/src/gateways/ws/ws-agent-handler.js +191 -14
- package/src/gateways/ws/ws-server.js +14 -3
- package/src/gateways/ws/ws-session-gateway.js +101 -5
- package/src/harness/jsonl-session-store.js +1210 -0
- package/src/lib/agent-team/team-runner.js +43 -13
- package/src/lib/artifact-access-ledger.js +462 -0
- package/src/lib/artifact-cleanup-ledger.js +861 -0
- package/src/lib/artifact-deletion-ledger.js +678 -0
- package/src/lib/artifact-recovery.js +970 -0
- package/src/lib/artifact-store.js +256 -51
- package/src/lib/artifact-workbench-projection.js +171 -0
- package/src/lib/command-lifecycle-report.js +8 -4
- package/src/lib/cowork-adapter.js +9 -5
- package/src/lib/cowork-task-runner.js +20 -0
- package/src/lib/cowork-workflow.js +178 -20
- package/src/lib/direct-model-usage.js +62 -22
- package/src/lib/dynamic-workflow-runtime.js +3592 -112
- package/src/lib/execution-location-result-apply.js +339 -0
- package/src/lib/execution-location-result-artifact.js +271 -0
- package/src/lib/execution-location-result-review.js +253 -0
- package/src/lib/execution-location-result-store.js +331 -0
- package/src/lib/execution-location-result.js +617 -0
- package/src/lib/execution-location-target.js +240 -3
- package/src/lib/managed-tool-checkpoint.js +47 -4
- package/src/lib/mcp-stdio-executable-identity.js +16 -0
- package/src/lib/mcp-stdio-native-code-policy.js +74 -0
- package/src/lib/mcp-stdio-package-materialization.js +12 -3
- package/src/lib/process-execution-broker/index.js +112 -0
- package/src/lib/process-execution-broker/platform-sandbox.js +57 -3
- package/src/lib/process-execution-broker/workspace-transaction.js +29 -0
- package/src/lib/session-budget-production-root.js +376 -0
- package/src/lib/session-budget-runtime.js +109 -18
- package/src/lib/session-budget-usage.js +63 -0
- package/src/lib/session-host-snapshot.js +19 -2
- package/src/lib/session-projection.js +126 -10
- package/src/lib/session-resource-budget.js +766 -105
- package/src/lib/sub-agent-context.js +69 -22
- package/src/lib/web-ui-server.js +12 -1
- package/src/repl/agent-repl.js +237 -16
- package/src/runtime/agent-core.js +135 -0
- package/src/runtime/headless-runner.js +135 -46
- package/src/runtime/headless-stream.js +133 -25
- package/src/runtime/policies/agent-policy.js +10 -0
- package/src/assets/web-panel/assets/ChatBubbleRenderer-D7tcdDS9.js +0 -1
- package/src/assets/web-panel/assets/MobileProjects-DGbP36-3.js +0 -1
- package/src/assets/web-panel/assets/Providers-D-etEhg5.js +0 -1
- package/src/assets/web-panel/assets/TimelineRenderer-CpbWcya_.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DLv_872g.js +0 -1
- package/src/assets/web-panel/assets/index-CdiGCibe.js +0 -1
- package/src/assets/web-panel/assets/index-D_0z-gyz.js +0 -1
- package/src/assets/web-panel/assets/parsers-UEvh_ShA.js +0 -4
|
@@ -5,23 +5,62 @@ import {
|
|
|
5
5
|
buildExecutionLocationCatalog,
|
|
6
6
|
buildExecutionLocationHandoffPreview,
|
|
7
7
|
computeExecutionLocationTargetFactsDigest,
|
|
8
|
+
createExecutionLocationTargetAttestation,
|
|
8
9
|
} from "../lib/execution-location-contract.js";
|
|
9
10
|
import { captureAmbientExecutionLocation } from "../lib/execution-location-runtime.js";
|
|
10
11
|
import {
|
|
11
12
|
EXECUTION_LOCATION_TARGET_ATTESTATION_SCHEMA,
|
|
13
|
+
EXECUTION_LOCATION_TARGET_RESULT_COLLECTION_SCHEMA,
|
|
12
14
|
EXECUTION_LOCATION_TARGET_RESUME_SCHEMA,
|
|
13
15
|
attestExecutionLocationTarget,
|
|
16
|
+
collectExecutionLocationTargetResult,
|
|
17
|
+
createExecutionLocationTargetResultCollectionRequest,
|
|
14
18
|
readExecutionLocationProfile,
|
|
15
19
|
resumeExecutionLocationTarget,
|
|
16
20
|
} from "../lib/execution-location-target.js";
|
|
21
|
+
import {
|
|
22
|
+
EXECUTION_LOCATION_RESULT_BUNDLE_SCHEMA,
|
|
23
|
+
EXECUTION_LOCATION_RESULT_VERIFICATION_SCHEMA,
|
|
24
|
+
MAX_EXECUTION_LOCATION_RESULT_BUNDLE_BYTES,
|
|
25
|
+
createExecutionLocationResultBundle,
|
|
26
|
+
readExecutionLocationResultBundle,
|
|
27
|
+
readExecutionLocationResultFile,
|
|
28
|
+
verifyExecutionLocationResultBundle,
|
|
29
|
+
} from "../lib/execution-location-result.js";
|
|
17
30
|
import {
|
|
18
31
|
MAX_SESSION_REPLICA_BYTES,
|
|
19
32
|
SESSION_EXECUTION_LOCATION_HANDOFF_INSTALL_SCHEMA,
|
|
33
|
+
SESSION_EXECUTION_LOCATION_RESULT_APPLY_RECEIPT_SCHEMA,
|
|
34
|
+
SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_RECEIPT_SCHEMA,
|
|
35
|
+
SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_RECEIPT_SCHEMA_V1,
|
|
20
36
|
getVerifiedSessionExecutionLocationAuthority,
|
|
21
37
|
installSessionReplica,
|
|
22
38
|
installSessionReplicaWithLocationHandoff,
|
|
39
|
+
readVerifiedSessionExecutionLocationResultApply,
|
|
40
|
+
readVerifiedSessionExecutionLocationResultSettlement,
|
|
23
41
|
readVerifiedTranscriptBytes,
|
|
42
|
+
reserveSessionExecutionLocationResultApply,
|
|
43
|
+
settleSessionExecutionLocationResultApply,
|
|
44
|
+
settleSessionExecutionLocationResultCollection,
|
|
24
45
|
} from "../harness/jsonl-session-store.js";
|
|
46
|
+
import {
|
|
47
|
+
readStoredExecutionLocationResultBundle,
|
|
48
|
+
storeExecutionLocationResultBundle,
|
|
49
|
+
} from "../lib/execution-location-result-store.js";
|
|
50
|
+
import {
|
|
51
|
+
EXECUTION_LOCATION_RESULT_REVIEW_SCHEMA,
|
|
52
|
+
createExecutionLocationResultReview,
|
|
53
|
+
} from "../lib/execution-location-result-review.js";
|
|
54
|
+
import {
|
|
55
|
+
EXECUTION_LOCATION_RESULT_ARTIFACT_IMPORT_SCHEMA,
|
|
56
|
+
importExecutionLocationResultArtifact,
|
|
57
|
+
} from "../lib/execution-location-result-artifact.js";
|
|
58
|
+
import {
|
|
59
|
+
executeControlledExecutionLocationResultApply,
|
|
60
|
+
terminalExecutionLocationResultApplyTransaction,
|
|
61
|
+
verifyExecutionLocationResultApplySourceGit,
|
|
62
|
+
} from "../lib/execution-location-result-apply.js";
|
|
63
|
+
import { executionBroker } from "../lib/process-execution-broker/index.js";
|
|
25
64
|
import {
|
|
26
65
|
sameFileStatIdentity,
|
|
27
66
|
samePathHandleFileIdentity,
|
|
@@ -31,6 +70,8 @@ import {
|
|
|
31
70
|
const MAX_HANDOFF_FACTS_BYTES = 1024 * 1024;
|
|
32
71
|
export const SESSION_EXECUTION_LOCATION_AUTHORITY_SCHEMA =
|
|
33
72
|
"cc-session-execution-location-authority/v1";
|
|
73
|
+
export const EXECUTION_LOCATION_RESULT_PREVIEW_SCHEMA =
|
|
74
|
+
"cc-execution-location-result-preview/v1";
|
|
34
75
|
|
|
35
76
|
function readHandoffFacts(filePath, deps = {}) {
|
|
36
77
|
const runtimeFs = deps.fs || fs;
|
|
@@ -293,6 +334,24 @@ export function prepareSessionReplicaHandoff(sessionId, options, deps = {}) {
|
|
|
293
334
|
if (targetFactsDigest !== String(options.expectedTargetFactsDigest || "")) {
|
|
294
335
|
throw new Error("target facts changed before location handoff append");
|
|
295
336
|
}
|
|
337
|
+
if (!/^sha256:[a-f0-9]{64}$/u.test(String(options.attestationDigest || ""))) {
|
|
338
|
+
throw new Error("source target attestation digest is invalid");
|
|
339
|
+
}
|
|
340
|
+
// observedAt is intentionally excluded from targetFactsDigest but included
|
|
341
|
+
// in attestationDigest. The source-side probe and this target-side prepare
|
|
342
|
+
// are separate process invocations, so a real target can never reproduce
|
|
343
|
+
// the source probe's timestamp. Bind the handoff event to this fresh target
|
|
344
|
+
// observation; the source rehashes its receipt and immediately verifies the
|
|
345
|
+
// canonical target projection before it is allowed to resume.
|
|
346
|
+
const targetAttestation = createExecutionLocationTargetAttestation({
|
|
347
|
+
profileDigest: options.profileDigest,
|
|
348
|
+
sourceSessionId: sessionId,
|
|
349
|
+
sourceHeadHash: options.expectedHeadHash,
|
|
350
|
+
sourceEventCount: Number(options.expectedEventCount),
|
|
351
|
+
targetEvidenceId: options.targetEvidenceId,
|
|
352
|
+
baseCommit: binding.source.git.commit,
|
|
353
|
+
binding,
|
|
354
|
+
});
|
|
296
355
|
return (
|
|
297
356
|
deps.installSessionReplicaWithLocationHandoff ||
|
|
298
357
|
installSessionReplicaWithLocationHandoff
|
|
@@ -308,12 +367,627 @@ export function prepareSessionReplicaHandoff(sessionId, options, deps = {}) {
|
|
|
308
367
|
profileDigest: options.profileDigest,
|
|
309
368
|
targetEvidenceId: options.targetEvidenceId,
|
|
310
369
|
targetFactsDigest,
|
|
311
|
-
attestationDigest:
|
|
370
|
+
attestationDigest: targetAttestation.attestationDigest,
|
|
312
371
|
binding,
|
|
313
372
|
},
|
|
314
373
|
);
|
|
315
374
|
}
|
|
316
375
|
|
|
376
|
+
function parseResultFileSpec(value, label) {
|
|
377
|
+
const text = String(value || "");
|
|
378
|
+
const separator = text.indexOf("=");
|
|
379
|
+
if (separator <= 0 || separator === text.length - 1) {
|
|
380
|
+
throw new Error(`${label} must be <media-type>=<path>`);
|
|
381
|
+
}
|
|
382
|
+
return {
|
|
383
|
+
mediaType: text.slice(0, separator),
|
|
384
|
+
path: text.slice(separator + 1),
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function collectResultFileSpec(value, previous) {
|
|
389
|
+
return [...previous, value];
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function resultBoundary(authority) {
|
|
393
|
+
const root = authority?.binding?.policy?.dataBoundary?.root;
|
|
394
|
+
if (typeof root !== "string" || root.length === 0) {
|
|
395
|
+
throw new Error(
|
|
396
|
+
"verified execution location data boundary is required for result files",
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
return root;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
export function createSessionExecutionLocationResultBundle(
|
|
403
|
+
sessionId,
|
|
404
|
+
options,
|
|
405
|
+
deps = {},
|
|
406
|
+
) {
|
|
407
|
+
const sessionAuthority = projectSessionExecutionLocation(sessionId, deps);
|
|
408
|
+
const boundaryRoot = resultBoundary(sessionAuthority);
|
|
409
|
+
const readFile =
|
|
410
|
+
deps.readExecutionLocationResultFile || readExecutionLocationResultFile;
|
|
411
|
+
const read = (filePath, fileOptions = {}) =>
|
|
412
|
+
readFile(filePath, {
|
|
413
|
+
boundaryRoot,
|
|
414
|
+
...fileOptions,
|
|
415
|
+
...(deps.resultFileDependencies || {}),
|
|
416
|
+
});
|
|
417
|
+
const readItems = (values, label) =>
|
|
418
|
+
(values || []).map((value) => {
|
|
419
|
+
const spec = parseResultFileSpec(value, label);
|
|
420
|
+
return {
|
|
421
|
+
mediaType: spec.mediaType,
|
|
422
|
+
bytes: read(spec.path, { allowEmpty: true }),
|
|
423
|
+
};
|
|
424
|
+
});
|
|
425
|
+
return (
|
|
426
|
+
deps.createExecutionLocationResultBundle ||
|
|
427
|
+
createExecutionLocationResultBundle
|
|
428
|
+
)({
|
|
429
|
+
sessionAuthority,
|
|
430
|
+
resultId: options.resultId,
|
|
431
|
+
summaryBytes: read(options.summary),
|
|
432
|
+
diffBytes: read(options.diff, { allowEmpty: true }),
|
|
433
|
+
artifacts: readItems(options.artifact, "--artifact"),
|
|
434
|
+
evidence: readItems(options.evidence, "--evidence"),
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
export function verifySessionExecutionLocationResultBundle(
|
|
439
|
+
sessionId,
|
|
440
|
+
bundlePath,
|
|
441
|
+
expectedHandoffId,
|
|
442
|
+
deps = {},
|
|
443
|
+
) {
|
|
444
|
+
const sourceAuthority = projectSessionExecutionLocation(sessionId, deps);
|
|
445
|
+
const boundaryRoot = resultBoundary(sourceAuthority);
|
|
446
|
+
const bundle = (
|
|
447
|
+
deps.readExecutionLocationResultBundle || readExecutionLocationResultBundle
|
|
448
|
+
)(bundlePath, {
|
|
449
|
+
boundaryRoot,
|
|
450
|
+
maxBytes: MAX_EXECUTION_LOCATION_RESULT_BUNDLE_BYTES,
|
|
451
|
+
...(deps.resultFileDependencies || {}),
|
|
452
|
+
});
|
|
453
|
+
return (
|
|
454
|
+
deps.verifyExecutionLocationResultBundle ||
|
|
455
|
+
verifyExecutionLocationResultBundle
|
|
456
|
+
)({
|
|
457
|
+
bundle,
|
|
458
|
+
sourceAuthority,
|
|
459
|
+
expectedHandoffId,
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
export function collectSessionExecutionLocationResult(
|
|
464
|
+
sessionId,
|
|
465
|
+
target,
|
|
466
|
+
options,
|
|
467
|
+
deps = {},
|
|
468
|
+
) {
|
|
469
|
+
const profile = (
|
|
470
|
+
deps.readExecutionLocationProfile || readExecutionLocationProfile
|
|
471
|
+
)(options.profile, deps);
|
|
472
|
+
const parseItems = (values, label) =>
|
|
473
|
+
(values || []).map((value) => parseResultFileSpec(value, label));
|
|
474
|
+
const artifacts = parseItems(options.artifact, "--artifact");
|
|
475
|
+
const evidence = parseItems(options.evidence, "--evidence");
|
|
476
|
+
const request = (
|
|
477
|
+
deps.createExecutionLocationTargetResultCollectionRequest ||
|
|
478
|
+
createExecutionLocationTargetResultCollectionRequest
|
|
479
|
+
)({
|
|
480
|
+
requestId: options.requestId,
|
|
481
|
+
sessionId,
|
|
482
|
+
target,
|
|
483
|
+
profile,
|
|
484
|
+
expectedTargetFactsDigest: options.expectedTargetFactsDigest,
|
|
485
|
+
expectedHandoffId: options.expectedHandoffId,
|
|
486
|
+
resultId: options.resultId,
|
|
487
|
+
summaryPath: options.summary,
|
|
488
|
+
diffPath: options.diff,
|
|
489
|
+
artifacts,
|
|
490
|
+
evidence,
|
|
491
|
+
});
|
|
492
|
+
const prior = (
|
|
493
|
+
deps.readVerifiedSessionExecutionLocationResultSettlement ||
|
|
494
|
+
readVerifiedSessionExecutionLocationResultSettlement
|
|
495
|
+
)(sessionId, request.requestId, { requestDigest: request.requestDigest });
|
|
496
|
+
if (prior !== null) {
|
|
497
|
+
if (prior.storage) {
|
|
498
|
+
const bundle = (
|
|
499
|
+
deps.readStoredExecutionLocationResultBundle ||
|
|
500
|
+
readStoredExecutionLocationResultBundle
|
|
501
|
+
)(prior.storage, deps.resultStoreOptions || {});
|
|
502
|
+
const verification = (
|
|
503
|
+
deps.verifyExecutionLocationResultBundle ||
|
|
504
|
+
verifyExecutionLocationResultBundle
|
|
505
|
+
)({
|
|
506
|
+
bundle,
|
|
507
|
+
sourceAuthority: {
|
|
508
|
+
sessionId: prior.sessionId,
|
|
509
|
+
headHash: prior.sourceHeadHash,
|
|
510
|
+
eventCount: prior.sourceEventCount,
|
|
511
|
+
},
|
|
512
|
+
expectedHandoffId: prior.handoffId,
|
|
513
|
+
});
|
|
514
|
+
if (
|
|
515
|
+
verification.verificationDigest !== prior.verificationDigest ||
|
|
516
|
+
bundle.bundleDigest !== prior.bundleDigest
|
|
517
|
+
) {
|
|
518
|
+
throw new Error("stored result bundle does not match settlement");
|
|
519
|
+
}
|
|
520
|
+
return Object.freeze({
|
|
521
|
+
...prior,
|
|
522
|
+
settlementAppended: false,
|
|
523
|
+
recovered: true,
|
|
524
|
+
bundleAvailable: true,
|
|
525
|
+
bundle,
|
|
526
|
+
verification,
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
return Object.freeze({
|
|
530
|
+
...prior,
|
|
531
|
+
settlementAppended: false,
|
|
532
|
+
recovered: true,
|
|
533
|
+
bundleAvailable: false,
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
const handoff = projectExecutionLocationHandoff(
|
|
537
|
+
sessionId,
|
|
538
|
+
target,
|
|
539
|
+
options.facts,
|
|
540
|
+
deps,
|
|
541
|
+
);
|
|
542
|
+
const readSourceAuthority = () => {
|
|
543
|
+
const authority = (
|
|
544
|
+
deps.getVerifiedSessionExecutionLocationAuthority ||
|
|
545
|
+
getVerifiedSessionExecutionLocationAuthority
|
|
546
|
+
)(sessionId);
|
|
547
|
+
return {
|
|
548
|
+
sessionId: authority.sessionId,
|
|
549
|
+
headHash: authority.headHash,
|
|
550
|
+
eventCount: authority.eventCount,
|
|
551
|
+
};
|
|
552
|
+
};
|
|
553
|
+
const collection = (
|
|
554
|
+
deps.collectExecutionLocationTargetResult ||
|
|
555
|
+
collectExecutionLocationTargetResult
|
|
556
|
+
)(
|
|
557
|
+
{
|
|
558
|
+
requestId: request.requestId,
|
|
559
|
+
handoff,
|
|
560
|
+
profile,
|
|
561
|
+
expectedTargetFactsDigest: options.expectedTargetFactsDigest,
|
|
562
|
+
expectedHandoffId: options.expectedHandoffId,
|
|
563
|
+
resultId: options.resultId,
|
|
564
|
+
summaryPath: options.summary,
|
|
565
|
+
diffPath: options.diff,
|
|
566
|
+
artifacts,
|
|
567
|
+
evidence,
|
|
568
|
+
readSourceAuthority,
|
|
569
|
+
},
|
|
570
|
+
deps,
|
|
571
|
+
);
|
|
572
|
+
if (collection.requestDigest !== request.requestDigest) {
|
|
573
|
+
throw new Error(
|
|
574
|
+
"result collection request digest changed during collection",
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
const storage = (
|
|
578
|
+
deps.storeExecutionLocationResultBundle ||
|
|
579
|
+
storeExecutionLocationResultBundle
|
|
580
|
+
)(collection.bundle, deps.resultStoreOptions || {});
|
|
581
|
+
const settlement = (
|
|
582
|
+
deps.settleSessionExecutionLocationResultCollection ||
|
|
583
|
+
settleSessionExecutionLocationResultCollection
|
|
584
|
+
)(sessionId, request.requestId, collection, storage.receipt);
|
|
585
|
+
return Object.freeze({
|
|
586
|
+
...collection,
|
|
587
|
+
storage: Object.freeze({ ...storage.receipt, stored: storage.stored }),
|
|
588
|
+
settlement,
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
function readSessionExecutionLocationResultReviewAuthority(
|
|
593
|
+
sessionId,
|
|
594
|
+
requestId,
|
|
595
|
+
deps,
|
|
596
|
+
) {
|
|
597
|
+
const settlement = (
|
|
598
|
+
deps.readVerifiedSessionExecutionLocationResultSettlement ||
|
|
599
|
+
readVerifiedSessionExecutionLocationResultSettlement
|
|
600
|
+
)(sessionId, requestId);
|
|
601
|
+
if (settlement === null) {
|
|
602
|
+
throw new Error("result collection settlement was not found");
|
|
603
|
+
}
|
|
604
|
+
if (!settlement.storage) {
|
|
605
|
+
throw new Error(
|
|
606
|
+
"legacy result settlement has no durable bundle available for review",
|
|
607
|
+
);
|
|
608
|
+
}
|
|
609
|
+
const bundle = (
|
|
610
|
+
deps.readStoredExecutionLocationResultBundle ||
|
|
611
|
+
readStoredExecutionLocationResultBundle
|
|
612
|
+
)(settlement.storage, deps.resultStoreOptions || {});
|
|
613
|
+
const review = (
|
|
614
|
+
deps.createExecutionLocationResultReview ||
|
|
615
|
+
createExecutionLocationResultReview
|
|
616
|
+
)({ settlement, bundle });
|
|
617
|
+
return Object.freeze({ settlement, bundle, review });
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
export function reviewSessionExecutionLocationResult(
|
|
621
|
+
sessionId,
|
|
622
|
+
requestId,
|
|
623
|
+
deps = {},
|
|
624
|
+
) {
|
|
625
|
+
return readSessionExecutionLocationResultReviewAuthority(
|
|
626
|
+
sessionId,
|
|
627
|
+
requestId,
|
|
628
|
+
deps,
|
|
629
|
+
).review;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
function selectResultPreviewRecord(bundle, selectorInput) {
|
|
633
|
+
const selector = String(selectorInput || "");
|
|
634
|
+
if (selector === "summary" || selector === "diff") {
|
|
635
|
+
return { kind: selector, record: bundle[selector] };
|
|
636
|
+
}
|
|
637
|
+
const match = /^(artifact|evidence):(sha256:[a-f0-9]{64})$/u.exec(selector);
|
|
638
|
+
if (!match) {
|
|
639
|
+
throw new Error(
|
|
640
|
+
"result preview item must be summary, diff, artifact:<sha256>, or evidence:<sha256>",
|
|
641
|
+
);
|
|
642
|
+
}
|
|
643
|
+
const [, kind, digest] = match;
|
|
644
|
+
const record = bundle[kind === "artifact" ? "artifacts" : "evidence"].find(
|
|
645
|
+
(entry) => entry.digest === digest,
|
|
646
|
+
);
|
|
647
|
+
if (!record) {
|
|
648
|
+
throw new Error(`reviewed ${kind} digest was not found`);
|
|
649
|
+
}
|
|
650
|
+
return { kind, record };
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
export function previewSessionExecutionLocationResult(
|
|
654
|
+
sessionId,
|
|
655
|
+
requestId,
|
|
656
|
+
reviewDigest,
|
|
657
|
+
item,
|
|
658
|
+
deps = {},
|
|
659
|
+
) {
|
|
660
|
+
const loaded = readSessionExecutionLocationResultReviewAuthority(
|
|
661
|
+
sessionId,
|
|
662
|
+
requestId,
|
|
663
|
+
deps,
|
|
664
|
+
);
|
|
665
|
+
assertReviewDigest(loaded.review, reviewDigest);
|
|
666
|
+
const selected = selectResultPreviewRecord(loaded.bundle, item);
|
|
667
|
+
const bytes = Buffer.from(selected.record.contentBase64, "base64");
|
|
668
|
+
const reviewedRecord =
|
|
669
|
+
selected.kind === "artifact" || selected.kind === "evidence"
|
|
670
|
+
? loaded.review[
|
|
671
|
+
selected.kind === "artifact" ? "artifacts" : "evidence"
|
|
672
|
+
].find((entry) => entry.digest === selected.record.digest)
|
|
673
|
+
: loaded.review[selected.kind];
|
|
674
|
+
if (
|
|
675
|
+
bytes.byteLength !== selected.record.byteLength ||
|
|
676
|
+
reviewedRecord?.digest !== selected.record.digest ||
|
|
677
|
+
reviewedRecord?.byteLength !== selected.record.byteLength ||
|
|
678
|
+
reviewedRecord?.mediaType !== selected.record.mediaType
|
|
679
|
+
) {
|
|
680
|
+
throw new Error(
|
|
681
|
+
"result preview content no longer matches review authority",
|
|
682
|
+
);
|
|
683
|
+
}
|
|
684
|
+
return Object.freeze({
|
|
685
|
+
schema: EXECUTION_LOCATION_RESULT_PREVIEW_SCHEMA,
|
|
686
|
+
sessionId,
|
|
687
|
+
requestId,
|
|
688
|
+
reviewDigest: loaded.review.reviewDigest,
|
|
689
|
+
item: String(item),
|
|
690
|
+
kind: selected.kind,
|
|
691
|
+
mediaType: selected.record.mediaType,
|
|
692
|
+
byteLength: selected.record.byteLength,
|
|
693
|
+
digest: selected.record.digest,
|
|
694
|
+
bytes,
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
export function importSessionExecutionLocationResultArtifact(
|
|
699
|
+
sessionId,
|
|
700
|
+
requestId,
|
|
701
|
+
reviewDigest,
|
|
702
|
+
item,
|
|
703
|
+
deps = {},
|
|
704
|
+
) {
|
|
705
|
+
const preview = previewSessionExecutionLocationResult(
|
|
706
|
+
sessionId,
|
|
707
|
+
requestId,
|
|
708
|
+
reviewDigest,
|
|
709
|
+
item,
|
|
710
|
+
deps,
|
|
711
|
+
);
|
|
712
|
+
return (
|
|
713
|
+
deps.importExecutionLocationResultArtifact ||
|
|
714
|
+
importExecutionLocationResultArtifact
|
|
715
|
+
)(preview, { artifactStore: deps.artifactStore });
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
function terminalSafeText(bytes) {
|
|
719
|
+
const text = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
720
|
+
return text.replace(
|
|
721
|
+
// The explicit control ranges are the terminal-injection boundary.
|
|
722
|
+
// eslint-disable-next-line no-control-regex
|
|
723
|
+
/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f\u200e\u200f\u202a-\u202e\u2066-\u2069]/gu,
|
|
724
|
+
(character) =>
|
|
725
|
+
character.codePointAt(0) <= 0xff
|
|
726
|
+
? `\\x${character.codePointAt(0).toString(16).padStart(2, "0")}`
|
|
727
|
+
: `\\u${character.codePointAt(0).toString(16).padStart(4, "0")}`,
|
|
728
|
+
);
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
export function writeSessionExecutionLocationResultPreview(preview, deps = {}) {
|
|
732
|
+
const output = deps.stdout || process.stdout;
|
|
733
|
+
const isTerminal = deps.isTTY ?? output.isTTY === true;
|
|
734
|
+
if (!isTerminal) {
|
|
735
|
+
output.write(preview.bytes);
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
if (!["summary", "diff"].includes(preview.kind)) {
|
|
739
|
+
throw new Error(
|
|
740
|
+
"binary artifact/evidence preview requires redirected stdout",
|
|
741
|
+
);
|
|
742
|
+
}
|
|
743
|
+
output.write(terminalSafeText(preview.bytes));
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
function assertReviewDigest(review, expectedReviewDigest) {
|
|
747
|
+
if (review.reviewDigest !== String(expectedReviewDigest || "")) {
|
|
748
|
+
throw new Error(
|
|
749
|
+
"result apply review digest does not match stored authority",
|
|
750
|
+
);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
function resultApplyProjection(receipt, options = {}) {
|
|
755
|
+
return Object.freeze({
|
|
756
|
+
...receipt,
|
|
757
|
+
recovered: options.recovered === true,
|
|
758
|
+
allowed: receipt.applied === true,
|
|
759
|
+
stage: options.stage || (receipt.applied ? "complete" : receipt.status),
|
|
760
|
+
process: options.process || null,
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
function settleResultApplyFromTransaction(
|
|
765
|
+
sessionId,
|
|
766
|
+
applyId,
|
|
767
|
+
transactionState,
|
|
768
|
+
deps,
|
|
769
|
+
options = {},
|
|
770
|
+
) {
|
|
771
|
+
const terminalTransaction = (
|
|
772
|
+
deps.terminalExecutionLocationResultApplyTransaction ||
|
|
773
|
+
terminalExecutionLocationResultApplyTransaction
|
|
774
|
+
)(transactionState);
|
|
775
|
+
const outcome =
|
|
776
|
+
transactionState.state === "committed" ? "applied" : "rolled_back";
|
|
777
|
+
const receipt = (
|
|
778
|
+
deps.settleSessionExecutionLocationResultApply ||
|
|
779
|
+
settleSessionExecutionLocationResultApply
|
|
780
|
+
)(sessionId, applyId, outcome, terminalTransaction);
|
|
781
|
+
return resultApplyProjection(receipt, {
|
|
782
|
+
recovered: options.recovered,
|
|
783
|
+
stage: options.stage || (outcome === "applied" ? "complete" : "recovery"),
|
|
784
|
+
process: options.process,
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
function readPriorResultApply(sessionId, applyId, deps) {
|
|
789
|
+
return (
|
|
790
|
+
deps.readVerifiedSessionExecutionLocationResultApply ||
|
|
791
|
+
readVerifiedSessionExecutionLocationResultApply
|
|
792
|
+
)(sessionId, applyId);
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
function inspectResultApplyTransaction(receipt, deps) {
|
|
796
|
+
const broker = deps.executionBroker || executionBroker;
|
|
797
|
+
if (typeof broker.inspectWorkspaceTransaction !== "function") {
|
|
798
|
+
throw new Error("result apply transaction inspection is unavailable");
|
|
799
|
+
}
|
|
800
|
+
return broker.inspectWorkspaceTransaction(receipt.transaction.id, {
|
|
801
|
+
...(deps.transactionStateDir ? { stateDir: deps.transactionStateDir } : {}),
|
|
802
|
+
});
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
export function applySessionExecutionLocationResult(
|
|
806
|
+
sessionId,
|
|
807
|
+
options,
|
|
808
|
+
deps = {},
|
|
809
|
+
) {
|
|
810
|
+
const loaded = readSessionExecutionLocationResultReviewAuthority(
|
|
811
|
+
sessionId,
|
|
812
|
+
options.requestId,
|
|
813
|
+
deps,
|
|
814
|
+
);
|
|
815
|
+
assertReviewDigest(loaded.review, options.reviewDigest);
|
|
816
|
+
const prior = readPriorResultApply(sessionId, options.applyId, deps);
|
|
817
|
+
if (prior !== null && prior.terminal !== null) {
|
|
818
|
+
if (
|
|
819
|
+
prior.requestId !== options.requestId ||
|
|
820
|
+
prior.reviewDigest !== loaded.review.reviewDigest
|
|
821
|
+
) {
|
|
822
|
+
throw new Error("result apply id is already bound to different inputs");
|
|
823
|
+
}
|
|
824
|
+
return resultApplyProjection(prior, { recovered: true });
|
|
825
|
+
}
|
|
826
|
+
if (prior !== null) {
|
|
827
|
+
if (
|
|
828
|
+
prior.requestId !== options.requestId ||
|
|
829
|
+
prior.reviewDigest !== loaded.review.reviewDigest
|
|
830
|
+
) {
|
|
831
|
+
throw new Error("result apply id is already bound to different inputs");
|
|
832
|
+
}
|
|
833
|
+
const transactionState = inspectResultApplyTransaction(prior, deps);
|
|
834
|
+
if (["committed", "rolled_back"].includes(transactionState.state)) {
|
|
835
|
+
return settleResultApplyFromTransaction(
|
|
836
|
+
sessionId,
|
|
837
|
+
options.applyId,
|
|
838
|
+
transactionState,
|
|
839
|
+
deps,
|
|
840
|
+
{ recovered: true },
|
|
841
|
+
);
|
|
842
|
+
}
|
|
843
|
+
throw new Error(
|
|
844
|
+
`result apply recovery is required for transaction ${prior.transaction.id}`,
|
|
845
|
+
);
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
const authority = (
|
|
849
|
+
deps.getVerifiedSessionExecutionLocationAuthority ||
|
|
850
|
+
getVerifiedSessionExecutionLocationAuthority
|
|
851
|
+
)(sessionId);
|
|
852
|
+
if (
|
|
853
|
+
authority.headHash !== loaded.settlement.settlementEventHash ||
|
|
854
|
+
authority.eventCount !== loaded.settlement.settlementEventCount
|
|
855
|
+
) {
|
|
856
|
+
throw new Error("source session advanced after result settlement");
|
|
857
|
+
}
|
|
858
|
+
const broker = deps.executionBroker || executionBroker;
|
|
859
|
+
const source = (
|
|
860
|
+
deps.verifyExecutionLocationResultApplySourceGit ||
|
|
861
|
+
verifyExecutionLocationResultApplySourceGit
|
|
862
|
+
)(authority, {
|
|
863
|
+
broker,
|
|
864
|
+
workspaceRoot: options.workspace,
|
|
865
|
+
platform: deps.platform,
|
|
866
|
+
});
|
|
867
|
+
const diffBytes = Buffer.from(loaded.bundle.diff.contentBase64, "base64");
|
|
868
|
+
const execution = (
|
|
869
|
+
deps.executeControlledExecutionLocationResultApply ||
|
|
870
|
+
executeControlledExecutionLocationResultApply
|
|
871
|
+
)({
|
|
872
|
+
broker,
|
|
873
|
+
sessionId,
|
|
874
|
+
applyId: options.applyId,
|
|
875
|
+
workspaceRoot: source.workspaceRoot,
|
|
876
|
+
diffBytes,
|
|
877
|
+
...(deps.transactionStateDir ? { stateDir: deps.transactionStateDir } : {}),
|
|
878
|
+
onPrepared: (transaction) => {
|
|
879
|
+
const pinnedSource = (
|
|
880
|
+
deps.verifyExecutionLocationResultApplySourceGit ||
|
|
881
|
+
verifyExecutionLocationResultApplySourceGit
|
|
882
|
+
)(authority, {
|
|
883
|
+
broker,
|
|
884
|
+
workspaceRoot: source.workspaceRoot,
|
|
885
|
+
platform: deps.platform,
|
|
886
|
+
});
|
|
887
|
+
if (
|
|
888
|
+
pinnedSource.sourceGit.rootDigest !== source.sourceGit.rootDigest ||
|
|
889
|
+
pinnedSource.sourceGit.commit !== source.sourceGit.commit
|
|
890
|
+
) {
|
|
891
|
+
throw new Error("source Git identity changed during apply preparation");
|
|
892
|
+
}
|
|
893
|
+
return (
|
|
894
|
+
deps.reserveSessionExecutionLocationResultApply ||
|
|
895
|
+
reserveSessionExecutionLocationResultApply
|
|
896
|
+
)(
|
|
897
|
+
sessionId,
|
|
898
|
+
options.applyId,
|
|
899
|
+
loaded.review,
|
|
900
|
+
pinnedSource.sourceGit,
|
|
901
|
+
transaction,
|
|
902
|
+
);
|
|
903
|
+
},
|
|
904
|
+
});
|
|
905
|
+
if (execution.stage === "reservation") {
|
|
906
|
+
const reserved = readPriorResultApply(sessionId, options.applyId, deps);
|
|
907
|
+
if (reserved === null) throw execution.error;
|
|
908
|
+
if (
|
|
909
|
+
reserved.reviewDigest !== loaded.review.reviewDigest ||
|
|
910
|
+
reserved.transaction.id !== execution.transaction.id
|
|
911
|
+
) {
|
|
912
|
+
throw new Error("result apply reservation response is ambiguous");
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
const receipt = (
|
|
916
|
+
deps.settleSessionExecutionLocationResultApply ||
|
|
917
|
+
settleSessionExecutionLocationResultApply
|
|
918
|
+
)(sessionId, options.applyId, execution.outcome, execution.transaction);
|
|
919
|
+
return resultApplyProjection(receipt, {
|
|
920
|
+
stage: execution.stage,
|
|
921
|
+
process: execution.process,
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
export function recoverSessionExecutionLocationResultApply(
|
|
926
|
+
sessionId,
|
|
927
|
+
options,
|
|
928
|
+
deps = {},
|
|
929
|
+
) {
|
|
930
|
+
const loaded = readSessionExecutionLocationResultReviewAuthority(
|
|
931
|
+
sessionId,
|
|
932
|
+
options.requestId,
|
|
933
|
+
deps,
|
|
934
|
+
);
|
|
935
|
+
assertReviewDigest(loaded.review, options.reviewDigest);
|
|
936
|
+
const prior = readPriorResultApply(sessionId, options.applyId, deps);
|
|
937
|
+
if (prior === null) {
|
|
938
|
+
throw new Error("result apply reservation was not found");
|
|
939
|
+
}
|
|
940
|
+
if (
|
|
941
|
+
prior.requestId !== options.requestId ||
|
|
942
|
+
prior.reviewDigest !== loaded.review.reviewDigest
|
|
943
|
+
) {
|
|
944
|
+
throw new Error("result apply recovery authority does not match review");
|
|
945
|
+
}
|
|
946
|
+
if (prior.terminal !== null) {
|
|
947
|
+
return resultApplyProjection(prior, { recovered: true });
|
|
948
|
+
}
|
|
949
|
+
const broker = deps.executionBroker || executionBroker;
|
|
950
|
+
const authority = (
|
|
951
|
+
deps.getVerifiedSessionExecutionLocationAuthority ||
|
|
952
|
+
getVerifiedSessionExecutionLocationAuthority
|
|
953
|
+
)(sessionId);
|
|
954
|
+
const source = (
|
|
955
|
+
deps.verifyExecutionLocationResultApplySourceGit ||
|
|
956
|
+
verifyExecutionLocationResultApplySourceGit
|
|
957
|
+
)(authority, {
|
|
958
|
+
broker,
|
|
959
|
+
workspaceRoot: options.workspace,
|
|
960
|
+
platform: deps.platform,
|
|
961
|
+
});
|
|
962
|
+
let transactionState = inspectResultApplyTransaction(prior, deps);
|
|
963
|
+
if (!["committed", "rolled_back"].includes(transactionState.state)) {
|
|
964
|
+
if (typeof broker.recoverWorkspaceTransactions !== "function") {
|
|
965
|
+
throw new Error("result apply workspace recovery is unavailable");
|
|
966
|
+
}
|
|
967
|
+
broker.recoverWorkspaceTransactions({
|
|
968
|
+
id: prior.transaction.id,
|
|
969
|
+
workspaceRoot: source.workspaceRoot,
|
|
970
|
+
reason: "explicit session result apply recovery",
|
|
971
|
+
...(deps.transactionStateDir
|
|
972
|
+
? { stateDir: deps.transactionStateDir }
|
|
973
|
+
: {}),
|
|
974
|
+
});
|
|
975
|
+
transactionState = inspectResultApplyTransaction(prior, deps);
|
|
976
|
+
}
|
|
977
|
+
if (!["committed", "rolled_back"].includes(transactionState.state)) {
|
|
978
|
+
throw new Error(
|
|
979
|
+
`result apply transaction still requires manual recovery: ${transactionState.state}`,
|
|
980
|
+
);
|
|
981
|
+
}
|
|
982
|
+
return settleResultApplyFromTransaction(
|
|
983
|
+
sessionId,
|
|
984
|
+
options.applyId,
|
|
985
|
+
transactionState,
|
|
986
|
+
deps,
|
|
987
|
+
{ recovered: true, stage: "recovery" },
|
|
988
|
+
);
|
|
989
|
+
}
|
|
990
|
+
|
|
317
991
|
function renderBinding(binding) {
|
|
318
992
|
const git = binding.source.git;
|
|
319
993
|
return [
|
|
@@ -350,6 +1024,57 @@ function writeProjection(projection, options = {}) {
|
|
|
350
1024
|
);
|
|
351
1025
|
return;
|
|
352
1026
|
}
|
|
1027
|
+
if (projection.schema === EXECUTION_LOCATION_RESULT_BUNDLE_SCHEMA) {
|
|
1028
|
+
process.stdout.write(
|
|
1029
|
+
`RESULT BUNDLE ${projection.resultId}\nBundle: ${projection.bundleDigest}\nBytes: ${projection.totalBytes}\nUse --json to transfer the canonical bundle bytes.\n`,
|
|
1030
|
+
);
|
|
1031
|
+
return;
|
|
1032
|
+
}
|
|
1033
|
+
if (projection.schema === EXECUTION_LOCATION_RESULT_VERIFICATION_SCHEMA) {
|
|
1034
|
+
process.stdout.write(
|
|
1035
|
+
`RESULT VERIFIED ${projection.resultId}\nBundle: ${projection.bundleDigest}\nVerification: ${projection.verificationDigest}\nApplied: no\n`,
|
|
1036
|
+
);
|
|
1037
|
+
return;
|
|
1038
|
+
}
|
|
1039
|
+
if (projection.schema === EXECUTION_LOCATION_RESULT_REVIEW_SCHEMA) {
|
|
1040
|
+
process.stdout.write(
|
|
1041
|
+
`RESULT REVIEWED ${projection.resultId}\nReview: ${projection.reviewDigest}\nBundle: ${projection.bundleDigest}\nSummary: ${projection.summary.byteLength} bytes (${projection.summary.digest})\nDiff: ${projection.diff.byteLength} bytes (${projection.diff.digest})\nApplied: no\n`,
|
|
1042
|
+
);
|
|
1043
|
+
return;
|
|
1044
|
+
}
|
|
1045
|
+
if (projection.schema === EXECUTION_LOCATION_RESULT_ARTIFACT_IMPORT_SCHEMA) {
|
|
1046
|
+
process.stdout.write(
|
|
1047
|
+
`RESULT ARTIFACT ${projection.imported ? "IMPORTED" : "AVAILABLE"} ${projection.artifact.id}\nImport: ${projection.importDigest}\nReview: ${projection.source.reviewDigest}\nItem: ${projection.source.item}\nArtifact bytes: ${projection.artifact.size} (${projection.source.sourceDigest})\nContent emitted: no\n`,
|
|
1048
|
+
);
|
|
1049
|
+
return;
|
|
1050
|
+
}
|
|
1051
|
+
if (
|
|
1052
|
+
projection.schema === SESSION_EXECUTION_LOCATION_RESULT_APPLY_RECEIPT_SCHEMA
|
|
1053
|
+
) {
|
|
1054
|
+
process.stdout.write(
|
|
1055
|
+
`RESULT APPLY ${projection.applied ? "APPLIED" : "ROLLED BACK"} ${projection.applyId}\nReview: ${projection.reviewDigest}\nTransaction: ${projection.transaction.id}\nEvidence: ${projection.transaction.evidenceDigest || "pending"}\nRecovered: ${projection.recovered ? "yes" : "no"}\n`,
|
|
1056
|
+
);
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
if (
|
|
1060
|
+
projection.schema === EXECUTION_LOCATION_TARGET_RESULT_COLLECTION_SCHEMA
|
|
1061
|
+
) {
|
|
1062
|
+
process.stdout.write(
|
|
1063
|
+
`RESULT COLLECTED ${projection.resultId}\nBundle: ${projection.bundleDigest}\nCollection: ${projection.collectionDigest}\nApplied: no\nGaps: ${projection.gaps.join(", ")}\n`,
|
|
1064
|
+
);
|
|
1065
|
+
return;
|
|
1066
|
+
}
|
|
1067
|
+
if (
|
|
1068
|
+
[
|
|
1069
|
+
SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_RECEIPT_SCHEMA,
|
|
1070
|
+
SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_RECEIPT_SCHEMA_V1,
|
|
1071
|
+
].includes(projection.schema)
|
|
1072
|
+
) {
|
|
1073
|
+
process.stdout.write(
|
|
1074
|
+
`RESULT COLLECTION SETTLED ${projection.resultId}\nRequest: ${projection.requestId}\nSettlement: ${projection.receiptDigest}\nBundle bytes available: ${projection.bundleAvailable ? "yes" : "no"}\nApplied: no\n`,
|
|
1075
|
+
);
|
|
1076
|
+
return;
|
|
1077
|
+
}
|
|
353
1078
|
if (projection.schema === "chainlesschain.session-replica-install/v1") {
|
|
354
1079
|
process.stdout.write(
|
|
355
1080
|
`${projection.installed ? "INSTALLED" : "ALREADY PRESENT"} ${projection.sessionId}\nReceipt: ${projection.receiptDigest}\n`,
|
|
@@ -399,6 +1124,16 @@ function runAction(action, options = {}) {
|
|
|
399
1124
|
}
|
|
400
1125
|
}
|
|
401
1126
|
|
|
1127
|
+
function runPreviewAction(action, deps = {}) {
|
|
1128
|
+
try {
|
|
1129
|
+
writeSessionExecutionLocationResultPreview(action(), deps);
|
|
1130
|
+
return 0;
|
|
1131
|
+
} catch (error) {
|
|
1132
|
+
process.stderr.write(`Execution location failed: ${error.message}\n`);
|
|
1133
|
+
return 1;
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
|
|
402
1137
|
export function registerSessionLocationSubcommands(session, deps = {}) {
|
|
403
1138
|
const location = session
|
|
404
1139
|
.command("location")
|
|
@@ -584,4 +1319,236 @@ export function registerSessionLocationSubcommands(session, deps = {}) {
|
|
|
584
1319
|
options,
|
|
585
1320
|
);
|
|
586
1321
|
});
|
|
1322
|
+
|
|
1323
|
+
location
|
|
1324
|
+
.command("result-pack <id>")
|
|
1325
|
+
.description(
|
|
1326
|
+
"Build a bounded result bundle from a verified target handoff session",
|
|
1327
|
+
)
|
|
1328
|
+
.requiredOption("--result-id <id>", "Stable result bundle id")
|
|
1329
|
+
.requiredOption(
|
|
1330
|
+
"--summary <path>",
|
|
1331
|
+
"UTF-8 summary file inside the data boundary",
|
|
1332
|
+
)
|
|
1333
|
+
.requiredOption("--diff <path>", "Diff file inside the data boundary")
|
|
1334
|
+
.option(
|
|
1335
|
+
"--artifact <media-type=path>",
|
|
1336
|
+
"Artifact bytes to include (repeatable)",
|
|
1337
|
+
collectResultFileSpec,
|
|
1338
|
+
[],
|
|
1339
|
+
)
|
|
1340
|
+
.option(
|
|
1341
|
+
"--evidence <media-type=path>",
|
|
1342
|
+
"Evidence bytes to include (repeatable)",
|
|
1343
|
+
collectResultFileSpec,
|
|
1344
|
+
[],
|
|
1345
|
+
)
|
|
1346
|
+
.option("--json", "Write the canonical bundle including base64 content")
|
|
1347
|
+
.action((id, options) => {
|
|
1348
|
+
process.exitCode = runAction(
|
|
1349
|
+
() => createSessionExecutionLocationResultBundle(id, options, deps),
|
|
1350
|
+
options,
|
|
1351
|
+
);
|
|
1352
|
+
});
|
|
1353
|
+
|
|
1354
|
+
location
|
|
1355
|
+
.command("result-verify <id>")
|
|
1356
|
+
.description(
|
|
1357
|
+
"Rehash a returned bundle and bind it to the unchanged source session",
|
|
1358
|
+
)
|
|
1359
|
+
.requiredOption("--bundle <path>", "Returned canonical bundle JSON")
|
|
1360
|
+
.requiredOption(
|
|
1361
|
+
"--expected-handoff-id <sha256>",
|
|
1362
|
+
"Exact handoff id accepted before target execution",
|
|
1363
|
+
)
|
|
1364
|
+
.option("--json", "Machine-readable content-free verification receipt")
|
|
1365
|
+
.action((id, options) => {
|
|
1366
|
+
process.exitCode = runAction(
|
|
1367
|
+
() =>
|
|
1368
|
+
verifySessionExecutionLocationResultBundle(
|
|
1369
|
+
id,
|
|
1370
|
+
options.bundle,
|
|
1371
|
+
options.expectedHandoffId,
|
|
1372
|
+
deps,
|
|
1373
|
+
),
|
|
1374
|
+
options,
|
|
1375
|
+
);
|
|
1376
|
+
});
|
|
1377
|
+
|
|
1378
|
+
location
|
|
1379
|
+
.command("result-collect <id> <target>")
|
|
1380
|
+
.description(
|
|
1381
|
+
"Fetch a target result through the fixed transport and verify it on source",
|
|
1382
|
+
)
|
|
1383
|
+
.requiredOption("--facts <path>", "Accepted handoff facts JSON")
|
|
1384
|
+
.requiredOption("--profile <path>", "Secret-free target profile JSON")
|
|
1385
|
+
.requiredOption(
|
|
1386
|
+
"--expected-target-facts-digest <sha256>",
|
|
1387
|
+
"Exact stable target facts digest accepted before execution",
|
|
1388
|
+
)
|
|
1389
|
+
.requiredOption(
|
|
1390
|
+
"--expected-handoff-id <sha256>",
|
|
1391
|
+
"Exact canonical target handoff id",
|
|
1392
|
+
)
|
|
1393
|
+
.requiredOption(
|
|
1394
|
+
"--request-id <id>",
|
|
1395
|
+
"Stable idempotency id for canonical collection settlement",
|
|
1396
|
+
)
|
|
1397
|
+
.requiredOption("--result-id <id>", "Stable result bundle id")
|
|
1398
|
+
.requiredOption("--summary <path>", "Target summary path")
|
|
1399
|
+
.requiredOption("--diff <path>", "Target diff path")
|
|
1400
|
+
.option(
|
|
1401
|
+
"--artifact <media-type=path>",
|
|
1402
|
+
"Target artifact bytes to include (repeatable)",
|
|
1403
|
+
collectResultFileSpec,
|
|
1404
|
+
[],
|
|
1405
|
+
)
|
|
1406
|
+
.option(
|
|
1407
|
+
"--evidence <media-type=path>",
|
|
1408
|
+
"Target evidence bytes to include (repeatable)",
|
|
1409
|
+
collectResultFileSpec,
|
|
1410
|
+
[],
|
|
1411
|
+
)
|
|
1412
|
+
.option(
|
|
1413
|
+
"--json",
|
|
1414
|
+
"Machine-readable collection with bundle bytes and verification receipt",
|
|
1415
|
+
)
|
|
1416
|
+
.action((id, target, options) => {
|
|
1417
|
+
process.exitCode = runAction(
|
|
1418
|
+
() => collectSessionExecutionLocationResult(id, target, options, deps),
|
|
1419
|
+
options,
|
|
1420
|
+
);
|
|
1421
|
+
});
|
|
1422
|
+
|
|
1423
|
+
location
|
|
1424
|
+
.command("result-review <id>")
|
|
1425
|
+
.description(
|
|
1426
|
+
"Review stored result metadata without exposing or applying content",
|
|
1427
|
+
)
|
|
1428
|
+
.requiredOption(
|
|
1429
|
+
"--request-id <id>",
|
|
1430
|
+
"Canonical result collection request id",
|
|
1431
|
+
)
|
|
1432
|
+
.option("--json", "Machine-readable content-free review authority")
|
|
1433
|
+
.action((id, options) => {
|
|
1434
|
+
process.exitCode = runAction(
|
|
1435
|
+
() => reviewSessionExecutionLocationResult(id, options.requestId, deps),
|
|
1436
|
+
options,
|
|
1437
|
+
);
|
|
1438
|
+
});
|
|
1439
|
+
|
|
1440
|
+
location
|
|
1441
|
+
.command("result-preview <id>")
|
|
1442
|
+
.description(
|
|
1443
|
+
"Explicitly stream one reviewed result item without changing the workspace",
|
|
1444
|
+
)
|
|
1445
|
+
.requiredOption(
|
|
1446
|
+
"--request-id <id>",
|
|
1447
|
+
"Canonical result collection request id",
|
|
1448
|
+
)
|
|
1449
|
+
.requiredOption(
|
|
1450
|
+
"--review-digest <sha256>",
|
|
1451
|
+
"Exact content-free review digest accepted by the operator",
|
|
1452
|
+
)
|
|
1453
|
+
.requiredOption(
|
|
1454
|
+
"--item <selector>",
|
|
1455
|
+
"summary, diff, artifact:<sha256>, or evidence:<sha256>",
|
|
1456
|
+
)
|
|
1457
|
+
.action((id, options) => {
|
|
1458
|
+
process.exitCode = runPreviewAction(
|
|
1459
|
+
() =>
|
|
1460
|
+
previewSessionExecutionLocationResult(
|
|
1461
|
+
id,
|
|
1462
|
+
options.requestId,
|
|
1463
|
+
options.reviewDigest,
|
|
1464
|
+
options.item,
|
|
1465
|
+
deps,
|
|
1466
|
+
),
|
|
1467
|
+
deps.previewOutputDependencies || {},
|
|
1468
|
+
);
|
|
1469
|
+
});
|
|
1470
|
+
|
|
1471
|
+
location
|
|
1472
|
+
.command("result-import <id>")
|
|
1473
|
+
.description(
|
|
1474
|
+
"Import one explicitly reviewed result item into the managed ArtifactStore",
|
|
1475
|
+
)
|
|
1476
|
+
.requiredOption(
|
|
1477
|
+
"--request-id <id>",
|
|
1478
|
+
"Canonical result collection request id",
|
|
1479
|
+
)
|
|
1480
|
+
.requiredOption(
|
|
1481
|
+
"--review-digest <sha256>",
|
|
1482
|
+
"Exact content-free review digest accepted by the operator",
|
|
1483
|
+
)
|
|
1484
|
+
.requiredOption(
|
|
1485
|
+
"--item <selector>",
|
|
1486
|
+
"summary, diff, artifact:<sha256>, or evidence:<sha256>",
|
|
1487
|
+
)
|
|
1488
|
+
.option("--json", "Machine-readable content-free import receipt")
|
|
1489
|
+
.action((id, options) => {
|
|
1490
|
+
process.exitCode = runAction(
|
|
1491
|
+
() =>
|
|
1492
|
+
importSessionExecutionLocationResultArtifact(
|
|
1493
|
+
id,
|
|
1494
|
+
options.requestId,
|
|
1495
|
+
options.reviewDigest,
|
|
1496
|
+
options.item,
|
|
1497
|
+
deps,
|
|
1498
|
+
),
|
|
1499
|
+
options,
|
|
1500
|
+
);
|
|
1501
|
+
});
|
|
1502
|
+
|
|
1503
|
+
location
|
|
1504
|
+
.command("result-apply <id>")
|
|
1505
|
+
.description(
|
|
1506
|
+
"Apply one explicitly reviewed stored diff inside a durable workspace transaction",
|
|
1507
|
+
)
|
|
1508
|
+
.requiredOption(
|
|
1509
|
+
"--request-id <id>",
|
|
1510
|
+
"Canonical result collection request id",
|
|
1511
|
+
)
|
|
1512
|
+
.requiredOption("--apply-id <id>", "Stable result apply idempotency id")
|
|
1513
|
+
.requiredOption(
|
|
1514
|
+
"--review-digest <sha256>",
|
|
1515
|
+
"Exact content-free review digest accepted by the operator",
|
|
1516
|
+
)
|
|
1517
|
+
.option(
|
|
1518
|
+
"--workspace <path>",
|
|
1519
|
+
"Exact source Git workspace (defaults to session authority)",
|
|
1520
|
+
)
|
|
1521
|
+
.option("--json", "Machine-readable content-free apply receipt")
|
|
1522
|
+
.action((id, options) => {
|
|
1523
|
+
process.exitCode = runAction(
|
|
1524
|
+
() => applySessionExecutionLocationResult(id, options, deps),
|
|
1525
|
+
options,
|
|
1526
|
+
);
|
|
1527
|
+
});
|
|
1528
|
+
|
|
1529
|
+
location
|
|
1530
|
+
.command("result-apply-recover <id>")
|
|
1531
|
+
.description(
|
|
1532
|
+
"Explicitly recover a reserved result apply without replaying its diff",
|
|
1533
|
+
)
|
|
1534
|
+
.requiredOption(
|
|
1535
|
+
"--request-id <id>",
|
|
1536
|
+
"Canonical result collection request id",
|
|
1537
|
+
)
|
|
1538
|
+
.requiredOption("--apply-id <id>", "Reserved result apply id")
|
|
1539
|
+
.requiredOption(
|
|
1540
|
+
"--review-digest <sha256>",
|
|
1541
|
+
"Exact content-free review digest bound to the reservation",
|
|
1542
|
+
)
|
|
1543
|
+
.option(
|
|
1544
|
+
"--workspace <path>",
|
|
1545
|
+
"Exact source Git workspace (defaults to session authority)",
|
|
1546
|
+
)
|
|
1547
|
+
.option("--json", "Machine-readable content-free recovery receipt")
|
|
1548
|
+
.action((id, options) => {
|
|
1549
|
+
process.exitCode = runAction(
|
|
1550
|
+
() => recoverSessionExecutionLocationResultApply(id, options, deps),
|
|
1551
|
+
options,
|
|
1552
|
+
);
|
|
1553
|
+
});
|
|
587
1554
|
}
|