chainlesschain 0.166.90 → 0.166.92
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 +15 -13
- package/package.json +4 -4
- package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
- package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-CZzXRe1-.js → AIOps-C74YzqwJ.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-_AZfbW1Q.js → ActionButton-TFef1hOE.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-CzaUx_wv.js → Analytics-CYsWpkkU.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-xHEeeD-m.js → AppLayout-CFf9kjwu.js} +4 -4
- package/src/assets/web-panel/assets/{Artifacts-DmTbtudE.js → Artifacts-TQqa94YO.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-Cn4ng4fo.js → Audit-B79ayqfS.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-DLUY1VD2.js → BackgroundAgents-pjkHfLP9.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-B2v--wB6.js → Backup-CE6A-t_r.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-Bgih7yAv.js → BaseInput-CwcgWMBY.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-1MiiA3yA.js → Chat-BIkDNesY.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-CPLynmbb.js → ChatBubbleRenderer-DgaokYts.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-DsyBa_NO.js → Checkbox-MbypIy5V.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-B7WCFx9H.js → Codegen-DiFHWDnt.js} +1 -1
- package/src/assets/web-panel/assets/{Col-D2x4GBGm.js → Col-BNMlYMso.js} +1 -1
- package/src/assets/web-panel/assets/{Community-Rnwg9nea.js → Community-B3HVyHOX.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BPczlrRh.js → Compact-C7hlAubb.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-Br1L_wGU.js → Compliance-PaXZu6sE.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DlsWB_oS.js → Cowork-BGiojbm-.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-BWo_KGpG.js → Cron-Bmr-1QAx.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-Cug7N8ge.js → Crosschain-BwUvWCVd.js} +1 -1
- package/src/assets/web-panel/assets/{DID-CMbyOZJN.js → DID-k_4QZocW.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-C4dl_UaE.js → Dashboard-_ieRo2C5.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-CBrC7M-9.js → Dropdown-DYHh6T27.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DTq7tU4b.js → EmailListRenderer-BNlQcWQX.js} +1 -1
- package/src/assets/web-panel/assets/{EvolutionSettings-DWP3csxS.js → EvolutionSettings-DIkZ6U2D.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-DZl7zuv_.js → FamilyGuardDashboard-Dq7qSr0P.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-W-GSlVK5.js → Federation-C64e3Cbx.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DMB7xYFV.js → FormItemContext-D-GE2vUa.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DNv8GEoq.js → GenericCardRenderer-DO3B2gis.js} +1 -1
- package/src/assets/web-panel/assets/{Git-BZ0Bbzw6.js → Git-0ETirIQH.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BNEdcOM5.js → Governance-C9fnRygX.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-C8249gIz.js → Inference-CLJ9RTsK.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-ngzebU3e.js → KnowledgeGraph-D3C_GxrN.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CP15th-f.js → Logs-C5ctGbkN.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-Ce-eWK3j.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-CaH59OsY.js → Marketplace-GF_t6hJ_.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-C07vnJev.js → McpTools-BGsGzgQs.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-CqAOkVAS.js → Memory-CcrY2A0j.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-qp7mZimq.js → MobileBridge-Bi4T0RlS.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-DKhbqvTw.js → MobileProjects-DvjEGyvf.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-CRYCnWXv.js → Mtc-DL77Vf-k.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-Z08IrKws.js → MtcAudit-CDy_Uswb.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-BWdatUnH.js → Multisig-DL0BAO_c.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-BKWiCZ_m.js → NLProgramming-B-woh5IR.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Bgpzk3sm.js → Notes-CEFVCxk7.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-DvtZEktR.js → NotificationSettings-BqPPMuAP.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-CBcy0szc.js → OrderTableRenderer-GUKQ1xwp.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-DRRL6vW1.js → Organization-B1gX8jlr.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-COmfB8Ns.js → Overflow-CeMxuUZy.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-BqMq_DSa.js → P2P-B5aIRWwJ.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-BX7iNvle.js → PdhVaultBrowser-6rYgejd4.js} +4 -4
- package/src/assets/web-panel/assets/{Permissions-DzYkjmV_.js → Permissions-CqCp2SIl.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-BBTcxBbN.js → PersonalDataHub-BsA7DJWW.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-eRkYFSbO.js → Pipeline-CiW6HeZh.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-Ch7IFKBh.js → Privacy-DckUOLYq.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-Ci8EcBYg.js → ProjectInit-CZppOOYR.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-B4lYHFbI.js → ProjectSettings-B9QPzhDU.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-zkE5cCo_.js → Projects-BErjjGha.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-BKDVD3_e.js → Providers-DehU6Qiz.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-BromrHlf.js → QrScannerModal-E1SUvv1m.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-CCgoY1gR.js → QuickAsk-COWFxyH3.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DCPZvpq7.js → Recommend-D26pWKxX.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-DPnFP8HU.js → RemoteSession-DCOIaId3.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-l6r8ytAs.js → Reputation-DT_AHGAR.js} +1 -1
- package/src/assets/web-panel/assets/{Row-ke9Mk1cx.js → Row-B50S-1nl.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-DQOEzUEn.js → RssFeed-BaBnHg3Q.js} +2 -2
- package/src/assets/web-panel/assets/{Search-BqgA0aUz.js → Search-BVdnLuuS.js} +1 -1
- package/src/assets/web-panel/assets/{Security-FeGD_jqV.js → Security-BnacH74J.js} +3 -3
- package/src/assets/web-panel/assets/{Services-4kiYYAjZ.js → Services-CxM08Zch.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-BbU8Xegs.js → Skeleton-DE7CIc1N.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-Dl2bUMUL.js → Skills-CGI0SJmf.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-xRGALeaZ.js → Sla-DpEzPcqc.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DZfd4RDm.js → SpeechSettings-CTmnmMHn.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-BRtCV9Ga.js → SyncSettings-Dxgrd9hd.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-DVRQklfG.js → Tasks-CW4slS0A.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BbhE5jt5.js → Templates-DxvGWDgB.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-qXPDNKbK.js → Tenant-_Q0o2tNK.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-CV48Ks7E.js → Terminal-BTZn8pow.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-BLGfJIDr.js → TimelineRenderer-CauL0KFe.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-7G9H6Hrt.js → Tokens-CDoM2qeT.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger--F64N11F.js → Trigger-B-QYGEU7.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-Cq1r-D_y.js → Trust-BD6XJHT-.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-Dqyu4RVh.js → UkeySign-x4TFwCy0.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-DuFmWH_B.js → VideoEditing-t3imBK_0.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-C3mg7EWP.js → Wallet-BCfkWwNC.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-CDK-Aj_X.js → WebAuthn-WH314Mdm.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor--K7K-T1F.js → WorkflowEditor-jUlcjrUg.js} +1 -1
- package/src/assets/web-panel/assets/{chat-BQDcS6VP.js → chat-Dg3VASTL.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BKxJL2-T.js → colors-BNvmBRKE.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-CFjQAMbY.js → compact-item-BGOfoqf4.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DbgCsdQd.js → createContext-BNQeqKAs.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-B7_ypN1G.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-BhkaOBNv.js → hasIn-Bg3AjCrq.js} +1 -1
- package/src/assets/web-panel/assets/{index-DvWWFJHJ.js → index--I3UF5t1.js} +1 -1
- package/src/assets/web-panel/assets/{index-DJ2OiRvh.js → index-2D04Zltx.js} +3 -3
- package/src/assets/web-panel/assets/{index-BuWPqSGT.js → index-60AnjUTX.js} +1 -1
- package/src/assets/web-panel/assets/{index-D2Zb-Kd1.js → index-7QJUWemf.js} +1 -1
- package/src/assets/web-panel/assets/{index-C0DzhUOX.js → index-B--0QM0S.js} +1 -1
- package/src/assets/web-panel/assets/index-B-jSKJK6.js +1 -0
- package/src/assets/web-panel/assets/{index-COGy6wXn.js → index-B0mgngoB.js} +1 -1
- package/src/assets/web-panel/assets/{index-bMX8BBLE.js → index-BBCMulQ-.js} +1 -1
- package/src/assets/web-panel/assets/{index-CE506mgj.js → index-BSNhW95G.js} +1 -1
- package/src/assets/web-panel/assets/{index-CoOu7sdP.js → index-B_JmInC0.js} +1 -1
- package/src/assets/web-panel/assets/{index-B4LlAJqc.js → index-BaPvEvB4.js} +1 -1
- package/src/assets/web-panel/assets/{index-CRtUDiXx.js → index-Bkz1tgFR.js} +1 -1
- package/src/assets/web-panel/assets/{index-Du_SxxBY.js → index-BmTacaQV.js} +1 -1
- package/src/assets/web-panel/assets/{index-CSUDlsIr.js → index-CCFZN66A.js} +1 -1
- package/src/assets/web-panel/assets/{index-3uR0ThJO.js → index-COol3xfA.js} +1 -1
- package/src/assets/web-panel/assets/{index-DmYK9Tqt.js → index-CY8cRKHR.js} +1 -1
- package/src/assets/web-panel/assets/{index-T9ka3Xj3.js → index-Cbp-wp-U.js} +1 -1
- package/src/assets/web-panel/assets/{index-CB4oHynY.js → index-Co_LnCWD.js} +1 -1
- package/src/assets/web-panel/assets/{index-DEwHywz9.js → index-Cx2EXRfr.js} +1 -1
- package/src/assets/web-panel/assets/{index-CUs7XpUO.js → index-D-mSvCQK.js} +1 -1
- package/src/assets/web-panel/assets/{index-BRqlCTrz.js → index-D072oLjp.js} +1 -1
- package/src/assets/web-panel/assets/{index-sKfUUldY.js → index-D6UqK83L.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dhfa_BIl.js → index-DF_FKSVH.js} +1 -1
- package/src/assets/web-panel/assets/{index-D9sVcw6v.js → index-DLwEXRrb.js} +1 -1
- package/src/assets/web-panel/assets/{index-3djsY75k.js → index-DO0VlNtc.js} +1 -1
- package/src/assets/web-panel/assets/{index-BfGGsAU7.js → index-DS04wRll.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dn2QSsuI.js → index-DYn5DnDk.js} +1 -1
- package/src/assets/web-panel/assets/{index-D-Yh3-1z.js → index-D_O2ZjPk.js} +1 -1
- package/src/assets/web-panel/assets/{index-BNjYPJNU.js → index-DcCnO0RU.js} +1 -1
- package/src/assets/web-panel/assets/{index-DP1NrM9J.js → index-Dkp-okWa.js} +1 -1
- package/src/assets/web-panel/assets/{index-DdcrixaQ.js → index-OUFoxUgH.js} +1 -1
- package/src/assets/web-panel/assets/index-P4FXZJqI.js +1 -0
- package/src/assets/web-panel/assets/{index-7BY44UEv.js → index-Wo0f2iqb.js} +1 -1
- package/src/assets/web-panel/assets/{index-DjmVlpap.js → index-ZD5Kd8tx.js} +1 -1
- package/src/assets/web-panel/assets/{index-3YutaXnp.js → index-fOwii3LP.js} +1 -1
- package/src/assets/web-panel/assets/{index-aPdVzagA.js → index-hG7jXGEW.js} +1 -1
- package/src/assets/web-panel/assets/{index-De7daEnc.js → index-pVdQieac.js} +1 -1
- package/src/assets/web-panel/assets/{index-CJoXgJ2N.js → index-uH2LnAs_.js} +1 -1
- package/src/assets/web-panel/assets/{index-DFt48Z-x.js → index-xzaUx19r.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-wrqabmui.js → initDefaultProps-B8PN9AxJ.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BoyB3ilP.js → motion-BHivfw5Q.js} +1 -1
- package/src/assets/web-panel/assets/{move-Cq31cSFE.js → move-B0QU5nDd.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-BkxNt-8H.js → mtc-parser-DRwRM3PE.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DofGni53.js → omit-SHt2rV2p.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-BnluLL16.js → pickAttrs-CcmDlEb2.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-C-yegJSP.js → placementArrow-DYatmXDS.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-CD3ziNhu.js → responsiveObserve-B7qrsXq5.js} +1 -1
- package/src/assets/web-panel/assets/{slide-ToZO4gQ1.js → slide-BRGhlOWd.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-DFVmDmVl.js → statusUtils-CT-7NXsQ.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-De0Y8g1O.js → styleChecker-rZdw_Yyp.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-wBKIYFKX.js → useFlexGapSupport-D8YNIP4P.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-CP9nmUMJ.js → useFs-B8pt0Gu-.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-vFGrVDyp.js → usePersonalDataHub-VMmYM1tt.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-BcBIjvjH.js → vnode-UNDuoPoq.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-DnXDAQxA.js → zoom-dN-u667S.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +1 -1
- package/src/commands/agent-process-ownership.js +121 -0
- package/src/commands/agent.js +2 -0
- package/src/commands/hub.js +86 -9
- package/src/data/changelog.json +54 -2
- package/src/lib/audit-logger.js +46 -20
- package/src/lib/checkpoint-restore-saga.js +11 -1
- package/src/lib/eval/verify01-host-evidence.js +36 -3
- package/src/lib/evolution/evolution-artifact-ports.js +26 -0
- package/src/lib/evolution/evolution-eval-cohort-enrollment.js +713 -47
- package/src/lib/evolution/evolution-eval-gate.js +146 -0
- package/src/lib/evolution/evolution-eval-launch-admission.js +168 -90
- package/src/lib/evolution/evolution-eval-ledger-capture.js +50 -0
- package/src/lib/evolution/evolution-eval-readonly-audit.js +106 -0
- package/src/lib/evolution/evolution-ledger-file-backend.js +20 -0
- package/src/lib/evolution/evolution-ledger-ports.js +59 -27
- package/src/lib/evolution/evolution-ledger-v2-journal.js +55 -18
- package/src/lib/evolution/evolution-workbench-file-resources.js +19 -1
- package/src/lib/evolution/rrsi-cohort-registration.js +275 -0
- package/src/lib/evolution/rrsi-contracts.js +742 -0
- package/src/lib/evolution/rrsi-data.js +196 -0
- package/src/lib/evolution/rrsi-evaluation-adapter.js +275 -0
- package/src/lib/evolution/rrsi-evaluation-variants.js +267 -0
- package/src/lib/evolution/rrsi-group-statistics.js +553 -0
- package/src/lib/evolution/rrsi-history-ledger-adapter.js +3261 -0
- package/src/lib/evolution/rrsi-native-batch-evidence.js +520 -0
- package/src/lib/evolution/rrsi-native-eval-row-collector.js +538 -0
- package/src/lib/evolution/rrsi-native-evaluation-batch.js +547 -0
- package/src/lib/evolution/rrsi-native-evaluation-plan.js +431 -0
- package/src/lib/evolution/rrsi-native-group-statistics-plan.js +121 -0
- package/src/lib/evolution/rrsi-native-group-statistics.js +482 -0
- package/src/lib/evolution/rrsi-native-quality-receipt-contracts.js +321 -0
- package/src/lib/evolution/rrsi-native-quality-receipt.js +256 -0
- package/src/lib/evolution/rrsi-native-statistics-protocol.js +330 -0
- package/src/lib/evolution/rrsi-parent-binding.js +290 -0
- package/src/lib/evolution/rrsi-pm-execution-bridge.js +500 -0
- package/src/lib/evolution/rrsi-pm-training-mapping.js +134 -0
- package/src/lib/evolution/rrsi-preparation-contracts.js +213 -0
- package/src/lib/evolution/rrsi-registry-history-binding.js +193 -0
- package/src/lib/evolution/rrsi-registry-store-policy.js +1191 -0
- package/src/lib/evolution/rrsi-runtime-composition.js +79 -0
- package/src/lib/evolution/rrsi-selector.js +434 -0
- package/src/lib/evolution/rrsi-statistics-simulation.js +354 -0
- package/src/lib/evolution/skill-candidate-registry.js +216 -29
- package/src/lib/evolution/skill-registry-maintenance.js +80 -0
- package/src/lib/evolution/skill-registry-writer-control.js +138 -0
- package/src/lib/evolution/skill-release-registry.js +399 -169
- package/src/lib/formal-quality-eval-runtime.js +2 -14
- package/src/lib/goal-store.js +225 -16
- package/src/lib/process-execution-broker/index.js +91 -1
- package/src/lib/process-execution-broker/platform-sandbox.js +42 -0
- package/src/lib/process-execution-broker/windows-native-evaluator-capabilities.js +757 -0
- package/src/lib/process-execution-broker/windows-native-evaluator.js +316 -0
- package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
- package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
- package/src/lib/process-execution-broker/windows-sandbox.cs +383 -11
- package/src/lib/record-replay/skill-recorder.js +38 -3
- package/src/lib/scheduler-kernel/authority-resolver.js +12 -163
- package/src/lib/scheduler-kernel/contract.js +27 -414
- package/src/lib/scheduler-kernel/runtime.js +21 -823
- package/src/lib/scheduler-kernel/service.js +11 -328
- package/src/lib/scheduler-kernel/source-locator-path.js +7 -142
- package/src/lib/scheduler-kernel/store.js +67 -5931
- package/src/lib/secure-fs.js +16 -1314
- package/src/lib/with-file-lock.js +122 -20
- package/src/assets/web-panel/assets/MarkdownRenderer-CW3B3JDq.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DlIv9Mbc.js +0 -1
- package/src/assets/web-panel/assets/index-BC972Grv.js +0 -1
- package/src/assets/web-panel/assets/index-CVifyQqL.js +0 -1
|
@@ -9,9 +9,9 @@ import {
|
|
|
9
9
|
isEvolutionLedgerArtifactResolver,
|
|
10
10
|
} from "./evolution-artifact-ports.js";
|
|
11
11
|
import {
|
|
12
|
-
EvolutionLedger,
|
|
13
12
|
EVOLUTION_ARTIFACT_RESOLUTION_SCHEMA,
|
|
14
13
|
EVOLUTION_LEDGER_DOMAIN_EVENT_SCHEMA,
|
|
14
|
+
EVOLUTION_LEDGER_MAX_EVENTS,
|
|
15
15
|
} from "./evolution-ledger.js";
|
|
16
16
|
import {
|
|
17
17
|
verifyPmExplorationEffectPlan,
|
|
@@ -20,11 +20,37 @@ import {
|
|
|
20
20
|
import {
|
|
21
21
|
createEvolutionEvalLaunchAdmissionAuthority,
|
|
22
22
|
resolveEvolutionEvalLaunch,
|
|
23
|
+
resolveEvolutionEvalLaunchFromReadonlyAudit,
|
|
23
24
|
EVOLUTION_EVAL_LAUNCH_ADMISSION_EVENT_TYPE,
|
|
24
25
|
} from "./evolution-eval-launch-admission.js";
|
|
26
|
+
import {
|
|
27
|
+
captureEvolutionEvalLedger,
|
|
28
|
+
readEvolutionEvalLedger,
|
|
29
|
+
} from "./evolution-eval-ledger-capture.js";
|
|
30
|
+
import {
|
|
31
|
+
createEvolutionEvalReadonlyAudit,
|
|
32
|
+
captureEvolutionEvalReadonlyAudit,
|
|
33
|
+
} from "./evolution-eval-readonly-audit.js";
|
|
34
|
+
import { captureRrsiHistoryLedgerAdapter } from "./rrsi-history-ledger-adapter.js";
|
|
35
|
+
import { snapshotRrsiData } from "./rrsi-data.js";
|
|
36
|
+
import {
|
|
37
|
+
RRSI_COHORT_REGISTRATION_SCHEMA,
|
|
38
|
+
RRSI_COHORT_PLAN_SCHEMA,
|
|
39
|
+
RRSI_COHORT_PLAN_V2_SCHEMA,
|
|
40
|
+
buildRrsiEvalCampaignPlan,
|
|
41
|
+
buildRrsiCohortRegistration,
|
|
42
|
+
prepareRrsiCohortRegistration,
|
|
43
|
+
normalizeRrsiCohortLookup,
|
|
44
|
+
} from "./rrsi-cohort-registration.js";
|
|
25
45
|
|
|
26
46
|
export const EVOLUTION_EVAL_COHORT_ENROLLMENT_SCHEMA =
|
|
27
47
|
"chainlesschain.evolution-eval-cohort-enrollment/v1";
|
|
48
|
+
export const RRSI_EVAL_COHORT_ENROLLMENT_SCHEMA =
|
|
49
|
+
"chainlesschain.evolution-eval-cohort-enrollment/v2";
|
|
50
|
+
export const RRSI_EVAL_CAMPAIGN_ENROLLMENT_SCHEMA =
|
|
51
|
+
"chainlesschain.rrsi-eval-campaign-enrollment/v1";
|
|
52
|
+
export const RRSI_EVAL_CAMPAIGN_ENROLLMENT_EVENT_TYPE =
|
|
53
|
+
"evolution.rrsi-campaign.enrolled";
|
|
28
54
|
export const EVOLUTION_EVAL_COHORT_SEAL_SCHEMA =
|
|
29
55
|
"chainlesschain.evolution-eval-cohort-seal/v1";
|
|
30
56
|
export const EVOLUTION_EVAL_COHORT_ENROLLMENT_EVENT_TYPE =
|
|
@@ -163,32 +189,106 @@ function scopeId(input) {
|
|
|
163
189
|
);
|
|
164
190
|
}
|
|
165
191
|
function allEvents(state) {
|
|
166
|
-
return
|
|
192
|
+
return readEvolutionEvalLedger(state.ledgerMethods);
|
|
167
193
|
}
|
|
168
194
|
function head(state) {
|
|
169
|
-
return
|
|
195
|
+
return state.ledgerMethods.verify();
|
|
170
196
|
}
|
|
171
197
|
function eventId(state, cohortId, type) {
|
|
172
198
|
return `${type}.${hash("eval-cohort-identity/v1", { tenantId: state.descriptor.tenantId, streamId: state.descriptor.streamId, cohortId }).slice(7)}`;
|
|
173
199
|
}
|
|
174
|
-
function matching(state, cohortId, type) {
|
|
175
|
-
return allEvents(state).filter(
|
|
200
|
+
function matching(state, cohortId, type, census = null) {
|
|
201
|
+
return (census ?? allEvents(state)).filter(
|
|
176
202
|
(event) =>
|
|
177
203
|
event.schema === EVOLUTION_LEDGER_DOMAIN_EVENT_SCHEMA &&
|
|
178
204
|
event.eventId === eventId(state, cohortId, type),
|
|
179
205
|
);
|
|
180
206
|
}
|
|
181
|
-
|
|
182
|
-
|
|
207
|
+
const READONLY_COHORT_AUDITS = new WeakMap();
|
|
208
|
+
|
|
209
|
+
function nativeAuditContext(state, ledgerAudit) {
|
|
210
|
+
if (!state.rrsiHistory)
|
|
211
|
+
fail("native audit requires genuine RRSI History composition");
|
|
212
|
+
const shared = captureEvolutionEvalReadonlyAudit(ledgerAudit, state.ledger);
|
|
213
|
+
const context = {
|
|
214
|
+
ledgerAudit,
|
|
215
|
+
shared,
|
|
216
|
+
census: shared.events,
|
|
217
|
+
identity: shared.identity,
|
|
218
|
+
historyRoot: state.rrsiHistory.resolveCampaignRoot(),
|
|
219
|
+
resolutions: new Map(),
|
|
220
|
+
registrations: new Map(),
|
|
221
|
+
enrollments: new Map(),
|
|
222
|
+
reconciliations: new Map(),
|
|
223
|
+
verifiedAdmissions: new Map(),
|
|
224
|
+
};
|
|
225
|
+
context.campaign = resolveRrsiCampaign(state, context);
|
|
226
|
+
return context;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** Read-only session caches are private, authority-bound and scoped to one journal snapshot. */
|
|
230
|
+
export function createRrsiEvalCohortReadonlyAudit(
|
|
231
|
+
authority,
|
|
232
|
+
ledgerAudit = null,
|
|
233
|
+
) {
|
|
234
|
+
const state = stateOf(authority);
|
|
235
|
+
const context = nativeAuditContext(
|
|
236
|
+
state,
|
|
237
|
+
ledgerAudit ?? createEvolutionEvalReadonlyAudit(state.ledger),
|
|
238
|
+
);
|
|
239
|
+
const session = Object.freeze({
|
|
240
|
+
schema: "chainlesschain.rrsi-cohort-readonly-audit/v1",
|
|
241
|
+
});
|
|
242
|
+
READONLY_COHORT_AUDITS.set(session, { state, context });
|
|
243
|
+
return session;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export function assertRrsiEvalCohortReadonlyAuditUnchanged(session) {
|
|
247
|
+
const captured = READONLY_COHORT_AUDITS.get(session);
|
|
248
|
+
if (!captured) fail("a branded native cohort audit is required");
|
|
249
|
+
return captured.context.shared.assertUnchanged();
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export async function resolveRrsiEvalCohortFromReadonlyAudit(
|
|
253
|
+
authority,
|
|
254
|
+
input,
|
|
255
|
+
session,
|
|
256
|
+
) {
|
|
257
|
+
const state = stateOf(authority);
|
|
258
|
+
const captured = READONLY_COHORT_AUDITS.get(session);
|
|
259
|
+
if (!captured || captured.state !== state)
|
|
260
|
+
fail("a matching branded native cohort audit is required");
|
|
261
|
+
captureEvolutionEvalReadonlyAudit(captured.context.ledgerAudit, state.ledger);
|
|
262
|
+
const cohortId = scopeId(input);
|
|
263
|
+
const reconciliation = await reconcileCohort(
|
|
264
|
+
state,
|
|
265
|
+
cohortId,
|
|
266
|
+
captured.context,
|
|
267
|
+
);
|
|
268
|
+
return frozen({
|
|
269
|
+
enrollment: captured.context.enrollments.get(cohortId),
|
|
270
|
+
reconciliation,
|
|
271
|
+
auditHead: captured.context.identity,
|
|
272
|
+
historicalSnapshotOnly: true,
|
|
273
|
+
requiresFinalAuditHeadCheck: true,
|
|
274
|
+
readyForExecution: false,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function admissions(state, nativeContext = null) {
|
|
279
|
+
if (nativeContext?.streamAdmissions) return nativeContext.streamAdmissions;
|
|
280
|
+
const result = (nativeContext?.census ?? allEvents(state)).filter(
|
|
183
281
|
(event) =>
|
|
184
282
|
event.schema === EVOLUTION_LEDGER_DOMAIN_EVENT_SCHEMA &&
|
|
185
283
|
event.type === EVOLUTION_EVAL_LAUNCH_ADMISSION_EVENT_TYPE &&
|
|
186
284
|
event.tenantId === state.descriptor.tenantId &&
|
|
187
285
|
event.correlationId === state.descriptor.streamId,
|
|
188
286
|
);
|
|
287
|
+
if (nativeContext?.ledgerAudit) nativeContext.streamAdmissions = result;
|
|
288
|
+
return result;
|
|
189
289
|
}
|
|
190
|
-
function readArtifact(state, event) {
|
|
191
|
-
const identity = head(state);
|
|
290
|
+
function readArtifact(state, event, wrapper = false, capturedIdentity = null) {
|
|
291
|
+
const identity = capturedIdentity ?? head(state);
|
|
192
292
|
const result = state.resolveArtifact({
|
|
193
293
|
epoch: identity.epoch,
|
|
194
294
|
ledgerId: identity.ledgerId,
|
|
@@ -219,7 +319,7 @@ function readArtifact(state, event) {
|
|
|
219
319
|
stored.type !== ARTIFACT_TYPE
|
|
220
320
|
)
|
|
221
321
|
fail("cohort durable artifact scope differs");
|
|
222
|
-
return stored.value;
|
|
322
|
+
return wrapper ? stored : stored.value;
|
|
223
323
|
}
|
|
224
324
|
function signatureMessage(core) {
|
|
225
325
|
return Buffer.from(`${core.schema}\0${canonical(core)}`, "utf8");
|
|
@@ -285,9 +385,66 @@ function issuedAt(state) {
|
|
|
285
385
|
if (!Number.isFinite(now)) fail("cohort clock is invalid");
|
|
286
386
|
return new Date(now).toISOString();
|
|
287
387
|
}
|
|
288
|
-
function validateRegistration(input) {
|
|
388
|
+
function validateRegistration(input, state, nativeContext = null) {
|
|
389
|
+
const nativeSource = snapshot(input);
|
|
390
|
+
if (
|
|
391
|
+
nativeSource.schema === RRSI_COHORT_REGISTRATION_SCHEMA ||
|
|
392
|
+
[RRSI_COHORT_PLAN_SCHEMA, RRSI_COHORT_PLAN_V2_SCHEMA].includes(
|
|
393
|
+
nativeSource.plan?.schema,
|
|
394
|
+
)
|
|
395
|
+
) {
|
|
396
|
+
if (!state?.rrsiHistory)
|
|
397
|
+
fail("native enrollment requires genuine RRSI History composition");
|
|
398
|
+
const source =
|
|
399
|
+
nativeSource.schema === RRSI_COHORT_REGISTRATION_SCHEMA
|
|
400
|
+
? normalizeRrsiCohortLookup(nativeSource)
|
|
401
|
+
: record(
|
|
402
|
+
nativeSource,
|
|
403
|
+
["plan", "manifest", "slots"],
|
|
404
|
+
"native cohort declaration",
|
|
405
|
+
);
|
|
406
|
+
const campaign = nativeContext?.campaign ?? resolveRrsiCampaign(state);
|
|
407
|
+
const batchDigest = source.batchDigest ?? source.plan.batchDigest;
|
|
408
|
+
if (
|
|
409
|
+
nativeContext?.expectedBatchDigest &&
|
|
410
|
+
nativeContext.expectedBatchDigest !== batchDigest
|
|
411
|
+
)
|
|
412
|
+
fail("native audit belongs to another batch");
|
|
413
|
+
const resolution =
|
|
414
|
+
nativeContext?.resolution ??
|
|
415
|
+
nativeContext?.resolutions?.get(batchDigest) ??
|
|
416
|
+
state.rrsiHistory.resolveNativeBatch({ batchDigest });
|
|
417
|
+
if (nativeContext?.resolutions)
|
|
418
|
+
nativeContext.resolutions.set(batchDigest, resolution);
|
|
419
|
+
if (resolution.batch.batchDigest !== batchDigest)
|
|
420
|
+
fail("native registration snapshot belongs to another batch");
|
|
421
|
+
const cohortId = source.cohortId ?? source.manifest.cohortId;
|
|
422
|
+
let prepared = nativeContext?.registrations?.get(batchDigest);
|
|
423
|
+
if (!prepared && nativeContext?.registrations) {
|
|
424
|
+
prepared = prepareRrsiCohortRegistration(
|
|
425
|
+
campaign.evidence.plan,
|
|
426
|
+
resolution,
|
|
427
|
+
);
|
|
428
|
+
nativeContext.registrations.set(batchDigest, prepared);
|
|
429
|
+
}
|
|
430
|
+
const derived = prepared
|
|
431
|
+
? prepared.build(cohortId)
|
|
432
|
+
: buildRrsiCohortRegistration(
|
|
433
|
+
campaign.evidence.plan,
|
|
434
|
+
resolution,
|
|
435
|
+
cohortId,
|
|
436
|
+
);
|
|
437
|
+
if (state.descriptor.streamId !== derived.plan.queryStreamId)
|
|
438
|
+
fail("native cohort must use its global History query stream");
|
|
439
|
+
if (
|
|
440
|
+
nativeSource.schema !== RRSI_COHORT_REGISTRATION_SCHEMA &&
|
|
441
|
+
canonical(nativeSource) !== canonical(derived)
|
|
442
|
+
)
|
|
443
|
+
fail("native cohort declaration differs from committed History");
|
|
444
|
+
return frozen(derived);
|
|
445
|
+
}
|
|
289
446
|
const source = record(
|
|
290
|
-
|
|
447
|
+
nativeSource,
|
|
291
448
|
["plan", "manifest", "slots"],
|
|
292
449
|
"cohort registration",
|
|
293
450
|
);
|
|
@@ -312,6 +469,19 @@ function validateRegistration(input) {
|
|
|
312
469
|
return frozen({ plan, manifest, slots });
|
|
313
470
|
}
|
|
314
471
|
const ENROLL_FIELDS = ["cohortId", "plan", "manifest", "slots", "issuedAt"];
|
|
472
|
+
function nativeRegistrationSourceRefs(campaign, registration) {
|
|
473
|
+
const statistics = registration.manifest.statisticsRegistration;
|
|
474
|
+
return [
|
|
475
|
+
campaign.enrollmentRef,
|
|
476
|
+
registration.manifest.reservationRecord.ref,
|
|
477
|
+
...(statistics
|
|
478
|
+
? [
|
|
479
|
+
statistics.scopeRegistrationRecord.ref,
|
|
480
|
+
statistics.planRegistrationRecord.ref,
|
|
481
|
+
]
|
|
482
|
+
: []),
|
|
483
|
+
];
|
|
484
|
+
}
|
|
315
485
|
const SEAL_FIELDS = [
|
|
316
486
|
"cohortId",
|
|
317
487
|
"enrollmentDigest",
|
|
@@ -320,6 +490,17 @@ const SEAL_FIELDS = [
|
|
|
320
490
|
"issuedAt",
|
|
321
491
|
];
|
|
322
492
|
function checkEvent(state, event, cohortId, type, evidence, sourceRefs) {
|
|
493
|
+
const expectedRefs = [...sourceRefs].sort((left, right) =>
|
|
494
|
+
left.ref < right.ref
|
|
495
|
+
? -1
|
|
496
|
+
: left.ref > right.ref
|
|
497
|
+
? 1
|
|
498
|
+
: left.digest < right.digest
|
|
499
|
+
? -1
|
|
500
|
+
: left.digest > right.digest
|
|
501
|
+
? 1
|
|
502
|
+
: 0,
|
|
503
|
+
);
|
|
323
504
|
if (
|
|
324
505
|
event.eventId !== eventId(state, cohortId, type) ||
|
|
325
506
|
event.type !== type ||
|
|
@@ -329,29 +510,38 @@ function checkEvent(state, event, cohortId, type, evidence, sourceRefs) {
|
|
|
329
510
|
event.decision !== "accepted" ||
|
|
330
511
|
event.skillName !== "evolution-eval" ||
|
|
331
512
|
event.timestamp !== evidence.issuedAt ||
|
|
332
|
-
canonical(event.sourceRefs) !== canonical(
|
|
513
|
+
canonical(event.sourceRefs) !== canonical(expectedRefs)
|
|
333
514
|
)
|
|
334
515
|
fail("cohort Ledger event differs from signed evidence");
|
|
335
516
|
}
|
|
336
|
-
function resolveEnrollment(state, cohortId) {
|
|
517
|
+
function resolveEnrollment(state, cohortId, nativeContext = null) {
|
|
518
|
+
if (nativeContext?.enrollments?.has(cohortId))
|
|
519
|
+
return nativeContext.enrollments.get(cohortId);
|
|
337
520
|
const found = matching(
|
|
338
521
|
state,
|
|
339
522
|
cohortId,
|
|
340
523
|
EVOLUTION_EVAL_COHORT_ENROLLMENT_EVENT_TYPE,
|
|
524
|
+
nativeContext?.census ?? null,
|
|
341
525
|
);
|
|
342
526
|
if (found.length !== 1) fail("cohort enrollment is absent or ambiguous");
|
|
343
527
|
const event = found[0];
|
|
344
528
|
const evidence = verifySigned(
|
|
345
529
|
state,
|
|
346
|
-
readArtifact(state, event),
|
|
347
|
-
|
|
530
|
+
readArtifact(state, event, false, nativeContext?.identity ?? null),
|
|
531
|
+
state.rrsiHistory
|
|
532
|
+
? RRSI_EVAL_COHORT_ENROLLMENT_SCHEMA
|
|
533
|
+
: EVOLUTION_EVAL_COHORT_ENROLLMENT_SCHEMA,
|
|
348
534
|
ENROLL_FIELDS,
|
|
349
535
|
);
|
|
350
|
-
const registration = validateRegistration(
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
536
|
+
const registration = validateRegistration(
|
|
537
|
+
{
|
|
538
|
+
plan: evidence.plan,
|
|
539
|
+
manifest: evidence.manifest,
|
|
540
|
+
slots: evidence.slots,
|
|
541
|
+
},
|
|
542
|
+
state,
|
|
543
|
+
nativeContext,
|
|
544
|
+
);
|
|
355
545
|
if (
|
|
356
546
|
evidence.cohortId !== cohortId ||
|
|
357
547
|
registration.manifest.cohortId !== cohortId
|
|
@@ -363,9 +553,14 @@ function resolveEnrollment(state, cohortId) {
|
|
|
363
553
|
cohortId,
|
|
364
554
|
EVOLUTION_EVAL_COHORT_ENROLLMENT_EVENT_TYPE,
|
|
365
555
|
evidence,
|
|
366
|
-
|
|
556
|
+
state.rrsiHistory
|
|
557
|
+
? nativeRegistrationSourceRefs(
|
|
558
|
+
nativeContext?.campaign ?? resolveRrsiCampaign(state),
|
|
559
|
+
registration,
|
|
560
|
+
)
|
|
561
|
+
: [],
|
|
367
562
|
);
|
|
368
|
-
|
|
563
|
+
const result = frozen({
|
|
369
564
|
schema: "chainlesschain.evolution-eval-cohort-enrollment-resolution/v1",
|
|
370
565
|
enrollmentDigest: hash(evidence.schema, evidence),
|
|
371
566
|
evidence,
|
|
@@ -375,8 +570,20 @@ function resolveEnrollment(state, cohortId) {
|
|
|
375
570
|
durable: true,
|
|
376
571
|
...LIMITS,
|
|
377
572
|
});
|
|
573
|
+
if (nativeContext?.enrollments)
|
|
574
|
+
nativeContext.enrollments.set(cohortId, result);
|
|
575
|
+
return result;
|
|
378
576
|
}
|
|
379
577
|
function publish(state, cohortId, type, evidence, sourceRefs, expectedHead) {
|
|
578
|
+
if (state.rrsiHistory) snapshotRrsiData(evidence);
|
|
579
|
+
if (
|
|
580
|
+
state.rrsiHistory &&
|
|
581
|
+
expectedHead.sequence +
|
|
582
|
+
1 +
|
|
583
|
+
(state.rrsiHistory.inspect().nativeRecoveryEventHolds ?? 0) >
|
|
584
|
+
EVOLUTION_LEDGER_MAX_EVENTS
|
|
585
|
+
)
|
|
586
|
+
fail("cohort must preserve native History recovery capacity");
|
|
380
587
|
const published = EvolutionArtifactPorts.prototype.putCanonical.call(
|
|
381
588
|
state.artifactPorts,
|
|
382
589
|
ARTIFACT_TYPE,
|
|
@@ -394,8 +601,9 @@ function publish(state, cohortId, type, evidence, sourceRefs, expectedHead) {
|
|
|
394
601
|
published.receipt.retention !== "ledger"
|
|
395
602
|
)
|
|
396
603
|
fail("cohort artifact persistence failed");
|
|
397
|
-
|
|
398
|
-
state.
|
|
604
|
+
if (state.rrsiHistory)
|
|
605
|
+
snapshotRrsiData(readArtifact(state, { subjectRef: published.ref }, true));
|
|
606
|
+
const receipt = state.ledgerMethods.appendDomainEvent(
|
|
399
607
|
{
|
|
400
608
|
type,
|
|
401
609
|
eventId: eventId(state, cohortId, type),
|
|
@@ -419,6 +627,109 @@ function publish(state, cohortId, type, evidence, sourceRefs, expectedHead) {
|
|
|
419
627
|
fail("cohort Ledger persistence failed");
|
|
420
628
|
}
|
|
421
629
|
|
|
630
|
+
function rrsiCampaignState(state, historyRoot = null) {
|
|
631
|
+
if (!state.rrsiHistory)
|
|
632
|
+
fail("RRSI campaign needs genuine History composition");
|
|
633
|
+
const plan = buildRrsiEvalCampaignPlan(
|
|
634
|
+
historyRoot ?? state.rrsiHistory.resolveCampaignRoot(),
|
|
635
|
+
);
|
|
636
|
+
return {
|
|
637
|
+
...state,
|
|
638
|
+
descriptor: frozen({
|
|
639
|
+
...state.descriptor,
|
|
640
|
+
streamId: `rrsi-root.${plan.campaignRootDigest.slice(7)}`,
|
|
641
|
+
}),
|
|
642
|
+
campaignPlan: plan,
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
function resolveRrsiCampaign(state, nativeContext = null) {
|
|
647
|
+
const root = rrsiCampaignState(state, nativeContext?.historyRoot ?? null);
|
|
648
|
+
const cohortId = root.campaignPlan.campaignRootDigest;
|
|
649
|
+
const matches = matching(
|
|
650
|
+
root,
|
|
651
|
+
cohortId,
|
|
652
|
+
RRSI_EVAL_CAMPAIGN_ENROLLMENT_EVENT_TYPE,
|
|
653
|
+
nativeContext?.census ?? null,
|
|
654
|
+
);
|
|
655
|
+
if (matches.length !== 1) fail("RRSI campaign root is absent or ambiguous");
|
|
656
|
+
const event = matches[0];
|
|
657
|
+
const evidence = verifySigned(
|
|
658
|
+
root,
|
|
659
|
+
readArtifact(root, event, false, nativeContext?.identity ?? null),
|
|
660
|
+
RRSI_EVAL_CAMPAIGN_ENROLLMENT_SCHEMA,
|
|
661
|
+
["cohortId", "plan", "issuedAt"],
|
|
662
|
+
);
|
|
663
|
+
if (
|
|
664
|
+
evidence.cohortId !== cohortId ||
|
|
665
|
+
canonical(evidence.plan) !== canonical(root.campaignPlan)
|
|
666
|
+
)
|
|
667
|
+
fail("RRSI signed campaign root differs from durable History");
|
|
668
|
+
checkEvent(
|
|
669
|
+
root,
|
|
670
|
+
event,
|
|
671
|
+
cohortId,
|
|
672
|
+
RRSI_EVAL_CAMPAIGN_ENROLLMENT_EVENT_TYPE,
|
|
673
|
+
evidence,
|
|
674
|
+
[root.campaignPlan.rootRegistrationRecord.ref],
|
|
675
|
+
);
|
|
676
|
+
return frozen({
|
|
677
|
+
enrollmentDigest: hash(evidence.schema, evidence),
|
|
678
|
+
enrollmentRef: event.subjectRef,
|
|
679
|
+
enrollmentSequence: event.sequence,
|
|
680
|
+
evidence,
|
|
681
|
+
authenticated: true,
|
|
682
|
+
durable: true,
|
|
683
|
+
productionAdmissionVerified: false,
|
|
684
|
+
promotionAuthority: false,
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/** Freeze the shared History quota root before any native child dispatch. */
|
|
689
|
+
export function enrollRrsiEvalCampaign(authority) {
|
|
690
|
+
const state = stateOf(authority);
|
|
691
|
+
const expectedHead = head(state);
|
|
692
|
+
const root = rrsiCampaignState(state);
|
|
693
|
+
const cohortId = root.campaignPlan.campaignRootDigest;
|
|
694
|
+
if (matching(root, cohortId, RRSI_EVAL_CAMPAIGN_ENROLLMENT_EVENT_TYPE).length)
|
|
695
|
+
fail("RRSI campaign root is already enrolled");
|
|
696
|
+
if (
|
|
697
|
+
state.rrsiHistory
|
|
698
|
+
.inspect()
|
|
699
|
+
.executions.some(
|
|
700
|
+
(entry) =>
|
|
701
|
+
entry.reservation.schema ===
|
|
702
|
+
"chainlesschain.rrsi-native-reservation/v1" && entry.dispatched,
|
|
703
|
+
)
|
|
704
|
+
)
|
|
705
|
+
fail("RRSI campaign root must precede native dispatch");
|
|
706
|
+
const evidence = verifySigned(
|
|
707
|
+
root,
|
|
708
|
+
sign(root, {
|
|
709
|
+
schema: RRSI_EVAL_CAMPAIGN_ENROLLMENT_SCHEMA,
|
|
710
|
+
descriptor: root.descriptor,
|
|
711
|
+
cohortId,
|
|
712
|
+
plan: root.campaignPlan,
|
|
713
|
+
issuedAt: issuedAt(root),
|
|
714
|
+
}),
|
|
715
|
+
RRSI_EVAL_CAMPAIGN_ENROLLMENT_SCHEMA,
|
|
716
|
+
["cohortId", "plan", "issuedAt"],
|
|
717
|
+
);
|
|
718
|
+
publish(
|
|
719
|
+
root,
|
|
720
|
+
cohortId,
|
|
721
|
+
RRSI_EVAL_CAMPAIGN_ENROLLMENT_EVENT_TYPE,
|
|
722
|
+
evidence,
|
|
723
|
+
[root.campaignPlan.rootRegistrationRecord.ref],
|
|
724
|
+
expectedHead,
|
|
725
|
+
);
|
|
726
|
+
return resolveRrsiCampaign(state);
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
export function resolveRrsiEvalCampaign(authority) {
|
|
730
|
+
return resolveRrsiCampaign(stateOf(authority));
|
|
731
|
+
}
|
|
732
|
+
|
|
422
733
|
export function createEvolutionEvalCohortEnrollmentAuthority({
|
|
423
734
|
descriptor,
|
|
424
735
|
publicKey,
|
|
@@ -427,6 +738,7 @@ export function createEvolutionEvalCohortEnrollmentAuthority({
|
|
|
427
738
|
ledger,
|
|
428
739
|
ledgerArtifactResolver,
|
|
429
740
|
now = Date.now,
|
|
741
|
+
rrsiHistoryAdapter = null,
|
|
430
742
|
} = {}) {
|
|
431
743
|
const scope = record(
|
|
432
744
|
descriptor,
|
|
@@ -440,11 +752,30 @@ export function createEvolutionEvalCohortEnrollmentAuthority({
|
|
|
440
752
|
if (
|
|
441
753
|
!(artifactPorts instanceof EvolutionArtifactPorts) ||
|
|
442
754
|
isProxy(artifactPorts) ||
|
|
443
|
-
!(ledger instanceof EvolutionLedger) ||
|
|
444
755
|
isProxy(ledger) ||
|
|
445
756
|
!isEvolutionLedgerArtifactResolver(ledgerArtifactResolver)
|
|
446
757
|
)
|
|
447
758
|
fail("cohort requires real artifact ports, Ledger and branded resolver");
|
|
759
|
+
let ledgerMethods;
|
|
760
|
+
try {
|
|
761
|
+
ledgerMethods = captureEvolutionEvalLedger(ledger);
|
|
762
|
+
} catch {
|
|
763
|
+
fail("cohort requires real artifact ports, Ledger and branded resolver");
|
|
764
|
+
}
|
|
765
|
+
const rrsiHistory =
|
|
766
|
+
rrsiHistoryAdapter === null
|
|
767
|
+
? null
|
|
768
|
+
: captureRrsiHistoryLedgerAdapter(rrsiHistoryAdapter);
|
|
769
|
+
if (
|
|
770
|
+
rrsiHistory &&
|
|
771
|
+
(rrsiHistory.ledger !== ledger ||
|
|
772
|
+
rrsiHistory.artifactPorts !== artifactPorts ||
|
|
773
|
+
rrsiHistory.ledgerArtifactResolver !== ledgerArtifactResolver ||
|
|
774
|
+
["tenantId", "artifactTenantId", "audience", "purpose"].some(
|
|
775
|
+
(name) => rrsiHistory.descriptor[name] !== scope[name],
|
|
776
|
+
))
|
|
777
|
+
)
|
|
778
|
+
fail("native cohort must use the same History storage and scope");
|
|
448
779
|
if (!signer || isProxy(signer) || typeof now !== "function" || isProxy(now))
|
|
449
780
|
fail("cohort signer and clock are required");
|
|
450
781
|
const signing = Object.getOwnPropertyDescriptor(signer, "sign")?.value;
|
|
@@ -463,6 +794,8 @@ export function createEvolutionEvalCohortEnrollmentAuthority({
|
|
|
463
794
|
sign: signing.bind(signer),
|
|
464
795
|
artifactPorts,
|
|
465
796
|
ledger,
|
|
797
|
+
ledgerMethods,
|
|
798
|
+
rrsiHistory,
|
|
466
799
|
resolveArtifact: ledgerArtifactResolver,
|
|
467
800
|
now,
|
|
468
801
|
});
|
|
@@ -471,7 +804,14 @@ export function createEvolutionEvalCohortEnrollmentAuthority({
|
|
|
471
804
|
|
|
472
805
|
export function enrollEvolutionEvalCohort(authority, input) {
|
|
473
806
|
const state = stateOf(authority);
|
|
474
|
-
const registration = validateRegistration(input);
|
|
807
|
+
const registration = validateRegistration(input, state);
|
|
808
|
+
if (
|
|
809
|
+
state.rrsiHistory &&
|
|
810
|
+
![RRSI_COHORT_PLAN_SCHEMA, RRSI_COHORT_PLAN_V2_SCHEMA].includes(
|
|
811
|
+
registration.plan.schema,
|
|
812
|
+
)
|
|
813
|
+
)
|
|
814
|
+
fail("native authority cannot downgrade to PM enrollment");
|
|
475
815
|
const cohortId = registration.manifest.cohortId;
|
|
476
816
|
const expectedHead = head(state);
|
|
477
817
|
if (
|
|
@@ -484,16 +824,32 @@ export function enrollEvolutionEvalCohort(authority, input) {
|
|
|
484
824
|
// Legacy admissions cannot establish a trustworthy cohort identity.
|
|
485
825
|
if (admissions(state).length)
|
|
486
826
|
fail("stream admission already exists before enrollment");
|
|
827
|
+
if (state.rrsiHistory) {
|
|
828
|
+
const resolution = state.rrsiHistory.resolveNativeBatch({
|
|
829
|
+
batchDigest: registration.plan.batchDigest,
|
|
830
|
+
});
|
|
831
|
+
if (
|
|
832
|
+
resolution.budgetOverrun ||
|
|
833
|
+
resolution.children.some((child) =>
|
|
834
|
+
child.states.some((arm) => arm.status !== "reserved" || arm.dispatched),
|
|
835
|
+
)
|
|
836
|
+
)
|
|
837
|
+
fail("native enrollment must precede every paired dispatch in its query");
|
|
838
|
+
}
|
|
487
839
|
const evidence = verifySigned(
|
|
488
840
|
state,
|
|
489
841
|
sign(state, {
|
|
490
|
-
schema:
|
|
842
|
+
schema: state.rrsiHistory
|
|
843
|
+
? RRSI_EVAL_COHORT_ENROLLMENT_SCHEMA
|
|
844
|
+
: EVOLUTION_EVAL_COHORT_ENROLLMENT_SCHEMA,
|
|
491
845
|
descriptor: state.descriptor,
|
|
492
846
|
cohortId,
|
|
493
847
|
...registration,
|
|
494
848
|
issuedAt: issuedAt(state),
|
|
495
849
|
}),
|
|
496
|
-
|
|
850
|
+
state.rrsiHistory
|
|
851
|
+
? RRSI_EVAL_COHORT_ENROLLMENT_SCHEMA
|
|
852
|
+
: EVOLUTION_EVAL_COHORT_ENROLLMENT_SCHEMA,
|
|
497
853
|
ENROLL_FIELDS,
|
|
498
854
|
);
|
|
499
855
|
publish(
|
|
@@ -501,7 +857,9 @@ export function enrollEvolutionEvalCohort(authority, input) {
|
|
|
501
857
|
cohortId,
|
|
502
858
|
EVOLUTION_EVAL_COHORT_ENROLLMENT_EVENT_TYPE,
|
|
503
859
|
evidence,
|
|
504
|
-
|
|
860
|
+
state.rrsiHistory
|
|
861
|
+
? nativeRegistrationSourceRefs(resolveRrsiCampaign(state), registration)
|
|
862
|
+
: [],
|
|
505
863
|
expectedHead,
|
|
506
864
|
);
|
|
507
865
|
const result = resolveEnrollment(state, cohortId);
|
|
@@ -514,6 +872,22 @@ export function resolveEvolutionEvalCohortEnrollment(authority, input) {
|
|
|
514
872
|
return resolveEnrollment(stateOf(authority), scopeId(input));
|
|
515
873
|
}
|
|
516
874
|
|
|
875
|
+
/** Read-only identity check, never an admission or dispatch capability. */
|
|
876
|
+
export function assertRrsiEvalCohortHistoryComposition(authority, adapter) {
|
|
877
|
+
const state = stateOf(authority);
|
|
878
|
+
const history = captureRrsiHistoryLedgerAdapter(adapter);
|
|
879
|
+
if (
|
|
880
|
+
!state.rrsiHistory ||
|
|
881
|
+
state.rrsiHistory.ledger !== history.ledger ||
|
|
882
|
+
state.rrsiHistory.artifactPorts !== history.artifactPorts ||
|
|
883
|
+
state.rrsiHistory.ledgerArtifactResolver !==
|
|
884
|
+
history.ledgerArtifactResolver ||
|
|
885
|
+
canonical(state.rrsiHistory.descriptor) !== canonical(history.descriptor)
|
|
886
|
+
)
|
|
887
|
+
fail("native cohort census requires the same History storage and scope");
|
|
888
|
+
return true;
|
|
889
|
+
}
|
|
890
|
+
|
|
517
891
|
function slotDescriptor(state, enrollment, slot) {
|
|
518
892
|
return frozen({
|
|
519
893
|
...state.descriptor,
|
|
@@ -523,7 +897,55 @@ function slotDescriptor(state, enrollment, slot) {
|
|
|
523
897
|
slotId: slot.slotId,
|
|
524
898
|
});
|
|
525
899
|
}
|
|
526
|
-
function
|
|
900
|
+
function assertNativeQueryReady(state, enrollment) {
|
|
901
|
+
const campaign = resolveRrsiCampaign(state);
|
|
902
|
+
const resolution = state.rrsiHistory.resolveNativeBatch({
|
|
903
|
+
batchDigest: enrollment.evidence.plan.batchDigest,
|
|
904
|
+
});
|
|
905
|
+
if (resolution.budgetOverrun) fail("native History has a resource overrun");
|
|
906
|
+
if (
|
|
907
|
+
head(state).sequence + 1 + resolution.recoveryEventsHeld >
|
|
908
|
+
EVOLUTION_LEDGER_MAX_EVENTS
|
|
909
|
+
)
|
|
910
|
+
fail("admission must preserve native History recovery capacity");
|
|
911
|
+
const identity = head(state);
|
|
912
|
+
const census = allEvents(state);
|
|
913
|
+
for (const cohortId of enrollment.evidence.manifest.allCohortIds) {
|
|
914
|
+
const sibling = resolveEnrollment(state, cohortId, {
|
|
915
|
+
campaign,
|
|
916
|
+
resolution,
|
|
917
|
+
census,
|
|
918
|
+
identity,
|
|
919
|
+
});
|
|
920
|
+
if (
|
|
921
|
+
![RRSI_COHORT_PLAN_SCHEMA, RRSI_COHORT_PLAN_V2_SCHEMA].includes(
|
|
922
|
+
sibling.evidence.plan.schema,
|
|
923
|
+
) ||
|
|
924
|
+
sibling.evidence.plan.schema !== enrollment.evidence.plan.schema ||
|
|
925
|
+
canonical(sibling.evidence.manifest.statisticsRegistration ?? null) !==
|
|
926
|
+
canonical(
|
|
927
|
+
enrollment.evidence.manifest.statisticsRegistration ?? null,
|
|
928
|
+
) ||
|
|
929
|
+
sibling.evidence.plan.batchDigest !==
|
|
930
|
+
enrollment.evidence.plan.batchDigest ||
|
|
931
|
+
sibling.evidence.manifest.queryOrdinal !==
|
|
932
|
+
enrollment.evidence.manifest.queryOrdinal ||
|
|
933
|
+
canonical(sibling.evidence.manifest.reservationRecord) !==
|
|
934
|
+
canonical(enrollment.evidence.manifest.reservationRecord)
|
|
935
|
+
)
|
|
936
|
+
fail("native query enrollment barrier is incomplete or substituted");
|
|
937
|
+
}
|
|
938
|
+
const current = head(state);
|
|
939
|
+
if (
|
|
940
|
+
["ledgerId", "identityDigest", "epoch", "headDigest", "sequence"].some(
|
|
941
|
+
(name) => current[name] !== identity[name],
|
|
942
|
+
)
|
|
943
|
+
)
|
|
944
|
+
fail("Ledger changed during native query barrier; retry audit");
|
|
945
|
+
return resolution;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
function deriveSlot(state, enrollment, slot, freshChild = null) {
|
|
527
949
|
const descriptor = slotDescriptor(state, enrollment, slot);
|
|
528
950
|
const expectedRequest = frozen({
|
|
529
951
|
requestDigest: slot.requestDigest,
|
|
@@ -531,12 +953,95 @@ function deriveSlot(state, enrollment, slot) {
|
|
|
531
953
|
evaluationAuthorityRoot: slot.evaluationAuthorityRoot,
|
|
532
954
|
});
|
|
533
955
|
const binding = Object.freeze({});
|
|
956
|
+
const nativeChild = state.rrsiHistory
|
|
957
|
+
? enrollment.evidence.manifest.childBindings.find(
|
|
958
|
+
(child) => child.slotId === slot.slotId,
|
|
959
|
+
)
|
|
960
|
+
: null;
|
|
961
|
+
let preparedAttempt = false;
|
|
962
|
+
let livePermit = null;
|
|
963
|
+
const recordNativeFailure = () => {
|
|
964
|
+
const resolution = state.rrsiHistory.resolveNativeBatch({
|
|
965
|
+
batchDigest: enrollment.evidence.plan.batchDigest,
|
|
966
|
+
});
|
|
967
|
+
const child = resolution.children.find(
|
|
968
|
+
(child) => child.bindings.childId === nativeChild.childId,
|
|
969
|
+
);
|
|
970
|
+
if (
|
|
971
|
+
child?.states.some(
|
|
972
|
+
(arm) => arm.dispatched && arm.status === "dispatch-intent",
|
|
973
|
+
)
|
|
974
|
+
)
|
|
975
|
+
state.rrsiHistory.markNativeUnknown({
|
|
976
|
+
childId: nativeChild.childId,
|
|
977
|
+
batchDigest: enrollment.evidence.plan.batchDigest,
|
|
978
|
+
});
|
|
979
|
+
};
|
|
534
980
|
SLOT_BINDINGS.set(binding, {
|
|
535
981
|
state,
|
|
536
982
|
descriptor,
|
|
537
983
|
enrollmentDigest: enrollment.enrollmentDigest,
|
|
538
984
|
enrollmentRef: enrollment.enrollmentRef,
|
|
539
985
|
expectedRequest,
|
|
986
|
+
...(state.rrsiHistory
|
|
987
|
+
? {
|
|
988
|
+
registrationKind: "rrsi-native",
|
|
989
|
+
historyBinding: {
|
|
990
|
+
campaignRootDigest: enrollment.evidence.plan.campaignRootDigest,
|
|
991
|
+
batchDigest: enrollment.evidence.plan.batchDigest,
|
|
992
|
+
childId: nativeChild.childId,
|
|
993
|
+
queryOrdinal: enrollment.evidence.manifest.queryOrdinal,
|
|
994
|
+
},
|
|
995
|
+
prepare(input) {
|
|
996
|
+
if (preparedAttempt)
|
|
997
|
+
fail("native admission permit has already been consumed");
|
|
998
|
+
preparedAttempt = true;
|
|
999
|
+
if (!freshChild)
|
|
1000
|
+
fail("native admission requires a fresh paired child capability");
|
|
1001
|
+
for (const key of Object.keys(expectedRequest))
|
|
1002
|
+
if (input[key] !== expectedRequest[key])
|
|
1003
|
+
fail("native admission request differs from enrolled child");
|
|
1004
|
+
state.rrsiHistory.assertNativeFreshChild(
|
|
1005
|
+
freshChild,
|
|
1006
|
+
nativeChild.bindings,
|
|
1007
|
+
);
|
|
1008
|
+
const resolution = assertNativeQueryReady(state, enrollment);
|
|
1009
|
+
const child = resolution.children.find(
|
|
1010
|
+
(child) => child.bindings.childId === nativeChild.childId,
|
|
1011
|
+
);
|
|
1012
|
+
if (
|
|
1013
|
+
!child ||
|
|
1014
|
+
child.states.some(
|
|
1015
|
+
(arm) => arm.status !== "reserved" || arm.dispatched,
|
|
1016
|
+
)
|
|
1017
|
+
)
|
|
1018
|
+
fail("native child is not fresh and reserved");
|
|
1019
|
+
if (
|
|
1020
|
+
matching(
|
|
1021
|
+
state,
|
|
1022
|
+
descriptor.cohortId,
|
|
1023
|
+
EVOLUTION_EVAL_COHORT_SEAL_EVENT_TYPE,
|
|
1024
|
+
).length
|
|
1025
|
+
)
|
|
1026
|
+
fail("cohort is sealed");
|
|
1027
|
+
try {
|
|
1028
|
+
const dispatch =
|
|
1029
|
+
state.rrsiHistory.recordNativeDispatch(freshChild);
|
|
1030
|
+
if (!dispatch.newlyCommitted)
|
|
1031
|
+
fail("native dispatch outcome is not fresh");
|
|
1032
|
+
livePermit = frozen(snapshot(input));
|
|
1033
|
+
} catch (error) {
|
|
1034
|
+
try {
|
|
1035
|
+
recordNativeFailure();
|
|
1036
|
+
} catch {
|
|
1037
|
+
/* Admission is unavailable; intent remains held. */
|
|
1038
|
+
}
|
|
1039
|
+
throw error;
|
|
1040
|
+
}
|
|
1041
|
+
},
|
|
1042
|
+
recordFailure: recordNativeFailure,
|
|
1043
|
+
}
|
|
1044
|
+
: {}),
|
|
540
1045
|
assertOpen(input) {
|
|
541
1046
|
const current = resolveEnrollment(state, descriptor.cohortId);
|
|
542
1047
|
if (current.enrollmentDigest !== enrollment.enrollmentDigest)
|
|
@@ -552,6 +1057,21 @@ function deriveSlot(state, enrollment, slot) {
|
|
|
552
1057
|
for (const key of Object.keys(expectedRequest))
|
|
553
1058
|
if (input[key] !== expectedRequest[key])
|
|
554
1059
|
fail("admission request differs from enrolled slot");
|
|
1060
|
+
if (state.rrsiHistory) {
|
|
1061
|
+
if (!livePermit || canonical(input) !== canonical(livePermit))
|
|
1062
|
+
fail("native admission has no matching live run permit");
|
|
1063
|
+
const resolution = assertNativeQueryReady(state, enrollment);
|
|
1064
|
+
const child = resolution.children.find(
|
|
1065
|
+
(child) => child.bindings.childId === nativeChild.childId,
|
|
1066
|
+
);
|
|
1067
|
+
if (
|
|
1068
|
+
!child ||
|
|
1069
|
+
child.states.some(
|
|
1070
|
+
(arm) => !arm.dispatched || arm.status !== "dispatch-intent",
|
|
1071
|
+
)
|
|
1072
|
+
)
|
|
1073
|
+
fail("native child dispatch intent is stale or unresolved");
|
|
1074
|
+
}
|
|
555
1075
|
},
|
|
556
1076
|
});
|
|
557
1077
|
return createEvolutionEvalLaunchAdmissionAuthority({
|
|
@@ -583,6 +1103,14 @@ export function captureEvolutionEvalCohortSlotBinding(binding, expected) {
|
|
|
583
1103
|
enrollmentRef: captured.enrollmentRef,
|
|
584
1104
|
expectedRequest: captured.expectedRequest,
|
|
585
1105
|
assertOpen: captured.assertOpen,
|
|
1106
|
+
...(captured.registrationKind
|
|
1107
|
+
? {
|
|
1108
|
+
registrationKind: captured.registrationKind,
|
|
1109
|
+
historyBinding: captured.historyBinding,
|
|
1110
|
+
prepare: captured.prepare,
|
|
1111
|
+
recordFailure: captured.recordFailure,
|
|
1112
|
+
}
|
|
1113
|
+
: {}),
|
|
586
1114
|
});
|
|
587
1115
|
}
|
|
588
1116
|
|
|
@@ -591,7 +1119,21 @@ export function createEvolutionEvalCohortSlotAdmissionAuthority(
|
|
|
591
1119
|
input,
|
|
592
1120
|
) {
|
|
593
1121
|
const state = stateOf(authority);
|
|
594
|
-
const lookup = record(
|
|
1122
|
+
const lookup = record(
|
|
1123
|
+
input,
|
|
1124
|
+
[
|
|
1125
|
+
"cohortId",
|
|
1126
|
+
"slotId",
|
|
1127
|
+
...(state.rrsiHistory &&
|
|
1128
|
+
input &&
|
|
1129
|
+
typeof input === "object" &&
|
|
1130
|
+
!isProxy(input) &&
|
|
1131
|
+
Object.hasOwn(input, "freshChild")
|
|
1132
|
+
? ["freshChild"]
|
|
1133
|
+
: []),
|
|
1134
|
+
],
|
|
1135
|
+
"cohort slot lookup",
|
|
1136
|
+
);
|
|
595
1137
|
text(lookup.cohortId, "cohortId");
|
|
596
1138
|
text(lookup.slotId, "slotId");
|
|
597
1139
|
const enrollment = resolveEnrollment(state, lookup.cohortId);
|
|
@@ -599,15 +1141,105 @@ export function createEvolutionEvalCohortSlotAdmissionAuthority(
|
|
|
599
1141
|
(item) => item.slotId === lookup.slotId,
|
|
600
1142
|
);
|
|
601
1143
|
if (!slot) fail("slot is not in the enrolled manifest");
|
|
602
|
-
return deriveSlot(state, enrollment, slot);
|
|
1144
|
+
return deriveSlot(state, enrollment, slot, lookup.freshChild ?? null);
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
async function inventory(
|
|
1148
|
+
state,
|
|
1149
|
+
enrollment,
|
|
1150
|
+
sealSequence = Infinity,
|
|
1151
|
+
nativeContext = null,
|
|
1152
|
+
) {
|
|
1153
|
+
if (!nativeContext) return legacyInventory(state, enrollment, sealSequence);
|
|
1154
|
+
const result = [];
|
|
1155
|
+
const used = new Set();
|
|
1156
|
+
for (const event of admissions(state, nativeContext)) {
|
|
1157
|
+
let checked = nativeContext?.verifiedAdmissions?.get(event.eventId);
|
|
1158
|
+
let value, registered, slot, resolution;
|
|
1159
|
+
if (checked) ({ value, registered, slot, resolution } = checked);
|
|
1160
|
+
else {
|
|
1161
|
+
value = readArtifact(
|
|
1162
|
+
state,
|
|
1163
|
+
event,
|
|
1164
|
+
false,
|
|
1165
|
+
nativeContext?.identity ?? null,
|
|
1166
|
+
);
|
|
1167
|
+
// Reject ambiguous legacy entries instead of accepting a caller-selected subset.
|
|
1168
|
+
if (!value.descriptor)
|
|
1169
|
+
fail("legacy admission prevents complete cohort inventory");
|
|
1170
|
+
registered =
|
|
1171
|
+
value.descriptor.cohortId === enrollment.evidence.cohortId
|
|
1172
|
+
? enrollment
|
|
1173
|
+
: resolveEnrollment(
|
|
1174
|
+
state,
|
|
1175
|
+
text(value.descriptor.cohortId, "admission cohortId"),
|
|
1176
|
+
nativeContext,
|
|
1177
|
+
);
|
|
1178
|
+
slot = registered.evidence.slots.find(
|
|
1179
|
+
(item) => item.slotId === value.descriptor.slotId,
|
|
1180
|
+
);
|
|
1181
|
+
if (!slot) fail("unknown cohort admission slot");
|
|
1182
|
+
const authority = deriveSlot(state, registered, slot);
|
|
1183
|
+
const lookup = {
|
|
1184
|
+
runId: value.runId,
|
|
1185
|
+
runNonce: value.runNonce,
|
|
1186
|
+
requestDigest: value.requestDigest,
|
|
1187
|
+
};
|
|
1188
|
+
resolution = nativeContext?.ledgerAudit
|
|
1189
|
+
? await resolveEvolutionEvalLaunchFromReadonlyAudit(
|
|
1190
|
+
authority,
|
|
1191
|
+
lookup,
|
|
1192
|
+
nativeContext.ledgerAudit,
|
|
1193
|
+
)
|
|
1194
|
+
: await resolveEvolutionEvalLaunch(authority, lookup);
|
|
1195
|
+
if (
|
|
1196
|
+
resolution.eventId !== event.eventId ||
|
|
1197
|
+
resolution.eventSequence !== event.sequence ||
|
|
1198
|
+
canonical(resolution.evidence) !== canonical(value)
|
|
1199
|
+
)
|
|
1200
|
+
fail("cohort admission event substitution");
|
|
1201
|
+
if (nativeContext?.verifiedAdmissions)
|
|
1202
|
+
nativeContext.verifiedAdmissions.set(event.eventId, {
|
|
1203
|
+
value,
|
|
1204
|
+
registered,
|
|
1205
|
+
slot,
|
|
1206
|
+
resolution,
|
|
1207
|
+
});
|
|
1208
|
+
}
|
|
1209
|
+
const ownCohort =
|
|
1210
|
+
value.descriptor.cohortId === enrollment.evidence.cohortId;
|
|
1211
|
+
if (
|
|
1212
|
+
event.sequence <= registered.enrollmentSequence ||
|
|
1213
|
+
(ownCohort && event.sequence >= sealSequence)
|
|
1214
|
+
)
|
|
1215
|
+
fail("admission lies outside cohort enrollment/seal boundary");
|
|
1216
|
+
if (!slot || (ownCohort && used.has(slot.slotId)))
|
|
1217
|
+
fail("unknown or duplicate cohort admission slot");
|
|
1218
|
+
if (!ownCohort) continue;
|
|
1219
|
+
used.add(slot.slotId);
|
|
1220
|
+
result.push({
|
|
1221
|
+
slotId: slot.slotId,
|
|
1222
|
+
eventId: event.eventId,
|
|
1223
|
+
sequence: event.sequence,
|
|
1224
|
+
admissionDigest: resolution.admissionDigest,
|
|
1225
|
+
runId: value.runId,
|
|
1226
|
+
runNonce: value.runNonce,
|
|
1227
|
+
requestDigest: value.requestDigest,
|
|
1228
|
+
});
|
|
1229
|
+
}
|
|
1230
|
+
return frozen({
|
|
1231
|
+
admissions: result,
|
|
1232
|
+
unadmittedSlotIds: enrollment.evidence.slots
|
|
1233
|
+
.filter((slot) => !used.has(slot.slotId))
|
|
1234
|
+
.map((slot) => slot.slotId),
|
|
1235
|
+
});
|
|
603
1236
|
}
|
|
604
1237
|
|
|
605
|
-
async function
|
|
1238
|
+
async function legacyInventory(state, enrollment, sealSequence = Infinity) {
|
|
606
1239
|
const result = [];
|
|
607
1240
|
const used = new Set();
|
|
608
1241
|
for (const event of admissions(state)) {
|
|
609
1242
|
const value = readArtifact(state, event);
|
|
610
|
-
// Reject ambiguous legacy entries instead of accepting a caller-selected subset.
|
|
611
1243
|
if (!value.descriptor)
|
|
612
1244
|
fail("legacy admission prevents complete cohort inventory");
|
|
613
1245
|
const ownCohort =
|
|
@@ -667,10 +1299,14 @@ export async function sealEvolutionEvalCohort(authority, input) {
|
|
|
667
1299
|
const state = stateOf(authority);
|
|
668
1300
|
const cohortId = scopeId(input);
|
|
669
1301
|
const expectedHead = head(state);
|
|
670
|
-
const
|
|
1302
|
+
const context = state.rrsiHistory
|
|
1303
|
+
? nativeAuditContext(state, createEvolutionEvalReadonlyAudit(state.ledger))
|
|
1304
|
+
: null;
|
|
1305
|
+
const enrollment = resolveEnrollment(state, cohortId, context);
|
|
671
1306
|
if (matching(state, cohortId, EVOLUTION_EVAL_COHORT_SEAL_EVENT_TYPE).length)
|
|
672
1307
|
fail("cohort is already sealed");
|
|
673
|
-
const contents = await inventory(state, enrollment);
|
|
1308
|
+
const contents = await inventory(state, enrollment, Infinity, context);
|
|
1309
|
+
if (context) context.shared.assertUnchanged();
|
|
674
1310
|
const evidence = verifySigned(
|
|
675
1311
|
state,
|
|
676
1312
|
sign(state, {
|
|
@@ -706,18 +1342,30 @@ export async function resolveEvolutionEvalCohortReconciliation(
|
|
|
706
1342
|
) {
|
|
707
1343
|
const state = stateOf(authority);
|
|
708
1344
|
const cohortId = scopeId(input);
|
|
709
|
-
const
|
|
710
|
-
|
|
1345
|
+
const context = state.rrsiHistory
|
|
1346
|
+
? nativeAuditContext(state, createEvolutionEvalReadonlyAudit(state.ledger))
|
|
1347
|
+
: null;
|
|
1348
|
+
const result = await reconcileCohort(state, cohortId, context);
|
|
1349
|
+
if (context) context.shared.assertUnchanged();
|
|
1350
|
+
return result;
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
async function reconcileCohort(state, cohortId, nativeContext = null) {
|
|
1354
|
+
if (nativeContext?.reconciliations?.has(cohortId))
|
|
1355
|
+
return nativeContext.reconciliations.get(cohortId);
|
|
1356
|
+
const expectedHead = nativeContext?.identity ?? head(state);
|
|
1357
|
+
const enrollment = resolveEnrollment(state, cohortId, nativeContext);
|
|
711
1358
|
const matches = matching(
|
|
712
1359
|
state,
|
|
713
1360
|
cohortId,
|
|
714
1361
|
EVOLUTION_EVAL_COHORT_SEAL_EVENT_TYPE,
|
|
1362
|
+
nativeContext?.census ?? null,
|
|
715
1363
|
);
|
|
716
1364
|
if (matches.length !== 1) fail("cohort seal is absent or ambiguous");
|
|
717
1365
|
const event = matches[0];
|
|
718
1366
|
const evidence = verifySigned(
|
|
719
1367
|
state,
|
|
720
|
-
readArtifact(state, event),
|
|
1368
|
+
readArtifact(state, event, false, nativeContext?.identity ?? null),
|
|
721
1369
|
EVOLUTION_EVAL_COHORT_SEAL_SCHEMA,
|
|
722
1370
|
SEAL_FIELDS,
|
|
723
1371
|
);
|
|
@@ -729,7 +1377,7 @@ export async function resolveEvolutionEvalCohortReconciliation(
|
|
|
729
1377
|
evidence,
|
|
730
1378
|
[enrollment.enrollmentRef],
|
|
731
1379
|
);
|
|
732
|
-
const previous = allEvents(state).find(
|
|
1380
|
+
const previous = (nativeContext?.census ?? allEvents(state)).find(
|
|
733
1381
|
(item) => item.sequence === event.sequence - 1,
|
|
734
1382
|
);
|
|
735
1383
|
if (
|
|
@@ -743,28 +1391,46 @@ export async function resolveEvolutionEvalCohortReconciliation(
|
|
|
743
1391
|
})
|
|
744
1392
|
)
|
|
745
1393
|
fail("cohort seal boundary differs");
|
|
746
|
-
const contents = await inventory(
|
|
1394
|
+
const contents = await inventory(
|
|
1395
|
+
state,
|
|
1396
|
+
enrollment,
|
|
1397
|
+
event.sequence,
|
|
1398
|
+
nativeContext,
|
|
1399
|
+
);
|
|
747
1400
|
if (canonical(contents) !== canonical(evidence.inventory))
|
|
748
1401
|
fail("sealed cohort inventory differs from complete Ledger events");
|
|
749
|
-
const currentHead = head(state);
|
|
1402
|
+
const currentHead = nativeContext?.identity ?? head(state);
|
|
750
1403
|
if (
|
|
751
1404
|
currentHead.headDigest !== expectedHead.headDigest ||
|
|
752
1405
|
currentHead.sequence !== expectedHead.sequence
|
|
753
1406
|
)
|
|
754
1407
|
fail("Ledger changed during cohort reconciliation; retry audit");
|
|
755
|
-
|
|
756
|
-
schema:
|
|
1408
|
+
const result = frozen({
|
|
1409
|
+
schema: state.rrsiHistory
|
|
1410
|
+
? "chainlesschain.evolution-eval-cohort-reconciliation/v2"
|
|
1411
|
+
: "chainlesschain.evolution-eval-cohort-reconciliation/v1",
|
|
757
1412
|
cohortId,
|
|
758
1413
|
enrollmentDigest: enrollment.enrollmentDigest,
|
|
759
1414
|
sealDigest: hash(evidence.schema, evidence),
|
|
760
1415
|
sealSequence: event.sequence,
|
|
761
1416
|
inventory: contents,
|
|
762
|
-
|
|
763
|
-
|
|
1417
|
+
...(state.rrsiHistory
|
|
1418
|
+
? {
|
|
1419
|
+
plannedObservationsPerArmByPartition:
|
|
1420
|
+
enrollment.evidence.manifest.plannedObservationsPerArmByPartition,
|
|
1421
|
+
nativeExecutionDenominatorVerified: false,
|
|
1422
|
+
}
|
|
1423
|
+
: {
|
|
1424
|
+
plannedTestObservationsPerArm:
|
|
1425
|
+
enrollment.evidence.manifest.plannedTestObservationsPerArm,
|
|
1426
|
+
}),
|
|
764
1427
|
admissionInventoryAuthenticated: true,
|
|
765
1428
|
executionCoverageAuthenticated: false,
|
|
766
1429
|
authenticated: true,
|
|
767
1430
|
durable: true,
|
|
768
1431
|
...LIMITS,
|
|
769
1432
|
});
|
|
1433
|
+
if (nativeContext?.reconciliations)
|
|
1434
|
+
nativeContext.reconciliations.set(cohortId, result);
|
|
1435
|
+
return result;
|
|
770
1436
|
}
|