chainlesschain 0.166.6 → 0.166.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -1
- package/src/assets/web-panel/assets/{AIOps-CVnFjTfG.js → AIOps-BlrmQxa2.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BxkwuuQC.js → ActionButton-zyRyLITg.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-C2670q6z.js → Analytics-DwGz7OGN.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-CU_rylW6.js → AppLayout-Dc-nj7Zd.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-DGJmYqnj.js → Artifacts-7Hu3O73p.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-BZOQbINJ.js → Audit-Bnoe3-fR.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-DghB4QwF.js → BackgroundAgents-BqYFrDKZ.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-l0mwPbta.js → Backup-B3hwW1nz.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-Bv3WSZOh.js → BaseInput-XFVxLA4w.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-s88nBdvt.js → Chat-CWRDNw7e.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-Z8CBuB1a.js → ChatBubbleRenderer-Bf30VM8G.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-B5icasEs.js → Checkbox-kFeeBgac.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CsUFqNud.js → Codegen-CCxp8xoI.js} +1 -1
- package/src/assets/web-panel/assets/{Col-DlBtClaW.js → Col-BLKZalle.js} +1 -1
- package/src/assets/web-panel/assets/{Community-xRn1IdLB.js → Community-DD0eWCez.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-naIr8a_o.js → Compact-CHqHWdy0.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-Dp9esfFE.js → Compliance-Bw54uPiK.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DQlMYJB-.js → Cowork-DZ13zKNJ.js} +4 -4
- package/src/assets/web-panel/assets/{Cron-Cd0oNLzJ.js → Cron-Dlj5Jevg.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BtDIx3XX.js → Crosschain-Nvz0aR0j.js} +1 -1
- package/src/assets/web-panel/assets/{DID-BOlpzEwg.js → DID-Ct89eUyY.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-DV15Axk1.js → Dashboard-BHUH5IAe.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-COXrewN1.js → Dropdown-BhZG-PO7.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-EjIt0Cm7.js → EmailListRenderer-ae4RVwwJ.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-DJlhwb-R.js → FamilyGuardDashboard-AOcxLfLr.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BMiFl82k.js → Federation-BK2PJQOF.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-BUcDQyxn.js → FormItemContext-C2n3xO2_.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-C25uFxvK.js → GenericCardRenderer-DcyUVFZq.js} +1 -1
- package/src/assets/web-panel/assets/{Git-D20uaEUU.js → Git-tBae9Lt8.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CQxYJjCX.js → Governance-DmNR3AP4.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-m-sczpS5.js → Inference-CoseEigi.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-CBsIlU0S.js → KnowledgeGraph-Bdjd1sxr.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-D0-5bqeu.js → Logs-CtlkKIcn.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-BwH414Ms.js → MarkdownRenderer-CZsTBEQE.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-CwDGFu2Q.js → Marketplace-BTYb7nEx.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-7FxJ3omT.js → McpTools-D0iUdW3P.js} +2 -2
- package/src/assets/web-panel/assets/{Memory-DOVyb59U.js → Memory--gwI7w4Y.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-DZXl-Hje.js → MobileBridge-JmFBi24T.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-DlZ8tRXt.js → MobileProjects-BK01cQRx.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-D7Pjx1s_.js → Mtc-u7avzyoO.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-BND7lX8p.js → MtcAudit-gT3z5fo_.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-BknS7B-p.js → Multisig-BIqZTz5n.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-7C2-KPHt.js → NLProgramming-DdhVfXYq.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-DNWdTndN.js → Notes-CBlyUmY3.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-DCm4KcJZ.js → NotificationSettings-DSyI26N3.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DyVwwjJx.js → OrderTableRenderer-B7IEuNz4.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-Dl2O_qJ9.js → Organization-ozhi4kGS.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-BOFCvk9Q.js → Overflow-CBy57RVM.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-DgdVowY1.js → P2P-CA-ZRv77.js} +2 -2
- package/src/assets/web-panel/assets/PdhVaultBrowser-DOHc9zm8.js +7 -0
- package/src/assets/web-panel/assets/{Permissions-BHNEUUwa.js → Permissions-DiP632GP.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-CaZbrOdz.js → PersonalDataHub-AnU8O-SS.js} +5 -5
- package/src/assets/web-panel/assets/{Pipeline-DJDnoXmE.js → Pipeline-DDibOUaP.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-CBQr2eX8.js → Privacy-D421t36T.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-Yghqa06z.js → ProjectInit-DR879ZPJ.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-HBAtJi8U.js → ProjectSettings-Ded8o6aY.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-DiCGnMjz.js → Projects-BHPxiucB.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-uJTz77GI.js → Providers-Boivuu-E.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-k3M5ouTp.js → QrScannerModal-xKD_ntKp.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-CMji45PH.js → QuickAsk-D3y_A6FV.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DyoZYPls.js → Recommend-BjKM-YC2.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-s1gR38IO.js → RemoteSession-CgqKMXG4.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-D4hIs4vV.js → Reputation-Ci2GjH5p.js} +1 -1
- package/src/assets/web-panel/assets/{Row-mzE-ElTg.js → Row-B0-T2BSh.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-cg7J3hI6.js → RssFeed-Bet-ur-r.js} +3 -3
- package/src/assets/web-panel/assets/{Search-6M0TkGSZ.js → Search-DWtRAS2R.js} +1 -1
- package/src/assets/web-panel/assets/{Security-B1GQ67qh.js → Security-BDfu2Qn6.js} +4 -4
- package/src/assets/web-panel/assets/{Services-D_RwU_5S.js → Services-CvJmvSMM.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-TZjk-dsW.js → Skeleton-CEbrKpdC.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CG6FcaCV.js → Skills-CjVeiETf.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-BI190QDv.js → Sla-Dibypxum.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-BWmxF2Wu.js → SpeechSettings-XflYXp7a.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-CwPiGw6L.js → SyncSettings-ro1Ivx1E.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-BIXgCeSk.js → Tasks-CHq1qFbo.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CQFgGCoK.js → Templates-CRnUZxtZ.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-DAelEdkL.js → Tenant-jUX72JCA.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-BbqWK6qh.js → Terminal-BBhAs7pt.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-cmG3zvY5.js → TimelineRenderer-CD5M3RGp.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-C8444NKU.js → Tokens-sah3v0gu.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-C1Rpnz0I.js → Trigger-BNT3Uz3s.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-u4koPiFD.js → Trust-BytMGPMo.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-oPWKn80Z.js → UkeySign-BkYVMRQs.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-D0CUUY_5.js → VideoEditing-psvb5Q7Y.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-fu9pIAbt.js → Wallet-PFQTW0MH.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-Bc5ciuOx.js → WebAuthn-DgO-OwRT.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-BCin4_4N.js → WorkflowEditor-DL2l9VNl.js} +1 -1
- package/src/assets/web-panel/assets/{chat-B2jbM-XN.js → chat-C84akEzN.js} +1 -1
- package/src/assets/web-panel/assets/{colors-CUVoUQ_2.js → colors-DzTWuQKP.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-DgOGpkRH.js → compact-item-CR9LJQFv.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DIxU6eKI.js → createContext-CTTov5Kn.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BOhvmlpc.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DoKRKMav.js → hasIn-DALj523o.js} +1 -1
- package/src/assets/web-panel/assets/{index-i5MB455u.js → index-3-XJoYgX.js} +1 -1
- package/src/assets/web-panel/assets/{index-CLdpHe6w.js → index-7ux_XohH.js} +1 -1
- package/src/assets/web-panel/assets/{index-B3F_p8NA.js → index-AXnERsyV.js} +1 -1
- package/src/assets/web-panel/assets/{index-D2yo6ast.js → index-B2qpjU-D.js} +1 -1
- package/src/assets/web-panel/assets/{index-CWbL1-N0.js → index-B6QOJbSn.js} +1 -1
- package/src/assets/web-panel/assets/{index-DtyAuGOm.js → index-BDyt57zL.js} +1 -1
- package/src/assets/web-panel/assets/{index-DpTFx8Xx.js → index-BHRXKiU1.js} +1 -1
- package/src/assets/web-panel/assets/{index-CF80xxPG.js → index-BKNIzw0U.js} +1 -1
- package/src/assets/web-panel/assets/{index-BRMEO2Tl.js → index-BNaQt49r.js} +1 -1
- package/src/assets/web-panel/assets/{index-ByjrulIZ.js → index-Be6Os5S8.js} +1 -1
- package/src/assets/web-panel/assets/{index-BCLeNqIL.js → index-C5eeMl_2.js} +1 -1
- package/src/assets/web-panel/assets/{index-DJMHnbmu.js → index-CNmTDXmf.js} +1 -1
- package/src/assets/web-panel/assets/{index-2flsPFIX.js → index-CXTEpfGe.js} +1 -1
- package/src/assets/web-panel/assets/{index-BwYofQJg.js → index-CXaCRXN4.js} +1 -1
- package/src/assets/web-panel/assets/{index-B5ySiGYy.js → index-CZhhFQi9.js} +1 -1
- package/src/assets/web-panel/assets/{index-CeWSw-z5.js → index-Cef0n4k_.js} +1 -1
- package/src/assets/web-panel/assets/{index-C846lPGD.js → index-CjkPDSX4.js} +1 -1
- package/src/assets/web-panel/assets/{index-C9TsO9T9.js → index-CmELknPe.js} +1 -1
- package/src/assets/web-panel/assets/{index-CqlwIjJx.js → index-CnxjXIsK.js} +1 -1
- package/src/assets/web-panel/assets/{index-Co4lDEk-.js → index-CqUgXYIQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cj-us-D_.js → index-CunGDV0g.js} +1 -1
- package/src/assets/web-panel/assets/{index-BFUprhNd.js → index-D0MqUnKO.js} +1 -1
- package/src/assets/web-panel/assets/{index-DGTZdZOE.js → index-D9ScRFxz.js} +3 -3
- package/src/assets/web-panel/assets/{index-C88m9lsi.js → index-DBIPnoTj.js} +1 -1
- package/src/assets/web-panel/assets/index-DDyMJexx.js +1 -0
- package/src/assets/web-panel/assets/{index-BXb-Smmm.js → index-DH6OG-ci.js} +1 -1
- package/src/assets/web-panel/assets/{index-eTWPaeBI.js → index-DZER6Lj3.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cskz--fd.js → index-D_Bg0LdK.js} +1 -1
- package/src/assets/web-panel/assets/{index-D-ufbAJB.js → index-Dah8M4l2.js} +1 -1
- package/src/assets/web-panel/assets/{index-DHugFl3v.js → index-DjE_ew7U.js} +1 -1
- package/src/assets/web-panel/assets/{index-B9mSYovv.js → index-DtW6Zr_i.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ds8r3Fzb.js → index-DxdzSljS.js} +1 -1
- package/src/assets/web-panel/assets/{index-CPXdBnGi.js → index-QW0EXx14.js} +1 -1
- package/src/assets/web-panel/assets/{index-B-f6l4Vm.js → index-W9axN_Ce.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpvyOt5Z.js → index-_8vetPbU.js} +1 -1
- package/src/assets/web-panel/assets/index-btiojFYn.js +1 -0
- package/src/assets/web-panel/assets/{index-eYxUASSG.js → index-eJcFleIV.js} +1 -1
- package/src/assets/web-panel/assets/{index-be8SonCh.js → index-hzzTITR9.js} +1 -1
- package/src/assets/web-panel/assets/{index-BtSPhEyC.js → index-s4CFyn-n.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-B4chl7iR.js → initDefaultProps-JuW8mFj7.js} +1 -1
- package/src/assets/web-panel/assets/{motion-DruN9h96.js → motion-Cwb0HBve.js} +1 -1
- package/src/assets/web-panel/assets/{move-Cl0UtCgU.js → move-DHokzMgu.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-FX2ttw70.js → mtc-parser-DX31y6QS.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BDCneY46.js → omit-BCIUYDA6.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DycsEg8b.js → pickAttrs-DMCj4EoZ.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-Bc-dBuMv.js → placementArrow-Dy5K-u1s.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve--Wwaf8lu.js → responsiveObserve-DkGeZu54.js} +1 -1
- package/src/assets/web-panel/assets/{slide-vDmHQqHH.js → slide-Dc5dyJdg.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-9c52yv3G.js → statusUtils-DIUBjOaC.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-BT4BiO6_.js → styleChecker-DmyEOxm5.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-C7XxWPcP.js → useFlexGapSupport-FRhakk1e.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-BHoMqh4i.js → useFs-clXyV1WQ.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BOLxvsAG.js → usePersonalDataHub-UF6DG41z.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-CA7poeeP.js → vnode-CoCt95G7.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-B_sAn-co.js → zoom-yVWt-ENm.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/graph.js +215 -5
- package/src/commands/team-distributed.js +342 -2
- package/src/commands/team.js +169 -7
- package/src/data/changelog.json +13 -0
- package/src/generated/cc-agent-protocol.schema.json +6 -1
- package/src/lib/agent-team/task-lease.js +315 -0
- package/src/lib/agent-team/team-agent-stream.js +16 -0
- package/src/lib/agent-team/team-distributed-graph-bridge.js +257 -0
- package/src/lib/agent-team/team-distributed-graph-writer.js +523 -0
- package/src/lib/agent-team/team-distributed-queue.js +251 -0
- package/src/lib/agent-team/team-graph-runtime-adapter.js +1918 -0
- package/src/lib/agent-team/team-runner.js +225 -2
- package/src/lib/app-server/graph-runtime.js +754 -0
- package/src/lib/app-server/rollout-store.js +32 -0
- package/src/lib/app-server/server.js +140 -0
- package/src/lib/autonomous-agent.js +11 -0
- package/src/lib/cowork-graph-authority-adapter.js +455 -0
- package/src/lib/dynamic-workflow-facade.js +83 -16
- package/src/lib/graph-kernel/adapters.js +93 -20
- package/src/lib/graph-kernel/authority.js +324 -0
- package/src/lib/graph-kernel/compiler.js +1 -8
- package/src/lib/graph-kernel/cutover-authority-resolver.js +219 -0
- package/src/lib/graph-kernel/cutover-ledger.js +650 -0
- package/src/lib/graph-kernel/event-store.js +15 -1
- package/src/lib/graph-kernel/graph-runtime-surfaces.json +1427 -0
- package/src/lib/graph-kernel/index.js +4 -0
- package/src/lib/graph-kernel/migration-saga.js +309 -0
- package/src/lib/graph-kernel/runtime-surface-manifest.js +481 -0
- package/src/lib/graph-kernel/runtime.js +661 -24
- package/src/lib/graph-kernel/store-cutover-evidence.js +354 -0
- package/src/lib/graph-kernel/trace-reducer.js +6 -0
- package/src/lib/graph-kernel/trigger-adapter.js +60 -3
- package/src/lib/legacy-runtime-authority.js +160 -0
- package/src/lib/orchestrator.js +28 -0
- package/src/lib/scheduler-kernel/graph-authority-adapter.js +512 -0
- package/src/lib/scheduler-kernel/runtime.js +75 -2
- package/src/assets/web-panel/assets/PdhVaultBrowser-BiaZfQIM.js +0 -7
- package/src/assets/web-panel/assets/devWarning-DiSlgCC4.js +0 -1
- package/src/assets/web-panel/assets/index-9WIQEHvv.js +0 -1
- package/src/assets/web-panel/assets/index-B7mDobAl.js +0 -1
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { graphDigest } from "./compiler.js";
|
|
2
|
+
import {
|
|
3
|
+
GRAPH_AUTHORITY_MODES,
|
|
4
|
+
GraphRunAuthorityRegistry,
|
|
5
|
+
createGraphAuthorityBinding,
|
|
6
|
+
} from "./authority.js";
|
|
2
7
|
|
|
3
8
|
export const GRAPH_RUNTIME_SURFACES = Object.freeze([
|
|
4
9
|
"cli_team",
|
|
@@ -22,8 +27,16 @@ function contractError(code, message, details = {}) {
|
|
|
22
27
|
|
|
23
28
|
export function validateRuntimeClaims(claims) {
|
|
24
29
|
const errors = [];
|
|
25
|
-
|
|
26
|
-
|
|
30
|
+
const originSurface = claims?.originSurface || claims?.surface;
|
|
31
|
+
if (!GRAPH_RUNTIME_SURFACES.includes(originSurface)) {
|
|
32
|
+
errors.push("originSurface must identify a known execution plane");
|
|
33
|
+
}
|
|
34
|
+
if (
|
|
35
|
+
claims?.originSurface &&
|
|
36
|
+
claims?.surface &&
|
|
37
|
+
claims.originSurface !== claims.surface
|
|
38
|
+
) {
|
|
39
|
+
errors.push("surface compatibility alias must match originSurface");
|
|
27
40
|
}
|
|
28
41
|
if (!new Set(["real", "simulated", "planned"]).has(claims?.execution)) {
|
|
29
42
|
errors.push("execution must be real, simulated, or planned");
|
|
@@ -37,7 +50,21 @@ export function validateRuntimeClaims(claims) {
|
|
|
37
50
|
if (typeof claims?.terminalEvidence !== "boolean") {
|
|
38
51
|
errors.push("terminalEvidence must be explicit");
|
|
39
52
|
}
|
|
40
|
-
if (
|
|
53
|
+
if (
|
|
54
|
+
!Array.isArray(claims?.authorityModes) ||
|
|
55
|
+
claims.authorityModes.length === 0 ||
|
|
56
|
+
claims.authorityModes.some((mode) => !GRAPH_AUTHORITY_MODES.includes(mode))
|
|
57
|
+
) {
|
|
58
|
+
errors.push(
|
|
59
|
+
"authorityModes must declare supported per-run authority modes",
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
if (claims?.authoritative === true) {
|
|
63
|
+
errors.push(
|
|
64
|
+
"authoritative is not a surface claim; authority must be bound per GraphRun",
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
if (originSurface === "browser") {
|
|
41
68
|
if (
|
|
42
69
|
claims.persistence !== "non_durable" &&
|
|
43
70
|
claims.restartHydration !== true
|
|
@@ -49,13 +76,13 @@ export function validateRuntimeClaims(claims) {
|
|
|
49
76
|
}
|
|
50
77
|
}
|
|
51
78
|
if (
|
|
52
|
-
claims?.
|
|
79
|
+
claims?.authorityModes?.includes("canonical") &&
|
|
53
80
|
(claims.execution !== "real" ||
|
|
54
81
|
claims.persistence !== "durable" ||
|
|
55
82
|
claims.terminalEvidence !== true)
|
|
56
83
|
) {
|
|
57
84
|
errors.push(
|
|
58
|
-
"
|
|
85
|
+
"canonical authority requires real durable evidence-bound execution",
|
|
59
86
|
);
|
|
60
87
|
}
|
|
61
88
|
return Object.freeze({
|
|
@@ -65,9 +92,9 @@ export function validateRuntimeClaims(claims) {
|
|
|
65
92
|
}
|
|
66
93
|
|
|
67
94
|
export class GraphRuntimeAdapterRegistry {
|
|
68
|
-
constructor() {
|
|
95
|
+
constructor({ authorityRegistry = new GraphRunAuthorityRegistry() } = {}) {
|
|
69
96
|
this.adapters = new Map();
|
|
70
|
-
this.
|
|
97
|
+
this.authorityRegistry = authorityRegistry;
|
|
71
98
|
}
|
|
72
99
|
|
|
73
100
|
register(adapter) {
|
|
@@ -78,6 +105,8 @@ export class GraphRuntimeAdapterRegistry {
|
|
|
78
105
|
);
|
|
79
106
|
}
|
|
80
107
|
const claims = clone(adapter.runtimeClaims());
|
|
108
|
+
claims.originSurface ||= claims.surface;
|
|
109
|
+
claims.surface ||= claims.originSurface;
|
|
81
110
|
const validation = validateRuntimeClaims(claims);
|
|
82
111
|
if (!validation.valid) {
|
|
83
112
|
throw contractError(
|
|
@@ -86,23 +115,17 @@ export class GraphRuntimeAdapterRegistry {
|
|
|
86
115
|
{ errors: validation.errors },
|
|
87
116
|
);
|
|
88
117
|
}
|
|
89
|
-
if (claims.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
)
|
|
94
|
-
throw contractError(
|
|
95
|
-
"CC_GRAPH_MULTIPLE_AUTHORITATIVE_WRITERS",
|
|
96
|
-
"only one Graph Kernel adapter may write authoritative run state",
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
this.authoritativeSurface = claims.surface;
|
|
118
|
+
if (this.adapters.has(claims.originSurface)) {
|
|
119
|
+
throw contractError(
|
|
120
|
+
"CC_GRAPH_ADAPTER_ALREADY_REGISTERED",
|
|
121
|
+
`graph runtime adapter is already registered: ${claims.originSurface}`,
|
|
122
|
+
);
|
|
100
123
|
}
|
|
101
|
-
this.adapters.set(claims.
|
|
124
|
+
this.adapters.set(claims.originSurface, {
|
|
102
125
|
adapter,
|
|
103
126
|
claims: Object.freeze(claims),
|
|
104
127
|
});
|
|
105
|
-
return this.claims(claims.
|
|
128
|
+
return this.claims(claims.originSurface);
|
|
106
129
|
}
|
|
107
130
|
|
|
108
131
|
claims(surface) {
|
|
@@ -121,6 +144,56 @@ export class GraphRuntimeAdapterRegistry {
|
|
|
121
144
|
adapter(surface) {
|
|
122
145
|
return this.adapters.get(surface)?.adapter || null;
|
|
123
146
|
}
|
|
147
|
+
|
|
148
|
+
bindRunAuthority(originSurface, input, options = {}) {
|
|
149
|
+
const claims = this.claims(originSurface);
|
|
150
|
+
if (!claims) {
|
|
151
|
+
throw contractError(
|
|
152
|
+
"CC_GRAPH_ADAPTER_NOT_REGISTERED",
|
|
153
|
+
`graph runtime adapter is not registered: ${originSurface}`,
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
const authorityMode = String(input?.authorityMode || "");
|
|
157
|
+
if (!claims.authorityModes.includes(authorityMode)) {
|
|
158
|
+
throw contractError(
|
|
159
|
+
"CC_GRAPH_AUTHORITY_MODE_UNSUPPORTED",
|
|
160
|
+
`${originSurface} does not support ${authorityMode} authority`,
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
if (originSurface === "browser" && authorityMode === "canonical") {
|
|
164
|
+
throw contractError(
|
|
165
|
+
"CC_GRAPH_BROWSER_NON_DURABLE",
|
|
166
|
+
"browser runtime cannot acquire canonical authority while non-durable",
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
const authoritySource =
|
|
170
|
+
authorityMode === "canonical"
|
|
171
|
+
? "graph_kernel"
|
|
172
|
+
: authorityMode === "shadow"
|
|
173
|
+
? "graph_kernel_shadow"
|
|
174
|
+
: "legacy_runtime";
|
|
175
|
+
const binding = createGraphAuthorityBinding({
|
|
176
|
+
...input,
|
|
177
|
+
originSurface,
|
|
178
|
+
authorityMode,
|
|
179
|
+
authoritySource,
|
|
180
|
+
});
|
|
181
|
+
return this.authorityRegistry.bind(binding, options);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
runAuthority(logicalRunId) {
|
|
185
|
+
return this.authorityRegistry.get(logicalRunId);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
transitionSurface(originSurface, stage) {
|
|
189
|
+
if (!this.adapters.has(originSurface)) {
|
|
190
|
+
throw contractError(
|
|
191
|
+
"CC_GRAPH_ADAPTER_NOT_REGISTERED",
|
|
192
|
+
`graph runtime adapter is not registered: ${originSurface}`,
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
return this.authorityRegistry.transition(originSurface, stage);
|
|
196
|
+
}
|
|
124
197
|
}
|
|
125
198
|
|
|
126
199
|
function terminalProjection(value) {
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
export const GRAPH_AUTHORITY_SCHEMA = "chainlesschain.graph-authority/v1";
|
|
2
|
+
export const GRAPH_PROJECTION_VERSION = 1;
|
|
3
|
+
export const GRAPH_AUTHORITY_MODES = Object.freeze([
|
|
4
|
+
"legacy",
|
|
5
|
+
"shadow",
|
|
6
|
+
"canonical",
|
|
7
|
+
]);
|
|
8
|
+
export const GRAPH_CUTOVER_STAGES = Object.freeze([
|
|
9
|
+
"legacy",
|
|
10
|
+
"shadow",
|
|
11
|
+
"canary",
|
|
12
|
+
"canonical",
|
|
13
|
+
"legacy_read_only",
|
|
14
|
+
]);
|
|
15
|
+
|
|
16
|
+
const AUTHORITY_SOURCES = new Set([
|
|
17
|
+
"legacy_runtime",
|
|
18
|
+
"graph_kernel_shadow",
|
|
19
|
+
"graph_kernel",
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
function authorityError(code, message, details = {}) {
|
|
23
|
+
const error = new Error(message);
|
|
24
|
+
error.name = "GraphAuthorityError";
|
|
25
|
+
error.code = code;
|
|
26
|
+
Object.assign(error, details);
|
|
27
|
+
return error;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function clone(value) {
|
|
31
|
+
return value == null ? value : JSON.parse(JSON.stringify(value));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function identifier(value, label) {
|
|
35
|
+
const output = String(value || "").trim();
|
|
36
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._:/-]{0,159}$/u.test(output)) {
|
|
37
|
+
throw authorityError("CC_GRAPH_AUTHORITY_INVALID", `${label} is invalid`, {
|
|
38
|
+
field: label,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return output;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function eventHead(value) {
|
|
45
|
+
if (value == null) return null;
|
|
46
|
+
const output = String(value);
|
|
47
|
+
if (!/^sha256:[a-f0-9]{64}$/u.test(output)) {
|
|
48
|
+
throw authorityError(
|
|
49
|
+
"CC_GRAPH_AUTHORITY_INVALID",
|
|
50
|
+
"eventHead must be a sha256 digest or null",
|
|
51
|
+
{ field: "eventHead" },
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
return output;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function leaseExpiry(value) {
|
|
58
|
+
if (value == null) return null;
|
|
59
|
+
const output = String(value);
|
|
60
|
+
const milliseconds = Date.parse(output);
|
|
61
|
+
if (!Number.isFinite(milliseconds)) {
|
|
62
|
+
throw authorityError(
|
|
63
|
+
"CC_GRAPH_AUTHORITY_INVALID",
|
|
64
|
+
"writerLeaseExpiresAt must be an ISO timestamp",
|
|
65
|
+
{ field: "writerLeaseExpiresAt" },
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
return new Date(milliseconds).toISOString();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function createGraphAuthorityBinding(input = {}) {
|
|
72
|
+
const authorityMode = String(input.authorityMode || "").trim();
|
|
73
|
+
if (!GRAPH_AUTHORITY_MODES.includes(authorityMode)) {
|
|
74
|
+
throw authorityError(
|
|
75
|
+
"CC_GRAPH_AUTHORITY_INVALID",
|
|
76
|
+
"authorityMode must be legacy, shadow, or canonical",
|
|
77
|
+
{ field: "authorityMode" },
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
const authoritySource = String(input.authoritySource || "").trim();
|
|
81
|
+
if (!AUTHORITY_SOURCES.has(authoritySource)) {
|
|
82
|
+
throw authorityError(
|
|
83
|
+
"CC_GRAPH_AUTHORITY_INVALID",
|
|
84
|
+
"authoritySource is not recognized",
|
|
85
|
+
{ field: "authoritySource" },
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
if (
|
|
89
|
+
(authorityMode === "canonical" && authoritySource !== "graph_kernel") ||
|
|
90
|
+
(authorityMode === "shadow" && authoritySource !== "graph_kernel_shadow") ||
|
|
91
|
+
(authorityMode === "legacy" && authoritySource !== "legacy_runtime")
|
|
92
|
+
) {
|
|
93
|
+
throw authorityError(
|
|
94
|
+
"CC_GRAPH_AUTHORITY_SOURCE_MISMATCH",
|
|
95
|
+
"authoritySource does not match authorityMode",
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
const authorityGeneration = Number(input.authorityGeneration);
|
|
99
|
+
if (!Number.isSafeInteger(authorityGeneration) || authorityGeneration < 1) {
|
|
100
|
+
throw authorityError(
|
|
101
|
+
"CC_GRAPH_AUTHORITY_INVALID",
|
|
102
|
+
"authorityGeneration must be a positive safe integer",
|
|
103
|
+
{ field: "authorityGeneration" },
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
const projectionVersion = Number(
|
|
107
|
+
input.projectionVersion ?? GRAPH_PROJECTION_VERSION,
|
|
108
|
+
);
|
|
109
|
+
if (!Number.isSafeInteger(projectionVersion) || projectionVersion < 1) {
|
|
110
|
+
throw authorityError(
|
|
111
|
+
"CC_GRAPH_AUTHORITY_INVALID",
|
|
112
|
+
"projectionVersion must be a positive safe integer",
|
|
113
|
+
{ field: "projectionVersion" },
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
const binding = {
|
|
117
|
+
schema: GRAPH_AUTHORITY_SCHEMA,
|
|
118
|
+
logicalRunId: identifier(input.logicalRunId, "logicalRunId"),
|
|
119
|
+
originSurface: identifier(input.originSurface, "originSurface"),
|
|
120
|
+
authorityMode,
|
|
121
|
+
authoritySource,
|
|
122
|
+
authorityGeneration,
|
|
123
|
+
writerId: identifier(input.writerId, "writerId"),
|
|
124
|
+
writerLeaseId: identifier(input.writerLeaseId, "writerLeaseId"),
|
|
125
|
+
writerLeaseExpiresAt: leaseExpiry(input.writerLeaseExpiresAt),
|
|
126
|
+
eventHead: eventHead(input.eventHead),
|
|
127
|
+
projectionVersion,
|
|
128
|
+
};
|
|
129
|
+
if (authorityMode === "canonical" && !binding.writerLeaseExpiresAt) {
|
|
130
|
+
throw authorityError(
|
|
131
|
+
"CC_GRAPH_WRITER_LEASE_REQUIRED",
|
|
132
|
+
"canonical authority requires an expiring writer lease",
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
return Object.freeze(binding);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function assertGraphAuthorityWriter(
|
|
139
|
+
binding,
|
|
140
|
+
writer,
|
|
141
|
+
{
|
|
142
|
+
now = Date.now(),
|
|
143
|
+
expectedEventHead = undefined,
|
|
144
|
+
requireCanonical = true,
|
|
145
|
+
} = {},
|
|
146
|
+
) {
|
|
147
|
+
const current = createGraphAuthorityBinding(binding);
|
|
148
|
+
if (requireCanonical && current.authorityMode !== "canonical") {
|
|
149
|
+
throw authorityError(
|
|
150
|
+
"CC_GRAPH_NON_CANONICAL_WRITER",
|
|
151
|
+
"only canonical authority may mutate canonical Graph state",
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
if (
|
|
155
|
+
current.authoritySource !== writer?.authoritySource ||
|
|
156
|
+
current.authorityGeneration !== Number(writer?.authorityGeneration) ||
|
|
157
|
+
current.writerId !== writer?.writerId ||
|
|
158
|
+
current.writerLeaseId !== writer?.writerLeaseId
|
|
159
|
+
) {
|
|
160
|
+
throw authorityError(
|
|
161
|
+
"CC_GRAPH_STALE_WRITER",
|
|
162
|
+
"writer identity, generation, or lease does not own this GraphRun",
|
|
163
|
+
{
|
|
164
|
+
authorityGeneration: current.authorityGeneration,
|
|
165
|
+
writerId: current.writerId,
|
|
166
|
+
},
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
if (
|
|
170
|
+
current.writerLeaseExpiresAt &&
|
|
171
|
+
Date.parse(current.writerLeaseExpiresAt) <= Number(now)
|
|
172
|
+
) {
|
|
173
|
+
throw authorityError(
|
|
174
|
+
"CC_GRAPH_WRITER_LEASE_EXPIRED",
|
|
175
|
+
"GraphRun writer lease has expired",
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
if (
|
|
179
|
+
expectedEventHead !== undefined &&
|
|
180
|
+
current.eventHead !== expectedEventHead
|
|
181
|
+
) {
|
|
182
|
+
throw authorityError(
|
|
183
|
+
"CC_GRAPH_EVENT_HEAD_CONFLICT",
|
|
184
|
+
"GraphRun event head changed before mutation",
|
|
185
|
+
{ expectedEventHead, actualEventHead: current.eventHead },
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
return current;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const CUTOVER_TRANSITIONS = Object.freeze({
|
|
192
|
+
legacy: new Set(["shadow"]),
|
|
193
|
+
shadow: new Set(["legacy", "canary"]),
|
|
194
|
+
canary: new Set(["shadow", "canonical"]),
|
|
195
|
+
canonical: new Set(["canary", "legacy_read_only"]),
|
|
196
|
+
legacy_read_only: new Set(["canonical"]),
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
export function assertGraphCutoverTransition(from, to) {
|
|
200
|
+
if (
|
|
201
|
+
!GRAPH_CUTOVER_STAGES.includes(from) ||
|
|
202
|
+
!GRAPH_CUTOVER_STAGES.includes(to)
|
|
203
|
+
) {
|
|
204
|
+
throw authorityError(
|
|
205
|
+
"CC_GRAPH_CUTOVER_STAGE_INVALID",
|
|
206
|
+
"Graph cutover stage is invalid",
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
if (from === to) return to;
|
|
210
|
+
if (!CUTOVER_TRANSITIONS[from].has(to)) {
|
|
211
|
+
throw authorityError(
|
|
212
|
+
"CC_GRAPH_CUTOVER_TRANSITION_INVALID",
|
|
213
|
+
`Graph cutover cannot transition from ${from} to ${to}`,
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
return to;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export class GraphRunAuthorityRegistry {
|
|
220
|
+
constructor({ now = Date.now } = {}) {
|
|
221
|
+
this.now = now;
|
|
222
|
+
this.runs = new Map();
|
|
223
|
+
this.cutovers = new Map();
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
bind(input, { replace = false } = {}) {
|
|
227
|
+
const next = createGraphAuthorityBinding(input);
|
|
228
|
+
const previous = this.runs.get(next.logicalRunId);
|
|
229
|
+
if (previous) {
|
|
230
|
+
if (next.authorityGeneration < previous.authorityGeneration) {
|
|
231
|
+
throw authorityError(
|
|
232
|
+
"CC_GRAPH_STALE_GENERATION",
|
|
233
|
+
"authority generation cannot move backwards",
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
if (next.authorityGeneration === previous.authorityGeneration) {
|
|
237
|
+
const sameOwner =
|
|
238
|
+
next.authoritySource === previous.authoritySource &&
|
|
239
|
+
next.authorityMode === previous.authorityMode &&
|
|
240
|
+
next.writerId === previous.writerId &&
|
|
241
|
+
next.writerLeaseId === previous.writerLeaseId;
|
|
242
|
+
if (!sameOwner) {
|
|
243
|
+
throw authorityError(
|
|
244
|
+
"CC_GRAPH_MULTIPLE_AUTHORITATIVE_WRITERS",
|
|
245
|
+
"one logical GraphRun cannot have two writers in one generation",
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
} else {
|
|
249
|
+
if (!replace) {
|
|
250
|
+
throw authorityError(
|
|
251
|
+
"CC_GRAPH_AUTHORITY_REPLACEMENT_REQUIRED",
|
|
252
|
+
"a higher writer generation requires an explicit replacement",
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
if (next.eventHead !== previous.eventHead) {
|
|
256
|
+
throw authorityError(
|
|
257
|
+
"CC_GRAPH_EVENT_HEAD_CONFLICT",
|
|
258
|
+
"writer replacement must bind the exact persisted event head",
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
this.runs.set(next.logicalRunId, next);
|
|
264
|
+
return this.get(next.logicalRunId);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
assertWriter(logicalRunId, writer, options = {}) {
|
|
268
|
+
const current = this.runs.get(identifier(logicalRunId, "logicalRunId"));
|
|
269
|
+
if (!current) {
|
|
270
|
+
throw authorityError(
|
|
271
|
+
"CC_GRAPH_AUTHORITY_NOT_FOUND",
|
|
272
|
+
"GraphRun has no registered authority",
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
return assertGraphAuthorityWriter(current, writer, {
|
|
276
|
+
now: this.now(),
|
|
277
|
+
...options,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
advanceEventHead(
|
|
282
|
+
logicalRunId,
|
|
283
|
+
writer,
|
|
284
|
+
{ expectedEventHead, eventHead: next },
|
|
285
|
+
) {
|
|
286
|
+
const current = this.assertWriter(logicalRunId, writer, {
|
|
287
|
+
expectedEventHead,
|
|
288
|
+
});
|
|
289
|
+
const updated = createGraphAuthorityBinding({
|
|
290
|
+
...current,
|
|
291
|
+
eventHead: next,
|
|
292
|
+
});
|
|
293
|
+
this.runs.set(current.logicalRunId, updated);
|
|
294
|
+
return this.get(current.logicalRunId);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
transition(originSurface, to) {
|
|
298
|
+
const surface = identifier(originSurface, "originSurface");
|
|
299
|
+
const from = this.cutovers.get(surface) || "legacy";
|
|
300
|
+
this.cutovers.set(surface, assertGraphCutoverTransition(from, to));
|
|
301
|
+
return Object.freeze({ originSurface: surface, from, to });
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
cutoverStage(originSurface) {
|
|
305
|
+
return (
|
|
306
|
+
this.cutovers.get(identifier(originSurface, "originSurface")) || "legacy"
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
get(logicalRunId) {
|
|
311
|
+
const value = this.runs.get(identifier(logicalRunId, "logicalRunId"));
|
|
312
|
+
return value ? Object.freeze(clone(value)) : null;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
list() {
|
|
316
|
+
return Object.freeze(
|
|
317
|
+
[...this.runs.values()]
|
|
318
|
+
.map(clone)
|
|
319
|
+
.sort((left, right) =>
|
|
320
|
+
left.logicalRunId.localeCompare(right.logicalRunId),
|
|
321
|
+
),
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import
|
|
2
|
+
import graphProtocolSchema from "../../generated/cc-agent-protocol.schema.json" with { type: "json" };
|
|
3
3
|
import { validate } from "../json-schema-validate.js";
|
|
4
4
|
|
|
5
|
-
const graphProtocolSchema = JSON.parse(
|
|
6
|
-
readFileSync(
|
|
7
|
-
new URL("../../generated/cc-agent-protocol.schema.json", import.meta.url),
|
|
8
|
-
"utf8",
|
|
9
|
-
),
|
|
10
|
-
);
|
|
11
|
-
|
|
12
5
|
export const GRAPH_DEFINITION_VERSION = 1;
|
|
13
6
|
export const GRAPH_DEFINITION_MIN_VERSION = Math.max(
|
|
14
7
|
0,
|