chainlesschain 0.166.59 → 0.166.63
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 +38 -8
- package/package.json +4 -1
- package/src/assets/web-panel/assets/{AIOps-B9i3kk5f.js → AIOps-CfPrpABR.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-DGMs1wBm.js → ActionButton-Bkv1erki.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-D-JGeynM.js → Analytics-fY_7epoU.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DLECnXlP.js → AppLayout-DegaN-aa.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-CwaTiXN4.js → Artifacts-90-UNTVE.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-BCb7s5Ky.js → Audit-BRQ1F4sA.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-D4IOzvKs.js → BackgroundAgents-Cb85uP7O.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-Cknunk10.js → Backup-CrLBSWQK.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-DnU8pbUh.js → BaseInput-DditUW5B.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-DOouYIhz.js → Chat-0XozleDQ.js} +5 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-8QXBJvgy.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-BrumNw6V.js → Checkbox-C2Ck_3ju.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-B4E_uI_N.js → Codegen-Chjw-MS7.js} +1 -1
- package/src/assets/web-panel/assets/{Col-C7H2sdaL.js → Col-B_w8_Oka.js} +1 -1
- package/src/assets/web-panel/assets/{Community-BFdzcMSl.js → Community-XAqxPnXq.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BzVXohrg.js → Compact-BX_3GJ3m.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-B_4QcuSH.js → Compliance-DE3kIC9z.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DjuQzJx8.js → Cowork-DPBYp1ey.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-Bf2iY-1-.js → Cron-D9cknqzn.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CY9QW7IT.js → Crosschain-BzHrGWY9.js} +1 -1
- package/src/assets/web-panel/assets/{DID-kDZBvaKr.js → DID-BuD8TkZl.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-DoYboS3g.js → Dashboard-BbxMuZVK.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-LLEzI6l1.js → Dropdown-jq0ki-tE.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-D2kmSvkg.js → EmailListRenderer-RiMvINxT.js} +1 -1
- package/src/assets/web-panel/assets/{EvolutionSettings-DHj2yUGZ.js → EvolutionSettings-DE-URi9i.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-B7Hg7fR0.js → FamilyGuardDashboard-DV3ao62-.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-CUdwU6aH.js → Federation-BF6BmBPg.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-D1KrwjwY.js → FormItemContext-CKTX59j2.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-CXGLoHfw.js → GenericCardRenderer-DZkH-CTs.js} +1 -1
- package/src/assets/web-panel/assets/{Git-TG3Q9JWG.js → Git-B5JYb-w-.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BJD7h_fv.js → Governance-D3WfDZ6W.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-Dky4l_bZ.js → Inference-DoSvfDUk.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-CCx9aXBV.js → KnowledgeGraph-DUDIzN97.js} +1 -1
- package/src/assets/web-panel/assets/Logs-JfJerfFD.js +2 -0
- package/src/assets/web-panel/assets/MarkdownRenderer-DXgA7cZm.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-BzL6KJMX.js → Marketplace-BpVrOM_V.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-BReSRzEU.js → McpTools-CFnQdiSv.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-BhmkkCxd.js → Memory-Dxv81cNl.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-BeQMHr_n.js → MobileBridge-C92eX7PB.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-CphEwj_l.js → MobileProjects-BUHw7Wox.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-CFk1ibuN.js → Mtc-D-G9H4A1.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-CU9qrmbH.js → MtcAudit-CAEaEtAz.js} +5 -5
- package/src/assets/web-panel/assets/{Multisig-CKR-Gh0Y.js → Multisig-Cx_-X9HD.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-D1qWY6Mx.js → NLProgramming-DRIKG4Xy.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-B4CM0C65.js → Notes-CmL0vKUv.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-BTQYWveR.js → NotificationSettings-D2cQ5aQn.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DxN6fAn8.js → OrderTableRenderer-CPfd7PNy.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-scgboNfd.js → Organization-EKqO46hz.js} +2 -2
- package/src/assets/web-panel/assets/{Overflow-BP4aQhid.js → Overflow-BOHjBwJo.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-65jIo6MY.js → P2P-Dx4LdCE0.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Bfi4-tDQ.js → PdhVaultBrowser-CgCt2xdT.js} +5 -5
- package/src/assets/web-panel/assets/{Permissions-DWtxT7bE.js → Permissions-DWjDeO7O.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-Bilmr8BR.js → PersonalDataHub-Bx4Od8pG.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-IPIMM-1y.js → Pipeline-oKxws_Ch.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-DFB8RiVK.js → Privacy-Df1HVRKR.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-DxZksvu1.js → ProjectInit-BraLwZT4.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-DsjPsnYN.js → ProjectSettings-CKru54M0.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-CC5FBLLq.js → Projects-BEr7cJcS.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-Dk3ViPuF.js → Providers-C8v30DU3.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-CJ8R6-bF.js → QrScannerModal-CPyNV-O5.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-DJfCPORc.js → QuickAsk-BLIew7A5.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DjDygXeb.js → Recommend-DVjWmsPs.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-BJiJ1YHw.js → RemoteSession-B4PNTaEf.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-fYE8jPcc.js → Reputation-D5HOV6oI.js} +1 -1
- package/src/assets/web-panel/assets/{Row-vcvsjMm4.js → Row-DgCQom2M.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CZnKliwn.js → RssFeed-zvIcGHgz.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DEStiFGI.js → Search-C-KbJP_z.js} +1 -1
- package/src/assets/web-panel/assets/{Security-BPb_szxS.js → Security-CasnI-Ld.js} +3 -3
- package/src/assets/web-panel/assets/{Services-TR0xZhSF.js → Services-CR-pSlFv.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-BSPu9boC.js → Skeleton-BB5On1b5.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CXEj9pC6.js → Skills-CC-wdQi-.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-jlOlDGMA.js → Sla-CPX5QKEu.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-C8oPE_HQ.js → SpeechSettings-Bifkl6Zz.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DZNUx8zt.js → SyncSettings-CdUVeB-S.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-B4T6aoOl.js → Tasks-BttwN3fs.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-DeRgtwZ5.js → Templates-CBHNbpQ7.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-DDVoXGxa.js → Tenant-B90lEwSQ.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-DGAUoJMz.js → Terminal-u8KqitsA.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-Co4Nkpjm.js → TimelineRenderer-CnEJMkJo.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DaMLa0Fm.js → Tokens-CTM2OOJ_.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-C7iLr-Ik.js → Trigger-Ca8NmmgU.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CxX_tQqi.js → Trust-CI9GpUj2.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-ClrdckEx.js → UkeySign-BlMLGqKK.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-DgTVhaoK.js → VideoEditing-C8yCZrH0.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-SIbwES0O.js → Wallet-BpuYrz8o.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-YNqVnhZF.js → WebAuthn-DFpNfLG_.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-BvynT9mj.js → WorkflowEditor-BWhLoeU4.js} +1 -1
- package/src/assets/web-panel/assets/{chat-X79b2tVy.js → chat-Dwo4LC7E.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DioWDCbu.js → colors-DkdGvKBf.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-DpAXXaqu.js → compact-item-1gI0lfs3.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BYq8bCQX.js → createContext-O9iHirtr.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-axBqv361.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-CDJNMJ_n.js → hasIn-DY1jo9BQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUe-hFGb.js → index-1AnBwAoM.js} +1 -1
- package/src/assets/web-panel/assets/{index-CS3QdYDW.js → index-B-kbagPi.js} +1 -1
- package/src/assets/web-panel/assets/{index-DZysaS5T.js → index-B0TX-bLV.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cx0_WiSe.js → index-B5l7eb6E.js} +1 -1
- package/src/assets/web-panel/assets/{index-CJEFd0QJ.js → index-BDwV_V5g.js} +1 -1
- package/src/assets/web-panel/assets/{index-D88MWTOx.js → index-BgHG4f2K.js} +1 -1
- package/src/assets/web-panel/assets/{index-BK53HyEP.js → index-BgVO1aXv.js} +1 -1
- package/src/assets/web-panel/assets/{index-COqkDiRU.js → index-Bl6GfsQZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CUbuCFWb.js → index-BmAK4o9I.js} +1 -1
- package/src/assets/web-panel/assets/{index-C7cXBJcM.js → index-BsQkwBu2.js} +1 -1
- package/src/assets/web-panel/assets/{index-Byt1ny7l.js → index-BumRAO-7.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bh9la-GL.js → index-Bx4MNNMY.js} +1 -1
- package/src/assets/web-panel/assets/{index-B8_grEFP.js → index-C4c0XaiT.js} +1 -1
- package/src/assets/web-panel/assets/index-CAsOttsq.js +1 -0
- package/src/assets/web-panel/assets/{index-YviHYMA2.js → index-CBqSTwY9.js} +1 -1
- package/src/assets/web-panel/assets/{index-00kVj4me.js → index-D8fqsTHW.js} +1 -1
- package/src/assets/web-panel/assets/{index-Wl55a61D.js → index-DCqPIE3G.js} +1 -1
- package/src/assets/web-panel/assets/{index-CLSt7mOy.js → index-DNnaEzC5.js} +1 -1
- package/src/assets/web-panel/assets/{index-C4xggKQp.js → index-DTppQua6.js} +1 -1
- package/src/assets/web-panel/assets/{index-CbxqdIzD.js → index-DfFzjnA0.js} +1 -1
- package/src/assets/web-panel/assets/{index-BwHEGjR7.js → index-DskEFn8M.js} +1 -1
- package/src/assets/web-panel/assets/{index-D3J9FKFr.js → index-DvRvwzc-.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGEXGr9g.js → index-DwBcFhcc.js} +1 -1
- package/src/assets/web-panel/assets/{index-B6wxVEIZ.js → index-DwJBbK3Z.js} +1 -1
- package/src/assets/web-panel/assets/{index-mHAPEcPi.js → index-DwhJqZqM.js} +1 -1
- package/src/assets/web-panel/assets/{index-C1-NqghD.js → index-Dx51Am-0.js} +1 -1
- package/src/assets/web-panel/assets/{index-DP9ZLjra.js → index-E5Ar6dNV.js} +1 -1
- package/src/assets/web-panel/assets/{index-DSFkmRvK.js → index-ETHEhWvI.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmNspbVU.js → index-KUrBWzIM.js} +1 -1
- package/src/assets/web-panel/assets/index-MgEKheCh.js +1 -0
- package/src/assets/web-panel/assets/{index-TqLyy6IR.js → index-YnGvCu0P.js} +3 -3
- package/src/assets/web-panel/assets/{index-Q3WQ5Zhr.js → index-hRtVittm.js} +1 -1
- package/src/assets/web-panel/assets/{index-DAnXSg0r.js → index-nXoV4OCZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BBvA7Hxj.js → index-qUbrqzvO.js} +1 -1
- package/src/assets/web-panel/assets/{index-BIO8EVHt.js → index-rIJqtLz-.js} +1 -1
- package/src/assets/web-panel/assets/{index-B8ChecWd.js → index-rkkMl4Lb.js} +1 -1
- package/src/assets/web-panel/assets/{index-DwG9khVs.js → index-tXjOuLZm.js} +1 -1
- package/src/assets/web-panel/assets/{index-V6l3ia83.js → index-zLOzCcxM.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bt0zcD5R.js → index-zPpssHXA.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-18rmGkik.js → initDefaultProps-Du5HHTVt.js} +1 -1
- package/src/assets/web-panel/assets/{motion-3kvGzSgV.js → motion-D9mAVPKP.js} +1 -1
- package/src/assets/web-panel/assets/{move-Dx3DiVHc.js → move-DPO_sFtt.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-VX1dFJEI.js → mtc-parser-CnezVcXi.js} +1 -1
- package/src/assets/web-panel/assets/{omit-CniSeCOA.js → omit-DNpYMbet.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-RPggmcOd.js → pickAttrs-BUFm_slL.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-B45YBykr.js → placementArrow-DvwJtnzY.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-D0nciAEn.js → responsiveObserve-CUWOh_KI.js} +1 -1
- package/src/assets/web-panel/assets/{slide-UxLNWqjI.js → slide-bVHCUsdj.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-CukpV_uI.js → statusUtils-FlOzOrxf.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-BIcEZk6Y.js → styleChecker-C6CFXutA.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-Zah-xvV3.js → useFlexGapSupport-BNGqO_E0.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-BA7ihKFN.js → useFs-DyKOrA27.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-C64CsyY3.js → usePersonalDataHub-DZAqeMAJ.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-Datcekgj.js → vnode-Do7fVasi.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-CaFQv1KF.js → zoom-DYkEmOT2.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/data/changelog.json +52 -0
- package/src/lib/background-agent-supervisor.js +10 -1
- package/src/lib/evolution/evidence-backed-wiki-maintainer.js +119 -12
- package/src/lib/evolution/evolution-artifact-ports.js +6 -0
- package/src/lib/evolution/evolution-deployment-loader.js +139 -0
- package/src/lib/evolution/evolution-eval-gate.js +5 -0
- package/src/lib/evolution/evolution-ledger-ports.js +41 -17
- package/src/lib/evolution/pm-exploration-benchmark.js +253 -0
- package/src/lib/evolution/pm-exploration-budget-executor.js +346 -0
- package/src/lib/evolution/pm-exploration-business-grader.js +581 -0
- package/src/lib/evolution/pm-exploration-evidence-bundle.js +613 -0
- package/src/lib/evolution/pm-exploration-execution-host.js +946 -0
- package/src/lib/evolution/pm-exploration-ledger-adapter.js +860 -0
- package/src/lib/evolution/pm-exploration-provider-settlement-adapter.js +420 -0
- package/src/lib/evolution/pm-exploration-receipts.js +626 -0
- package/src/lib/evolution/pm-exploration-recovery-snapshot-store.js +521 -0
- package/src/lib/evolution/pm-exploration-rounds.js +842 -0
- package/src/lib/evolution/pm-exploration-transition-committer.js +541 -0
- package/src/lib/evolution/pm-exploration-volcengine-provider.js +724 -0
- package/src/lib/evolution/pm-result-grader.cjs +287 -0
- package/src/lib/read-file-loop-guard.js +36 -5
- package/src/lib/secure-fs.js +51 -4
- package/src/lib/task-progress-tracker.js +29 -7
- package/src/lib/text-file-search.js +1 -0
- package/src/runtime/agent-core.js +46 -4
- package/src/assets/web-panel/assets/ChatBubbleRenderer-C4tdSms8.js +0 -1
- package/src/assets/web-panel/assets/Logs-BtesccPB.js +0 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-DoN7oE2J.js +0 -1
- package/src/assets/web-panel/assets/devWarning-ONeWC5dH.js +0 -1
- package/src/assets/web-panel/assets/index--QLnQuO9.js +0 -1
- package/src/assets/web-panel/assets/index-CkgeII0e.js +0 -1
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { isProxy } from "node:util/types";
|
|
4
|
+
|
|
5
|
+
import grader from "./pm-result-grader.cjs";
|
|
6
|
+
import {
|
|
7
|
+
createPmExplorationGrader,
|
|
8
|
+
PM_EXPLORATION_GRADE_REQUEST_SCHEMA,
|
|
9
|
+
PM_EXPLORATION_RUN_REQUEST_SCHEMA,
|
|
10
|
+
} from "./pm-exploration-execution-host.js";
|
|
11
|
+
import { inspectPmExplorationReceiptAuthority } from "./pm-exploration-receipts.js";
|
|
12
|
+
|
|
13
|
+
export const PM_EXPLORATION_OUTCOME_SOURCE_SCHEMA =
|
|
14
|
+
"chainlesschain.pm-exploration-read-only-outcome-source/v2";
|
|
15
|
+
export const PM_EXPLORATION_OUTCOME_QUERY_SCHEMA =
|
|
16
|
+
"chainlesschain.pm-exploration-read-only-outcome-query/v1";
|
|
17
|
+
export const PM_EXPLORATION_BUSINESS_RESULT_SCHEMA =
|
|
18
|
+
"chainlesschain.pm-exploration-business-grader-result/v1";
|
|
19
|
+
|
|
20
|
+
const DIGEST = /^sha256:[a-f0-9]{64}$/u;
|
|
21
|
+
const ID = /^[a-z][a-z0-9]*(?:[._:@/-][a-z0-9]+)*$/u;
|
|
22
|
+
const SOURCES = new WeakMap();
|
|
23
|
+
|
|
24
|
+
function canonical(value) {
|
|
25
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
26
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
|
|
27
|
+
return `{${Object.keys(value)
|
|
28
|
+
.sort()
|
|
29
|
+
.map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`)
|
|
30
|
+
.join(",")}}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function hash(domain, value) {
|
|
34
|
+
return `sha256:${createHash("sha256")
|
|
35
|
+
.update(domain)
|
|
36
|
+
.update("\0")
|
|
37
|
+
.update(canonical(value))
|
|
38
|
+
.digest("hex")}`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function deepFreeze(value, seen = new WeakSet()) {
|
|
42
|
+
if (!value || typeof value !== "object" || seen.has(value)) return value;
|
|
43
|
+
seen.add(value);
|
|
44
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
45
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
46
|
+
if (descriptor && "value" in descriptor) deepFreeze(descriptor.value, seen);
|
|
47
|
+
}
|
|
48
|
+
return Object.freeze(value);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function exact(value, keys, label) {
|
|
52
|
+
if (
|
|
53
|
+
!value ||
|
|
54
|
+
typeof value !== "object" ||
|
|
55
|
+
Array.isArray(value) ||
|
|
56
|
+
isProxy(value) ||
|
|
57
|
+
Object.getPrototypeOf(value) !== Object.prototype
|
|
58
|
+
) {
|
|
59
|
+
throw new TypeError(`${label} must be a plain object`);
|
|
60
|
+
}
|
|
61
|
+
const actual = Reflect.ownKeys(value);
|
|
62
|
+
if (
|
|
63
|
+
actual.length !== keys.length ||
|
|
64
|
+
actual.some((key) => {
|
|
65
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
66
|
+
return (
|
|
67
|
+
typeof key !== "string" ||
|
|
68
|
+
!keys.includes(key) ||
|
|
69
|
+
!descriptor ||
|
|
70
|
+
!descriptor.enumerable ||
|
|
71
|
+
!("value" in descriptor)
|
|
72
|
+
);
|
|
73
|
+
})
|
|
74
|
+
) {
|
|
75
|
+
throw new TypeError(`${label} has unexpected or accessor fields`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function identifier(value, label) {
|
|
80
|
+
if (typeof value !== "string" || value.length > 256 || !ID.test(value))
|
|
81
|
+
throw new TypeError(`${label} is invalid`);
|
|
82
|
+
return value;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function digest(value, label) {
|
|
86
|
+
if (typeof value !== "string" || !DIGEST.test(value))
|
|
87
|
+
throw new TypeError(`${label} must be a sha256 digest`);
|
|
88
|
+
return value;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function integer(value, label, minimum = 0) {
|
|
92
|
+
if (!Number.isSafeInteger(value) || value < minimum)
|
|
93
|
+
throw new TypeError(`${label} is outside its allowed range`);
|
|
94
|
+
return value;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function directFunction(value, label, nullable = false) {
|
|
98
|
+
if (nullable && value === null) return null;
|
|
99
|
+
if (typeof value !== "function" || isProxy(value))
|
|
100
|
+
throw new TypeError(`${label} must be a direct function`);
|
|
101
|
+
return value;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function normalizeSourceDescriptor(value) {
|
|
105
|
+
exact(
|
|
106
|
+
value,
|
|
107
|
+
[
|
|
108
|
+
"sourceId",
|
|
109
|
+
"revision",
|
|
110
|
+
"handlerArtifactDigest",
|
|
111
|
+
"environmentDigest",
|
|
112
|
+
"outcomeBindingDigest",
|
|
113
|
+
],
|
|
114
|
+
"PM exploration outcome source descriptor",
|
|
115
|
+
);
|
|
116
|
+
const core = deepFreeze({
|
|
117
|
+
schema: PM_EXPLORATION_OUTCOME_SOURCE_SCHEMA,
|
|
118
|
+
sourceId: identifier(value.sourceId, "sourceId"),
|
|
119
|
+
revision: integer(value.revision, "revision", 1),
|
|
120
|
+
handlerArtifactDigest: digest(
|
|
121
|
+
value.handlerArtifactDigest,
|
|
122
|
+
"handlerArtifactDigest",
|
|
123
|
+
),
|
|
124
|
+
environmentDigest: digest(value.environmentDigest, "environmentDigest"),
|
|
125
|
+
outcomeBindingDigest: digest(
|
|
126
|
+
value.outcomeBindingDigest,
|
|
127
|
+
"outcomeBindingDigest",
|
|
128
|
+
),
|
|
129
|
+
});
|
|
130
|
+
return deepFreeze({
|
|
131
|
+
...core,
|
|
132
|
+
sourceDigest: hash(PM_EXPLORATION_OUTCOME_SOURCE_SCHEMA, core),
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function createPmExplorationReadOnlyOutcomeSource(options = {}) {
|
|
137
|
+
exact(
|
|
138
|
+
options,
|
|
139
|
+
["descriptor", "readProjectState", "readBoardExport"],
|
|
140
|
+
"PM exploration read-only outcome source options",
|
|
141
|
+
);
|
|
142
|
+
const source = Object.freeze({});
|
|
143
|
+
SOURCES.set(source, {
|
|
144
|
+
descriptor: normalizeSourceDescriptor(options.descriptor),
|
|
145
|
+
readProjectState: directFunction(
|
|
146
|
+
options.readProjectState,
|
|
147
|
+
"readProjectState",
|
|
148
|
+
true,
|
|
149
|
+
),
|
|
150
|
+
readBoardExport: directFunction(
|
|
151
|
+
options.readBoardExport,
|
|
152
|
+
"readBoardExport",
|
|
153
|
+
true,
|
|
154
|
+
),
|
|
155
|
+
});
|
|
156
|
+
return source;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function inspectPmExplorationReadOnlyOutcomeSource(value) {
|
|
160
|
+
const source = SOURCES.get(value);
|
|
161
|
+
if (!source)
|
|
162
|
+
throw new TypeError(
|
|
163
|
+
"a branded PM exploration read-only outcome source is required",
|
|
164
|
+
);
|
|
165
|
+
return source.descriptor;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function entityId(value, label) {
|
|
169
|
+
if (
|
|
170
|
+
typeof value !== "string" ||
|
|
171
|
+
value.length < 1 ||
|
|
172
|
+
value.length > 512 ||
|
|
173
|
+
value.trim() !== value ||
|
|
174
|
+
[...value].some((character) => character.charCodeAt(0) < 32)
|
|
175
|
+
) {
|
|
176
|
+
throw new TypeError(`${label} is invalid`);
|
|
177
|
+
}
|
|
178
|
+
return value;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function denseEntityIds(value, label) {
|
|
182
|
+
if (
|
|
183
|
+
!Array.isArray(value) ||
|
|
184
|
+
isProxy(value) ||
|
|
185
|
+
Object.getPrototypeOf(value) !== Array.prototype ||
|
|
186
|
+
value.length < 1 ||
|
|
187
|
+
value.length > 10_000 ||
|
|
188
|
+
Reflect.ownKeys(value).length !== value.length + 1
|
|
189
|
+
) {
|
|
190
|
+
throw new TypeError(`${label} must be a dense nonempty array`);
|
|
191
|
+
}
|
|
192
|
+
const normalized = [];
|
|
193
|
+
for (let index = 0; index < value.length; index++) {
|
|
194
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, index);
|
|
195
|
+
if (
|
|
196
|
+
!descriptor ||
|
|
197
|
+
descriptor.enumerable !== true ||
|
|
198
|
+
!("value" in descriptor)
|
|
199
|
+
) {
|
|
200
|
+
throw new TypeError(`${label} cannot contain holes or accessors`);
|
|
201
|
+
}
|
|
202
|
+
normalized.push(entityId(descriptor.value, label));
|
|
203
|
+
}
|
|
204
|
+
if (new Set(normalized).size !== normalized.length)
|
|
205
|
+
throw new TypeError(`${label} must contain unique identifiers`);
|
|
206
|
+
return Object.freeze(normalized);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function normalizeExpectation(value) {
|
|
210
|
+
if (
|
|
211
|
+
!value ||
|
|
212
|
+
typeof value !== "object" ||
|
|
213
|
+
Array.isArray(value) ||
|
|
214
|
+
isProxy(value) ||
|
|
215
|
+
Object.getPrototypeOf(value) !== Object.prototype
|
|
216
|
+
) {
|
|
217
|
+
throw new TypeError("PM expectation must be plain data");
|
|
218
|
+
}
|
|
219
|
+
const kindDescriptor = Object.getOwnPropertyDescriptor(value, "kind");
|
|
220
|
+
if (
|
|
221
|
+
!kindDescriptor ||
|
|
222
|
+
!kindDescriptor.enumerable ||
|
|
223
|
+
!("value" in kindDescriptor)
|
|
224
|
+
) {
|
|
225
|
+
throw new TypeError("PM expectation kind must be plain data");
|
|
226
|
+
}
|
|
227
|
+
if (
|
|
228
|
+
kindDescriptor.value === "file-export" ||
|
|
229
|
+
kindDescriptor.value === "project-state"
|
|
230
|
+
) {
|
|
231
|
+
return grader.normalizePmExpectation(value);
|
|
232
|
+
}
|
|
233
|
+
exact(
|
|
234
|
+
value,
|
|
235
|
+
["kind", "boardId", "taskIds", "sprintIds"],
|
|
236
|
+
"PM board expectation",
|
|
237
|
+
);
|
|
238
|
+
if (value.kind !== "board-export")
|
|
239
|
+
throw new TypeError("PM expectation kind is invalid");
|
|
240
|
+
return deepFreeze({
|
|
241
|
+
kind: value.kind,
|
|
242
|
+
boardId: entityId(value.boardId, "boardId"),
|
|
243
|
+
taskIds: denseEntityIds(value.taskIds, "taskIds"),
|
|
244
|
+
sprintIds: denseEntityIds(value.sprintIds, "sprintIds"),
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function normalizeExpectationEntry(value, index) {
|
|
249
|
+
const label = `PM business expectation ${index}`;
|
|
250
|
+
if (
|
|
251
|
+
!value ||
|
|
252
|
+
typeof value !== "object" ||
|
|
253
|
+
Array.isArray(value) ||
|
|
254
|
+
isProxy(value) ||
|
|
255
|
+
Object.getPrototypeOf(value) !== Object.prototype
|
|
256
|
+
) {
|
|
257
|
+
throw new TypeError(`${label} must be a plain object`);
|
|
258
|
+
}
|
|
259
|
+
const expectedDescriptor = Object.getOwnPropertyDescriptor(value, "expected");
|
|
260
|
+
if (
|
|
261
|
+
!expectedDescriptor ||
|
|
262
|
+
!expectedDescriptor.enumerable ||
|
|
263
|
+
!("value" in expectedDescriptor)
|
|
264
|
+
) {
|
|
265
|
+
throw new TypeError(`${label}.expected must be plain data`);
|
|
266
|
+
}
|
|
267
|
+
const expected = normalizeExpectation(expectedDescriptor.value);
|
|
268
|
+
exact(
|
|
269
|
+
value,
|
|
270
|
+
expected.kind === "file-export"
|
|
271
|
+
? ["taskId", "expected", "artifactRoot"]
|
|
272
|
+
: ["taskId", "expected"],
|
|
273
|
+
label,
|
|
274
|
+
);
|
|
275
|
+
let artifactRoot = null;
|
|
276
|
+
if (expected.kind === "file-export") {
|
|
277
|
+
if (
|
|
278
|
+
typeof value.artifactRoot !== "string" ||
|
|
279
|
+
value.artifactRoot.length === 0 ||
|
|
280
|
+
!path.isAbsolute(value.artifactRoot)
|
|
281
|
+
) {
|
|
282
|
+
throw new TypeError(`${label}.artifactRoot must be absolute`);
|
|
283
|
+
}
|
|
284
|
+
artifactRoot = value.artifactRoot;
|
|
285
|
+
}
|
|
286
|
+
return deepFreeze({
|
|
287
|
+
taskId: identifier(value.taskId, `${label}.taskId`),
|
|
288
|
+
expected,
|
|
289
|
+
artifactRoot,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function normalizeExpectations(value) {
|
|
294
|
+
if (
|
|
295
|
+
!Array.isArray(value) ||
|
|
296
|
+
isProxy(value) ||
|
|
297
|
+
Object.getPrototypeOf(value) !== Array.prototype ||
|
|
298
|
+
value.length < 1 ||
|
|
299
|
+
value.length > 1024 ||
|
|
300
|
+
Reflect.ownKeys(value).length !== value.length + 1
|
|
301
|
+
) {
|
|
302
|
+
throw new TypeError("PM business expectations must be a dense array");
|
|
303
|
+
}
|
|
304
|
+
const result = [];
|
|
305
|
+
for (let index = 0; index < value.length; index++) {
|
|
306
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, index);
|
|
307
|
+
if (
|
|
308
|
+
!descriptor ||
|
|
309
|
+
descriptor.enumerable !== true ||
|
|
310
|
+
!("value" in descriptor)
|
|
311
|
+
) {
|
|
312
|
+
throw new TypeError(
|
|
313
|
+
"PM business expectations cannot contain holes or accessors",
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
result.push(normalizeExpectationEntry(descriptor.value, index));
|
|
317
|
+
}
|
|
318
|
+
if (new Set(result.map((entry) => entry.taskId)).size !== result.length)
|
|
319
|
+
throw new TypeError("PM business expectation taskIds must be unique");
|
|
320
|
+
return Object.freeze(result);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
function assertRunRequest(value, planDigest, environmentDigest) {
|
|
324
|
+
exact(
|
|
325
|
+
value,
|
|
326
|
+
[
|
|
327
|
+
"schema",
|
|
328
|
+
"planDigest",
|
|
329
|
+
"suiteDigest",
|
|
330
|
+
"trainingPartitionDigest",
|
|
331
|
+
"environmentDigest",
|
|
332
|
+
"executionManifestDigest",
|
|
333
|
+
"toolPolicyDigest",
|
|
334
|
+
"roundId",
|
|
335
|
+
"stage",
|
|
336
|
+
"branchId",
|
|
337
|
+
"taskId",
|
|
338
|
+
"inputMemoryDigest",
|
|
339
|
+
"requestDigest",
|
|
340
|
+
],
|
|
341
|
+
"PM business grader run request",
|
|
342
|
+
);
|
|
343
|
+
if (
|
|
344
|
+
value.schema !== PM_EXPLORATION_RUN_REQUEST_SCHEMA ||
|
|
345
|
+
value.planDigest !== planDigest ||
|
|
346
|
+
value.environmentDigest !== environmentDigest
|
|
347
|
+
) {
|
|
348
|
+
throw new Error("PM business grader run request differs from its binding");
|
|
349
|
+
}
|
|
350
|
+
digest(value.requestDigest, "run requestDigest");
|
|
351
|
+
identifier(value.roundId, "roundId");
|
|
352
|
+
identifier(value.taskId, "taskId");
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function assertGradeRequest(value, planDigest, environmentDigest) {
|
|
356
|
+
exact(
|
|
357
|
+
value,
|
|
358
|
+
[
|
|
359
|
+
"schema",
|
|
360
|
+
"planDigest",
|
|
361
|
+
"environmentDigest",
|
|
362
|
+
"executionManifestDigest",
|
|
363
|
+
"roundId",
|
|
364
|
+
"taskId",
|
|
365
|
+
"executionRequestDigest",
|
|
366
|
+
"inputMemoryDigest",
|
|
367
|
+
"outputMemoryDigest",
|
|
368
|
+
"executionStatus",
|
|
369
|
+
"executionReceiptDigest",
|
|
370
|
+
"traceDigest",
|
|
371
|
+
"requestDigest",
|
|
372
|
+
],
|
|
373
|
+
"PM business grader request",
|
|
374
|
+
);
|
|
375
|
+
if (
|
|
376
|
+
value.schema !== PM_EXPLORATION_GRADE_REQUEST_SCHEMA ||
|
|
377
|
+
value.planDigest !== planDigest ||
|
|
378
|
+
value.environmentDigest !== environmentDigest
|
|
379
|
+
) {
|
|
380
|
+
throw new Error("PM business grader request differs from its binding");
|
|
381
|
+
}
|
|
382
|
+
for (const key of [
|
|
383
|
+
"executionRequestDigest",
|
|
384
|
+
"executionReceiptDigest",
|
|
385
|
+
"inputMemoryDigest",
|
|
386
|
+
"outputMemoryDigest",
|
|
387
|
+
"traceDigest",
|
|
388
|
+
"requestDigest",
|
|
389
|
+
]) {
|
|
390
|
+
digest(value[key], key);
|
|
391
|
+
}
|
|
392
|
+
identifier(value.roundId, "roundId");
|
|
393
|
+
identifier(value.taskId, "taskId");
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function sanitizedOutcome(executionSucceeded, reason) {
|
|
397
|
+
return Object.freeze({
|
|
398
|
+
schema: "chainlesschain.pm-local-outcome/v1",
|
|
399
|
+
executionSucceeded,
|
|
400
|
+
artifactCheckPassed: false,
|
|
401
|
+
pass: false,
|
|
402
|
+
reason,
|
|
403
|
+
artifactDigest: null,
|
|
404
|
+
authenticated: false,
|
|
405
|
+
qualifiesForPromotion: false,
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
function queryFor(request, sourceDigest) {
|
|
410
|
+
return deepFreeze({
|
|
411
|
+
schema: PM_EXPLORATION_OUTCOME_QUERY_SCHEMA,
|
|
412
|
+
planDigest: request.planDigest,
|
|
413
|
+
environmentDigest: request.environmentDigest,
|
|
414
|
+
sourceDigest,
|
|
415
|
+
roundId: request.roundId,
|
|
416
|
+
taskId: request.taskId,
|
|
417
|
+
executionRequestDigest: request.executionRequestDigest,
|
|
418
|
+
executionReceiptDigest: request.executionReceiptDigest,
|
|
419
|
+
outputMemoryDigest: request.outputMemoryDigest,
|
|
420
|
+
traceDigest: request.traceDigest,
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
function gradeResult(request, source, privateExpectationBinding, localOutcome) {
|
|
425
|
+
const resultDigest = hash(PM_EXPLORATION_BUSINESS_RESULT_SCHEMA, {
|
|
426
|
+
schema: PM_EXPLORATION_BUSINESS_RESULT_SCHEMA,
|
|
427
|
+
planDigest: request.planDigest,
|
|
428
|
+
environmentDigest: request.environmentDigest,
|
|
429
|
+
requestDigest: request.requestDigest,
|
|
430
|
+
taskId: request.taskId,
|
|
431
|
+
executionRequestDigest: request.executionRequestDigest,
|
|
432
|
+
executionReceiptDigest: request.executionReceiptDigest,
|
|
433
|
+
outputMemoryDigest: request.outputMemoryDigest,
|
|
434
|
+
sourceDigest: source.descriptor.sourceDigest,
|
|
435
|
+
privateExpectationBinding,
|
|
436
|
+
outcome: localOutcome,
|
|
437
|
+
});
|
|
438
|
+
return Object.freeze({
|
|
439
|
+
decision:
|
|
440
|
+
request.executionStatus !== "succeeded"
|
|
441
|
+
? "unsafe"
|
|
442
|
+
: localOutcome.pass
|
|
443
|
+
? "accept"
|
|
444
|
+
: "reject",
|
|
445
|
+
scoreBasisPoints: localOutcome.pass ? 10_000 : 0,
|
|
446
|
+
resultDigest,
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
export function createPmExplorationBusinessGrader(options = {}) {
|
|
451
|
+
exact(
|
|
452
|
+
options,
|
|
453
|
+
["signer", "source", "planDigest", "expectations"],
|
|
454
|
+
"PM exploration business grader options",
|
|
455
|
+
);
|
|
456
|
+
const source = SOURCES.get(options.source);
|
|
457
|
+
if (!source)
|
|
458
|
+
throw new TypeError(
|
|
459
|
+
"a branded PM exploration read-only outcome source is required",
|
|
460
|
+
);
|
|
461
|
+
const planDigest = digest(options.planDigest, "planDigest");
|
|
462
|
+
const signerDescriptor = inspectPmExplorationReceiptAuthority(options.signer);
|
|
463
|
+
if (signerDescriptor.role !== "grader")
|
|
464
|
+
throw new TypeError("PM business grader requires a grader signer");
|
|
465
|
+
if (
|
|
466
|
+
signerDescriptor.handlerArtifactDigest !==
|
|
467
|
+
source.descriptor.handlerArtifactDigest
|
|
468
|
+
) {
|
|
469
|
+
throw new Error(
|
|
470
|
+
"PM business grader signer and outcome source use different handler artifacts",
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
const expectations = normalizeExpectations(options.expectations);
|
|
474
|
+
const byTaskId = new Map(expectations.map((entry) => [entry.taskId, entry]));
|
|
475
|
+
const privateExpectationBinding = hash(
|
|
476
|
+
PM_EXPLORATION_BUSINESS_RESULT_SCHEMA,
|
|
477
|
+
{
|
|
478
|
+
nonce: randomBytes(32).toString("hex"),
|
|
479
|
+
expectations,
|
|
480
|
+
},
|
|
481
|
+
);
|
|
482
|
+
const prepared = new Map();
|
|
483
|
+
|
|
484
|
+
return createPmExplorationGrader({
|
|
485
|
+
signer: options.signer,
|
|
486
|
+
prepare: async (request) => {
|
|
487
|
+
assertRunRequest(
|
|
488
|
+
request,
|
|
489
|
+
planDigest,
|
|
490
|
+
source.descriptor.environmentDigest,
|
|
491
|
+
);
|
|
492
|
+
const expectation = byTaskId.get(request.taskId);
|
|
493
|
+
if (!expectation)
|
|
494
|
+
throw new Error("PM business grader has no expectation for the task");
|
|
495
|
+
if (prepared.has(request.requestDigest))
|
|
496
|
+
throw new Error("PM business grader request was already prepared");
|
|
497
|
+
let baseline = null;
|
|
498
|
+
let preparationFailed = false;
|
|
499
|
+
if (expectation.expected.kind === "file-export") {
|
|
500
|
+
try {
|
|
501
|
+
baseline = grader.capturePmExportBaseline(
|
|
502
|
+
expectation.artifactRoot,
|
|
503
|
+
expectation.expected.relativePath,
|
|
504
|
+
);
|
|
505
|
+
} catch {
|
|
506
|
+
preparationFailed = true;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
prepared.set(request.requestDigest, {
|
|
510
|
+
baseline,
|
|
511
|
+
expectation,
|
|
512
|
+
preparationFailed,
|
|
513
|
+
});
|
|
514
|
+
if (preparationFailed)
|
|
515
|
+
throw new Error("PM file-export baseline is unavailable or unsafe");
|
|
516
|
+
},
|
|
517
|
+
grade: async (request, runtime) => {
|
|
518
|
+
assertGradeRequest(
|
|
519
|
+
request,
|
|
520
|
+
planDigest,
|
|
521
|
+
source.descriptor.environmentDigest,
|
|
522
|
+
);
|
|
523
|
+
const preparation = prepared.get(request.executionRequestDigest);
|
|
524
|
+
prepared.delete(request.executionRequestDigest);
|
|
525
|
+
if (!preparation || preparation.expectation.taskId !== request.taskId) {
|
|
526
|
+
throw new Error("PM business grader request was not prepared");
|
|
527
|
+
}
|
|
528
|
+
const executionSucceeded = request.executionStatus === "succeeded";
|
|
529
|
+
let localOutcome;
|
|
530
|
+
if (!executionSucceeded) {
|
|
531
|
+
localOutcome = sanitizedOutcome(false, "execution-failed");
|
|
532
|
+
} else if (preparation.preparationFailed) {
|
|
533
|
+
localOutcome = sanitizedOutcome(
|
|
534
|
+
true,
|
|
535
|
+
"artifact-precondition-unavailable-or-unsafe",
|
|
536
|
+
);
|
|
537
|
+
} else if (preparation.expectation.expected.kind === "file-export") {
|
|
538
|
+
localOutcome = grader.gradePmExportFile({
|
|
539
|
+
baseline: preparation.baseline,
|
|
540
|
+
expected: preparation.expectation.expected,
|
|
541
|
+
executionSucceeded: true,
|
|
542
|
+
});
|
|
543
|
+
} else if (preparation.expectation.expected.kind === "project-state") {
|
|
544
|
+
if (source.readProjectState === null)
|
|
545
|
+
throw new Error("PM project-state outcome source is unavailable");
|
|
546
|
+
const actual = await source.readProjectState(
|
|
547
|
+
queryFor(request, source.descriptor.sourceDigest),
|
|
548
|
+
runtime.signal,
|
|
549
|
+
);
|
|
550
|
+
localOutcome = grader.gradePmProjectState({
|
|
551
|
+
actual,
|
|
552
|
+
expected: preparation.expectation.expected,
|
|
553
|
+
executionSucceeded: true,
|
|
554
|
+
});
|
|
555
|
+
} else {
|
|
556
|
+
if (source.readBoardExport === null)
|
|
557
|
+
throw new Error("PM board-export outcome source is unavailable");
|
|
558
|
+
const actual = await source.readBoardExport(
|
|
559
|
+
queryFor(request, source.descriptor.sourceDigest),
|
|
560
|
+
runtime.signal,
|
|
561
|
+
);
|
|
562
|
+
const expected = {
|
|
563
|
+
boardId: preparation.expectation.expected.boardId,
|
|
564
|
+
taskIds: preparation.expectation.expected.taskIds,
|
|
565
|
+
sprintIds: preparation.expectation.expected.sprintIds,
|
|
566
|
+
};
|
|
567
|
+
localOutcome = grader.gradePmBoardExport({
|
|
568
|
+
actual,
|
|
569
|
+
expected,
|
|
570
|
+
executionSucceeded: true,
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
return gradeResult(
|
|
574
|
+
request,
|
|
575
|
+
source,
|
|
576
|
+
privateExpectationBinding,
|
|
577
|
+
localOutcome,
|
|
578
|
+
);
|
|
579
|
+
},
|
|
580
|
+
});
|
|
581
|
+
}
|