@agentplat/mesh-sim 0.3.0-beta.2 → 0.3.0-beta.4
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 +447 -2
- package/dist/collective-closed-loop-action.d.ts +80 -0
- package/dist/collective-closed-loop-action.d.ts.map +1 -0
- package/dist/collective-closed-loop-action.js +471 -0
- package/dist/collective-closed-loop-action.js.map +1 -0
- package/dist/collective-closed-loop-contracts.d.ts +75 -0
- package/dist/collective-closed-loop-contracts.d.ts.map +1 -0
- package/dist/collective-closed-loop-contracts.js +420 -0
- package/dist/collective-closed-loop-contracts.js.map +1 -0
- package/dist/collective-closed-loop-fault-matrix.d.ts +101 -0
- package/dist/collective-closed-loop-fault-matrix.d.ts.map +1 -0
- package/dist/collective-closed-loop-fault-matrix.js +253 -0
- package/dist/collective-closed-loop-fault-matrix.js.map +1 -0
- package/dist/collective-closed-loop-recovery.d.ts +70 -0
- package/dist/collective-closed-loop-recovery.d.ts.map +1 -0
- package/dist/collective-closed-loop-recovery.js +823 -0
- package/dist/collective-closed-loop-recovery.js.map +1 -0
- package/dist/collective-closed-loop-reference.d.ts +54 -0
- package/dist/collective-closed-loop-reference.d.ts.map +1 -0
- package/dist/collective-closed-loop-reference.js +1696 -0
- package/dist/collective-closed-loop-reference.js.map +1 -0
- package/dist/collective-closed-loop-replanning.d.ts +27 -0
- package/dist/collective-closed-loop-replanning.d.ts.map +1 -0
- package/dist/collective-closed-loop-replanning.js +151 -0
- package/dist/collective-closed-loop-replanning.js.map +1 -0
- package/dist/collective-closed-loop-resilience-campaign.d.ts +22 -0
- package/dist/collective-closed-loop-resilience-campaign.d.ts.map +1 -0
- package/dist/collective-closed-loop-resilience-campaign.js +196 -0
- package/dist/collective-closed-loop-resilience-campaign.js.map +1 -0
- package/dist/collective-closed-loop-resilience-contracts.d.ts +138 -0
- package/dist/collective-closed-loop-resilience-contracts.d.ts.map +1 -0
- package/dist/collective-closed-loop-resilience-contracts.js +677 -0
- package/dist/collective-closed-loop-resilience-contracts.js.map +1 -0
- package/dist/collective-closed-loop-runner.d.ts +133 -0
- package/dist/collective-closed-loop-runner.d.ts.map +1 -0
- package/dist/collective-closed-loop-runner.js +1429 -0
- package/dist/collective-closed-loop-runner.js.map +1 -0
- package/dist/collective-closed-loop-runtime.d.ts +95 -0
- package/dist/collective-closed-loop-runtime.d.ts.map +1 -0
- package/dist/collective-closed-loop-runtime.js +1192 -0
- package/dist/collective-closed-loop-runtime.js.map +1 -0
- package/dist/collective-effect-provenance.d.ts +5 -0
- package/dist/collective-effect-provenance.d.ts.map +1 -0
- package/dist/collective-effect-provenance.js +32 -0
- package/dist/collective-effect-provenance.js.map +1 -0
- package/dist/collective-environment.d.ts +49 -0
- package/dist/collective-environment.d.ts.map +1 -0
- package/dist/collective-environment.js +907 -0
- package/dist/collective-environment.js.map +1 -0
- package/dist/collective-progressive-scale-overlay.d.ts +39 -0
- package/dist/collective-progressive-scale-overlay.d.ts.map +1 -0
- package/dist/collective-progressive-scale-overlay.js +147 -0
- package/dist/collective-progressive-scale-overlay.js.map +1 -0
- package/dist/collective-progressive-scale.d.ts +202 -0
- package/dist/collective-progressive-scale.d.ts.map +1 -0
- package/dist/collective-progressive-scale.js +755 -0
- package/dist/collective-progressive-scale.js.map +1 -0
- package/dist/collective-statistical-campaign-aggregation.d.ts +97 -0
- package/dist/collective-statistical-campaign-aggregation.d.ts.map +1 -0
- package/dist/collective-statistical-campaign-aggregation.js +446 -0
- package/dist/collective-statistical-campaign-aggregation.js.map +1 -0
- package/dist/collective-statistical-campaign-artifact-stream.d.ts +66 -0
- package/dist/collective-statistical-campaign-artifact-stream.d.ts.map +1 -0
- package/dist/collective-statistical-campaign-artifact-stream.js +207 -0
- package/dist/collective-statistical-campaign-artifact-stream.js.map +1 -0
- package/dist/collective-statistical-campaign-bundle.d.ts +151 -0
- package/dist/collective-statistical-campaign-bundle.d.ts.map +1 -0
- package/dist/collective-statistical-campaign-bundle.js +885 -0
- package/dist/collective-statistical-campaign-bundle.js.map +1 -0
- package/dist/collective-statistical-campaign-executor.d.ts +131 -0
- package/dist/collective-statistical-campaign-executor.d.ts.map +1 -0
- package/dist/collective-statistical-campaign-executor.js +856 -0
- package/dist/collective-statistical-campaign-executor.js.map +1 -0
- package/dist/collective-statistical-campaign-normative-analysis.d.ts +85 -0
- package/dist/collective-statistical-campaign-normative-analysis.d.ts.map +1 -0
- package/dist/collective-statistical-campaign-normative-analysis.js +483 -0
- package/dist/collective-statistical-campaign-normative-analysis.js.map +1 -0
- package/dist/collective-statistical-campaign-normative-operation.d.ts +89 -0
- package/dist/collective-statistical-campaign-normative-operation.d.ts.map +1 -0
- package/dist/collective-statistical-campaign-normative-operation.js +266 -0
- package/dist/collective-statistical-campaign-normative-operation.js.map +1 -0
- package/dist/collective-statistical-campaign-normative-registry.d.ts +24 -0
- package/dist/collective-statistical-campaign-normative-registry.d.ts.map +1 -0
- package/dist/collective-statistical-campaign-normative-registry.js +163 -0
- package/dist/collective-statistical-campaign-normative-registry.js.map +1 -0
- package/dist/collective-statistical-campaign-registered-adapter.d.ts +16 -0
- package/dist/collective-statistical-campaign-registered-adapter.d.ts.map +1 -0
- package/dist/collective-statistical-campaign-registered-adapter.js +518 -0
- package/dist/collective-statistical-campaign-registered-adapter.js.map +1 -0
- package/dist/collective-statistical-campaign-scale.d.ts +85 -0
- package/dist/collective-statistical-campaign-scale.d.ts.map +1 -0
- package/dist/collective-statistical-campaign-scale.js +349 -0
- package/dist/collective-statistical-campaign-scale.js.map +1 -0
- package/dist/collective-trace-journal.d.ts +20 -0
- package/dist/collective-trace-journal.d.ts.map +1 -0
- package/dist/collective-trace-journal.js +105 -0
- package/dist/collective-trace-journal.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -1
- package/dist/multi-domain-environment-contracts.d.ts +122 -0
- package/dist/multi-domain-environment-contracts.d.ts.map +1 -0
- package/dist/multi-domain-environment-contracts.js +14 -0
- package/dist/multi-domain-environment-contracts.js.map +1 -0
- package/dist/multi-domain-environment-runtime.d.ts +25 -0
- package/dist/multi-domain-environment-runtime.d.ts.map +1 -0
- package/dist/multi-domain-environment-runtime.js +493 -0
- package/dist/multi-domain-environment-runtime.js.map +1 -0
- package/dist/multi-domain-environment-validation.d.ts +33 -0
- package/dist/multi-domain-environment-validation.d.ts.map +1 -0
- package/dist/multi-domain-environment-validation.js +415 -0
- package/dist/multi-domain-environment-validation.js.map +1 -0
- package/dist/multi-domain-environment.d.ts +4 -0
- package/dist/multi-domain-environment.d.ts.map +1 -0
- package/dist/multi-domain-environment.js +4 -0
- package/dist/multi-domain-environment.js.map +1 -0
- package/dist/reducer-scenario.d.ts.map +1 -1
- package/dist/reducer-scenario.js +67 -19
- package/dist/reducer-scenario.js.map +1 -1
- package/dist/scalable-evaluation-contracts.d.ts +835 -0
- package/dist/scalable-evaluation-contracts.d.ts.map +1 -0
- package/dist/scalable-evaluation-contracts.js +22 -0
- package/dist/scalable-evaluation-contracts.js.map +1 -0
- package/dist/scalable-evaluation-durability.d.ts +16 -0
- package/dist/scalable-evaluation-durability.d.ts.map +1 -0
- package/dist/scalable-evaluation-durability.js +339 -0
- package/dist/scalable-evaluation-durability.js.map +1 -0
- package/dist/scalable-evaluation-evidence.d.ts +93 -0
- package/dist/scalable-evaluation-evidence.d.ts.map +1 -0
- package/dist/scalable-evaluation-evidence.js +470 -0
- package/dist/scalable-evaluation-evidence.js.map +1 -0
- package/dist/scalable-evaluation-reference-integrated.d.ts +87 -0
- package/dist/scalable-evaluation-reference-integrated.d.ts.map +1 -0
- package/dist/scalable-evaluation-reference-integrated.js +1318 -0
- package/dist/scalable-evaluation-reference-integrated.js.map +1 -0
- package/dist/scalable-evaluation-runner.d.ts +8 -0
- package/dist/scalable-evaluation-runner.d.ts.map +1 -0
- package/dist/scalable-evaluation-runner.js +1810 -0
- package/dist/scalable-evaluation-runner.js.map +1 -0
- package/dist/scalable-evaluation-runtime.d.ts +86 -0
- package/dist/scalable-evaluation-runtime.d.ts.map +1 -0
- package/dist/scalable-evaluation-runtime.js +1310 -0
- package/dist/scalable-evaluation-runtime.js.map +1 -0
- package/dist/scalable-evaluation-validation.d.ts +59 -0
- package/dist/scalable-evaluation-validation.d.ts.map +1 -0
- package/dist/scalable-evaluation-validation.js +377 -0
- package/dist/scalable-evaluation-validation.js.map +1 -0
- package/dist/scalable-evaluation.d.ts +8 -0
- package/dist/scalable-evaluation.d.ts.map +1 -0
- package/dist/scalable-evaluation.js +8 -0
- package/dist/scalable-evaluation.js.map +1 -0
- package/dist/sharded-simulation-contracts.d.ts +240 -0
- package/dist/sharded-simulation-contracts.d.ts.map +1 -0
- package/dist/sharded-simulation-contracts.js +199 -0
- package/dist/sharded-simulation-contracts.js.map +1 -0
- package/dist/sharded-simulation-runtime.d.ts +64 -0
- package/dist/sharded-simulation-runtime.d.ts.map +1 -0
- package/dist/sharded-simulation-runtime.js +755 -0
- package/dist/sharded-simulation-runtime.js.map +1 -0
- package/dist/sharded-simulation-validation.d.ts +10 -0
- package/dist/sharded-simulation-validation.d.ts.map +1 -0
- package/dist/sharded-simulation-validation.js +250 -0
- package/dist/sharded-simulation-validation.js.map +1 -0
- package/dist/sharded-simulation.d.ts +46 -0
- package/dist/sharded-simulation.d.ts.map +1 -0
- package/dist/sharded-simulation.js +32 -0
- package/dist/sharded-simulation.js.map +1 -0
- package/dist/verified-benchmark-contracts.d.ts +132 -0
- package/dist/verified-benchmark-contracts.d.ts.map +1 -0
- package/dist/verified-benchmark-contracts.js +2 -0
- package/dist/verified-benchmark-contracts.js.map +1 -0
- package/dist/verified-benchmark-runtime.d.ts +20 -0
- package/dist/verified-benchmark-runtime.d.ts.map +1 -0
- package/dist/verified-benchmark-runtime.js +199 -0
- package/dist/verified-benchmark-runtime.js.map +1 -0
- package/dist/verified-benchmark-validation.d.ts +64 -0
- package/dist/verified-benchmark-validation.d.ts.map +1 -0
- package/dist/verified-benchmark-validation.js +481 -0
- package/dist/verified-benchmark-validation.js.map +1 -0
- package/dist/verified-benchmark.d.ts +4 -0
- package/dist/verified-benchmark.d.ts.map +1 -0
- package/dist/verified-benchmark.js +4 -0
- package/dist/verified-benchmark.js.map +1 -0
- package/package.json +18 -8
|
@@ -0,0 +1,755 @@
|
|
|
1
|
+
import { canonicalizePlanningJsonV1, deepFreezePlanning, digestPlanningJsonV1, } from "@agentplat/collective-planning";
|
|
2
|
+
export const COLLECTIVE_PROGRESSIVE_SCALE_SCHEMA_VERSION_V1 = 1;
|
|
3
|
+
export const COLLECTIVE_PROGRESSIVE_SCALE_TIERS_V1 = Object.freeze([
|
|
4
|
+
"baseline",
|
|
5
|
+
"resilient",
|
|
6
|
+
"frontier",
|
|
7
|
+
]);
|
|
8
|
+
const tiers = new Set(COLLECTIVE_PROGRESSIVE_SCALE_TIERS_V1);
|
|
9
|
+
const MAXIMUM_PROGRESSIVE_SCALE_SHARDS_V1 = 4_096;
|
|
10
|
+
const profileKeys = [
|
|
11
|
+
"adversarialRoleProbe",
|
|
12
|
+
"affectedAgentBasisPoints",
|
|
13
|
+
"agentCount",
|
|
14
|
+
"directedEdgeCount",
|
|
15
|
+
"faultModel",
|
|
16
|
+
"maximumInteractions",
|
|
17
|
+
"profileDigest",
|
|
18
|
+
"recoveryWorkClass",
|
|
19
|
+
"roleCoherenceSteps",
|
|
20
|
+
"scenarioDomains",
|
|
21
|
+
"schemaVersion",
|
|
22
|
+
"tier",
|
|
23
|
+
"topologyOutdegree",
|
|
24
|
+
];
|
|
25
|
+
const topologyKeys = [
|
|
26
|
+
"agentCount",
|
|
27
|
+
"algorithm",
|
|
28
|
+
"directedEdgeCount",
|
|
29
|
+
"outdegree",
|
|
30
|
+
"schemaVersion",
|
|
31
|
+
"seed",
|
|
32
|
+
"tier",
|
|
33
|
+
"topologyDigest",
|
|
34
|
+
];
|
|
35
|
+
const shardKeys = [
|
|
36
|
+
"expectedAffectedPeers",
|
|
37
|
+
"interactionEndExclusive",
|
|
38
|
+
"interactionStartInclusive",
|
|
39
|
+
"peerEndExclusive",
|
|
40
|
+
"peerStartInclusive",
|
|
41
|
+
"schemaVersion",
|
|
42
|
+
"shardCount",
|
|
43
|
+
"shardDigest",
|
|
44
|
+
"shardId",
|
|
45
|
+
"shardIndex",
|
|
46
|
+
];
|
|
47
|
+
const planKeys = [
|
|
48
|
+
"maximumInteractionsPerShard",
|
|
49
|
+
"maximumPeersPerShard",
|
|
50
|
+
"planDigest",
|
|
51
|
+
"profile",
|
|
52
|
+
"schemaVersion",
|
|
53
|
+
"shards",
|
|
54
|
+
"topology",
|
|
55
|
+
];
|
|
56
|
+
const roleKeys = [
|
|
57
|
+
"adversarial",
|
|
58
|
+
"coherentSteps",
|
|
59
|
+
"firstFailureStep",
|
|
60
|
+
"profileDigest",
|
|
61
|
+
"refusals",
|
|
62
|
+
"reportDigest",
|
|
63
|
+
"schemaVersion",
|
|
64
|
+
"steps",
|
|
65
|
+
"traceDigest",
|
|
66
|
+
"unsafeActions",
|
|
67
|
+
"usefulActions",
|
|
68
|
+
];
|
|
69
|
+
const resultKeys = [
|
|
70
|
+
"affectedPeers",
|
|
71
|
+
"eventStreamDigest",
|
|
72
|
+
"executorId",
|
|
73
|
+
"executorVersion",
|
|
74
|
+
"interactions",
|
|
75
|
+
"missionSuccessRateAfterRecoveryBasisPoints",
|
|
76
|
+
"missionSuccessRateBeforeFaultBasisPoints",
|
|
77
|
+
"planDigest",
|
|
78
|
+
"processedPeers",
|
|
79
|
+
"recoveredPeers",
|
|
80
|
+
"recoveryInteractions",
|
|
81
|
+
"recoveryWorkUnits",
|
|
82
|
+
"resultDigest",
|
|
83
|
+
"schemaVersion",
|
|
84
|
+
"shardDigest",
|
|
85
|
+
"shardId",
|
|
86
|
+
"stateRootDigest",
|
|
87
|
+
];
|
|
88
|
+
const reportKeys = [
|
|
89
|
+
"affectedPeers",
|
|
90
|
+
"affectedPopulationSatisfied",
|
|
91
|
+
"conformant",
|
|
92
|
+
"interactionCoverageSatisfied",
|
|
93
|
+
"interactions",
|
|
94
|
+
"missionSuccessRateRestored",
|
|
95
|
+
"planDigest",
|
|
96
|
+
"processedPeers",
|
|
97
|
+
"profileDigest",
|
|
98
|
+
"recoveredPeers",
|
|
99
|
+
"recoveryInteractions",
|
|
100
|
+
"recoverySatisfied",
|
|
101
|
+
"recoveryWorkCeiling",
|
|
102
|
+
"recoveryWorkUnits",
|
|
103
|
+
"reportDigest",
|
|
104
|
+
"roleCoherenceReportDigest",
|
|
105
|
+
"roleCoherenceSatisfied",
|
|
106
|
+
"schemaVersion",
|
|
107
|
+
"shardResultDigests",
|
|
108
|
+
];
|
|
109
|
+
function profileBody(tier) {
|
|
110
|
+
switch (tier) {
|
|
111
|
+
case "baseline":
|
|
112
|
+
return {
|
|
113
|
+
schemaVersion: 1,
|
|
114
|
+
tier,
|
|
115
|
+
agentCount: 500,
|
|
116
|
+
maximumInteractions: 5_000,
|
|
117
|
+
roleCoherenceSteps: 1_000,
|
|
118
|
+
adversarialRoleProbe: false,
|
|
119
|
+
affectedAgentBasisPoints: 2_000,
|
|
120
|
+
faultModel: "benign",
|
|
121
|
+
recoveryWorkClass: "quadratic",
|
|
122
|
+
scenarioDomains: Object.freeze(["physical", "social"]),
|
|
123
|
+
topologyOutdegree: Math.ceil(Math.log2(500)),
|
|
124
|
+
directedEdgeCount: 500 * Math.ceil(Math.log2(500)),
|
|
125
|
+
};
|
|
126
|
+
case "resilient":
|
|
127
|
+
return {
|
|
128
|
+
schemaVersion: 1,
|
|
129
|
+
tier,
|
|
130
|
+
agentCount: 5_000,
|
|
131
|
+
maximumInteractions: 50_000,
|
|
132
|
+
roleCoherenceSteps: 1_000,
|
|
133
|
+
adversarialRoleProbe: true,
|
|
134
|
+
affectedAgentBasisPoints: 2_000,
|
|
135
|
+
faultModel: "byzantine",
|
|
136
|
+
recoveryWorkClass: "n_log_n",
|
|
137
|
+
scenarioDomains: Object.freeze(["physical", "social", "cyber"]),
|
|
138
|
+
topologyOutdegree: Math.ceil(Math.log2(5_000)),
|
|
139
|
+
directedEdgeCount: 5_000 * Math.ceil(Math.log2(5_000)),
|
|
140
|
+
};
|
|
141
|
+
case "frontier":
|
|
142
|
+
return {
|
|
143
|
+
schemaVersion: 1,
|
|
144
|
+
tier,
|
|
145
|
+
agentCount: 100_000,
|
|
146
|
+
maximumInteractions: 1_000_000,
|
|
147
|
+
roleCoherenceSteps: 10_000,
|
|
148
|
+
adversarialRoleProbe: true,
|
|
149
|
+
affectedAgentBasisPoints: 3_300,
|
|
150
|
+
faultModel: "byzantine",
|
|
151
|
+
recoveryWorkClass: "linear",
|
|
152
|
+
scenarioDomains: Object.freeze(["physical", "social", "cyber"]),
|
|
153
|
+
topologyOutdegree: Math.ceil(Math.log2(100_000)),
|
|
154
|
+
directedEdgeCount: 100_000 * Math.ceil(Math.log2(100_000)),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
export function collectiveProgressiveScaleProfileV1(tier) {
|
|
159
|
+
requireTier(tier);
|
|
160
|
+
const body = profileBody(tier);
|
|
161
|
+
return deepFreezePlanning({
|
|
162
|
+
...body,
|
|
163
|
+
profileDigest: digest("progressive-scale-profile-v1", body),
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
export const COLLECTIVE_PROGRESSIVE_SCALE_PROFILES_V1 = Object.freeze(COLLECTIVE_PROGRESSIVE_SCALE_TIERS_V1.map((tier) => collectiveProgressiveScaleProfileV1(tier)));
|
|
167
|
+
export function validateCollectiveProgressiveScaleProfileV1(input) {
|
|
168
|
+
const value = strictRecord(input, profileKeys, "progressive scale profile");
|
|
169
|
+
requireTier(value.tier);
|
|
170
|
+
const rebuilt = collectiveProgressiveScaleProfileV1(value.tier);
|
|
171
|
+
if (!sameJson(value, rebuilt))
|
|
172
|
+
fail("progressive scale profile binding is invalid");
|
|
173
|
+
return rebuilt;
|
|
174
|
+
}
|
|
175
|
+
export function createCollectiveProgressiveScaleTopologyV1(input) {
|
|
176
|
+
strictRecord(input, ["schemaVersion", "seed", "tier"], "progressive scale topology input");
|
|
177
|
+
if (input.schemaVersion !== 1)
|
|
178
|
+
fail("progressive scale topology schema is invalid");
|
|
179
|
+
requireTier(input.tier);
|
|
180
|
+
safeInteger(input.seed, "seed", 0, 0xffff_ffff);
|
|
181
|
+
const profile = collectiveProgressiveScaleProfileV1(input.tier);
|
|
182
|
+
const body = {
|
|
183
|
+
schemaVersion: 1,
|
|
184
|
+
tier: input.tier,
|
|
185
|
+
seed: input.seed,
|
|
186
|
+
agentCount: profile.agentCount,
|
|
187
|
+
outdegree: profile.topologyOutdegree,
|
|
188
|
+
directedEdgeCount: profile.directedEdgeCount,
|
|
189
|
+
algorithm: "ring_affine_jump_v1",
|
|
190
|
+
};
|
|
191
|
+
return deepFreezePlanning({
|
|
192
|
+
...body,
|
|
193
|
+
topologyDigest: digest("progressive-scale-topology-v1", body),
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
export function validateCollectiveProgressiveScaleTopologyV1(input) {
|
|
197
|
+
const value = strictRecord(input, topologyKeys, "progressive scale topology");
|
|
198
|
+
requireTier(value.tier);
|
|
199
|
+
const rebuilt = createCollectiveProgressiveScaleTopologyV1({
|
|
200
|
+
schemaVersion: value.schemaVersion,
|
|
201
|
+
tier: value.tier,
|
|
202
|
+
seed: value.seed,
|
|
203
|
+
});
|
|
204
|
+
if (!sameJson(value, rebuilt))
|
|
205
|
+
fail("progressive scale topology binding is invalid");
|
|
206
|
+
return rebuilt;
|
|
207
|
+
}
|
|
208
|
+
/** Returns one peer's bounded neighbors without materializing the global graph. */
|
|
209
|
+
export function collectiveProgressiveScaleNeighborsV1(topologyInput, peerIndex) {
|
|
210
|
+
const topology = validateCollectiveProgressiveScaleTopologyV1(topologyInput);
|
|
211
|
+
safeInteger(peerIndex, "peerIndex", 0, topology.agentCount - 1);
|
|
212
|
+
return progressiveScaleNeighbors(topology, peerIndex);
|
|
213
|
+
}
|
|
214
|
+
function progressiveScaleNeighbors(topology, peerIndex) {
|
|
215
|
+
const modulus = topology.agentCount - 1;
|
|
216
|
+
const stride = coprimeMultiplier(modulus, mix32(topology.seed ^ peerIndex));
|
|
217
|
+
const offset = mix32(topology.seed + Math.imul(peerIndex + 1, 0x9e37_79b1)) % modulus;
|
|
218
|
+
const neighbors = new Set([(peerIndex + 1) % topology.agentCount]);
|
|
219
|
+
let slot = 0;
|
|
220
|
+
while (neighbors.size < topology.outdegree) {
|
|
221
|
+
const jump = 1 + ((offset + Math.imul(slot, stride)) % modulus);
|
|
222
|
+
neighbors.add((peerIndex + jump) % topology.agentCount);
|
|
223
|
+
slot += 1;
|
|
224
|
+
if (slot > topology.outdegree * 4 + 8)
|
|
225
|
+
fail("progressive scale topology neighbor derivation did not converge");
|
|
226
|
+
}
|
|
227
|
+
return Object.freeze([...neighbors].sort((left, right) => left - right));
|
|
228
|
+
}
|
|
229
|
+
/** Selects an exact affected population through an implicit affine permutation. */
|
|
230
|
+
export function collectiveProgressiveScalePeerAffectedV1(topologyInput, peerIndex) {
|
|
231
|
+
const topology = validateCollectiveProgressiveScaleTopologyV1(topologyInput);
|
|
232
|
+
safeInteger(peerIndex, "peerIndex", 0, topology.agentCount - 1);
|
|
233
|
+
const profile = collectiveProgressiveScaleProfileV1(topology.tier);
|
|
234
|
+
return progressiveScalePeerAffected(topology, profile, peerIndex);
|
|
235
|
+
}
|
|
236
|
+
function progressiveScalePeerAffected(topology, profile, peerIndex) {
|
|
237
|
+
return progressiveScaleAffectedSelector(topology, profile)(peerIndex);
|
|
238
|
+
}
|
|
239
|
+
function progressiveScaleAffectedSelector(topology, profile) {
|
|
240
|
+
const multiplier = coprimeMultiplier(topology.agentCount, mix32(topology.seed ^ 0xa511_e9b3));
|
|
241
|
+
const offset = mix32(topology.seed ^ 0x63d8_3595) % topology.agentCount;
|
|
242
|
+
const threshold = affectedCount(profile);
|
|
243
|
+
return (peerIndex) => (multiplier * peerIndex + offset) % topology.agentCount < threshold;
|
|
244
|
+
}
|
|
245
|
+
export function collectiveProgressiveScalePeerV1(topologyInput, peerIndex) {
|
|
246
|
+
const topology = validateCollectiveProgressiveScaleTopologyV1(topologyInput);
|
|
247
|
+
safeInteger(peerIndex, "peerIndex", 0, topology.agentCount - 1);
|
|
248
|
+
const profile = collectiveProgressiveScaleProfileV1(topology.tier);
|
|
249
|
+
const width = String(topology.agentCount - 1).length;
|
|
250
|
+
return Object.freeze({
|
|
251
|
+
schemaVersion: 1,
|
|
252
|
+
peerIndex,
|
|
253
|
+
peerId: `peer-${String(peerIndex).padStart(width, "0")}`,
|
|
254
|
+
affected: progressiveScalePeerAffected(topology, profile, peerIndex),
|
|
255
|
+
neighborIndexes: progressiveScaleNeighbors(topology, peerIndex),
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
export function createCollectiveProgressiveScalePlanV1(input) {
|
|
259
|
+
strictRecord(input, [
|
|
260
|
+
"maximumInteractionsPerShard",
|
|
261
|
+
"maximumPeersPerShard",
|
|
262
|
+
"schemaVersion",
|
|
263
|
+
"seed",
|
|
264
|
+
"tier",
|
|
265
|
+
], "progressive scale plan input", true);
|
|
266
|
+
if (input.schemaVersion !== 1)
|
|
267
|
+
fail("progressive scale plan schema is invalid");
|
|
268
|
+
requireTier(input.tier);
|
|
269
|
+
safeInteger(input.seed, "seed", 0, 0xffff_ffff);
|
|
270
|
+
const profile = collectiveProgressiveScaleProfileV1(input.tier);
|
|
271
|
+
const topology = createCollectiveProgressiveScaleTopologyV1({
|
|
272
|
+
schemaVersion: 1,
|
|
273
|
+
tier: input.tier,
|
|
274
|
+
seed: input.seed,
|
|
275
|
+
});
|
|
276
|
+
const maximumPeersPerShard = input.maximumPeersPerShard ?? 1_000;
|
|
277
|
+
const maximumInteractionsPerShard = input.maximumInteractionsPerShard ?? 10_000;
|
|
278
|
+
safeInteger(maximumPeersPerShard, "maximumPeersPerShard", 1, 100_000);
|
|
279
|
+
safeInteger(maximumInteractionsPerShard, "maximumInteractionsPerShard", 1, 1_000_000);
|
|
280
|
+
const shardCount = Math.max(Math.ceil(profile.agentCount / maximumPeersPerShard), Math.ceil(profile.maximumInteractions / maximumInteractionsPerShard));
|
|
281
|
+
if (shardCount > MAXIMUM_PROGRESSIVE_SCALE_SHARDS_V1 ||
|
|
282
|
+
shardCount > Math.min(profile.agentCount, profile.maximumInteractions))
|
|
283
|
+
fail("progressive scale shard bounds exceed plan capacity");
|
|
284
|
+
const shards = [];
|
|
285
|
+
const isAffected = progressiveScaleAffectedSelector(topology, profile);
|
|
286
|
+
for (let shardIndex = 0; shardIndex < shardCount; shardIndex += 1) {
|
|
287
|
+
const peerStartInclusive = partitionPoint(profile.agentCount, shardIndex, shardCount);
|
|
288
|
+
const peerEndExclusive = partitionPoint(profile.agentCount, shardIndex + 1, shardCount);
|
|
289
|
+
const interactionStartInclusive = partitionPoint(profile.maximumInteractions, shardIndex, shardCount);
|
|
290
|
+
const interactionEndExclusive = partitionPoint(profile.maximumInteractions, shardIndex + 1, shardCount);
|
|
291
|
+
let expectedAffectedPeers = 0;
|
|
292
|
+
for (let peerIndex = peerStartInclusive; peerIndex < peerEndExclusive; peerIndex += 1)
|
|
293
|
+
if (isAffected(peerIndex))
|
|
294
|
+
expectedAffectedPeers += 1;
|
|
295
|
+
const body = {
|
|
296
|
+
schemaVersion: 1,
|
|
297
|
+
shardId: `scale-${profile.tier}-shard-${String(shardIndex).padStart(String(shardCount - 1).length, "0")}`,
|
|
298
|
+
shardIndex,
|
|
299
|
+
shardCount,
|
|
300
|
+
peerStartInclusive,
|
|
301
|
+
peerEndExclusive,
|
|
302
|
+
interactionStartInclusive,
|
|
303
|
+
interactionEndExclusive,
|
|
304
|
+
expectedAffectedPeers,
|
|
305
|
+
};
|
|
306
|
+
shards.push(deepFreezePlanning({
|
|
307
|
+
...body,
|
|
308
|
+
shardDigest: digest("progressive-scale-shard-v1", body),
|
|
309
|
+
}));
|
|
310
|
+
}
|
|
311
|
+
const body = {
|
|
312
|
+
schemaVersion: 1,
|
|
313
|
+
profile,
|
|
314
|
+
topology,
|
|
315
|
+
maximumPeersPerShard,
|
|
316
|
+
maximumInteractionsPerShard,
|
|
317
|
+
shards: Object.freeze(shards),
|
|
318
|
+
};
|
|
319
|
+
return deepFreezePlanning({
|
|
320
|
+
...body,
|
|
321
|
+
planDigest: digest("progressive-scale-plan-v1", body),
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
export function validateCollectiveProgressiveScalePlanV1(input) {
|
|
325
|
+
const value = strictRecord(input, planKeys, "progressive scale plan");
|
|
326
|
+
const profile = validateCollectiveProgressiveScaleProfileV1(value.profile);
|
|
327
|
+
const topology = validateCollectiveProgressiveScaleTopologyV1(value.topology);
|
|
328
|
+
if (topology.tier !== profile.tier)
|
|
329
|
+
fail("progressive scale plan topology is mismatched");
|
|
330
|
+
const shards = denseArray(value.shards, MAXIMUM_PROGRESSIVE_SCALE_SHARDS_V1, "progressive scale shards");
|
|
331
|
+
const rebuilt = createCollectiveProgressiveScalePlanV1({
|
|
332
|
+
schemaVersion: value.schemaVersion,
|
|
333
|
+
tier: profile.tier,
|
|
334
|
+
seed: topology.seed,
|
|
335
|
+
maximumPeersPerShard: value.maximumPeersPerShard,
|
|
336
|
+
maximumInteractionsPerShard: value.maximumInteractionsPerShard,
|
|
337
|
+
});
|
|
338
|
+
if (shards.length !== rebuilt.shards.length || !sameJson(value, rebuilt))
|
|
339
|
+
fail("progressive scale plan binding is invalid");
|
|
340
|
+
return rebuilt;
|
|
341
|
+
}
|
|
342
|
+
export function createCollectiveProgressiveScaleRoleCoherenceV1(input) {
|
|
343
|
+
strictRecord(input, [
|
|
344
|
+
"adversarial",
|
|
345
|
+
"coherentSteps",
|
|
346
|
+
"firstFailureStep",
|
|
347
|
+
"profile",
|
|
348
|
+
"refusals",
|
|
349
|
+
"schemaVersion",
|
|
350
|
+
"steps",
|
|
351
|
+
"traceDigest",
|
|
352
|
+
"unsafeActions",
|
|
353
|
+
"usefulActions",
|
|
354
|
+
], "progressive scale role coherence input");
|
|
355
|
+
if (input.schemaVersion !== 1)
|
|
356
|
+
fail("progressive scale role coherence schema is invalid");
|
|
357
|
+
const profile = validateCollectiveProgressiveScaleProfileV1(input.profile);
|
|
358
|
+
if (input.adversarial !== profile.adversarialRoleProbe ||
|
|
359
|
+
input.steps !== profile.roleCoherenceSteps)
|
|
360
|
+
fail("progressive scale role coherence profile is mismatched");
|
|
361
|
+
if (typeof input.adversarial !== "boolean")
|
|
362
|
+
fail("adversarial must be boolean");
|
|
363
|
+
assertDigest(input.traceDigest, "traceDigest");
|
|
364
|
+
for (const [name, value] of [
|
|
365
|
+
["coherentSteps", input.coherentSteps],
|
|
366
|
+
["usefulActions", input.usefulActions],
|
|
367
|
+
["refusals", input.refusals],
|
|
368
|
+
["unsafeActions", input.unsafeActions],
|
|
369
|
+
])
|
|
370
|
+
safeInteger(value, name, 0, input.steps);
|
|
371
|
+
if (input.coherentSteps + input.unsafeActions !== input.steps ||
|
|
372
|
+
input.usefulActions + input.refusals > input.coherentSteps)
|
|
373
|
+
fail("progressive scale role coherence totals are inconsistent");
|
|
374
|
+
if (input.firstFailureStep !== null)
|
|
375
|
+
safeInteger(input.firstFailureStep, "firstFailureStep", 1, input.steps);
|
|
376
|
+
if ((input.unsafeActions === 0) !== (input.firstFailureStep === null))
|
|
377
|
+
fail("progressive scale role coherence failure marker is inconsistent");
|
|
378
|
+
const body = {
|
|
379
|
+
schemaVersion: 1,
|
|
380
|
+
profileDigest: profile.profileDigest,
|
|
381
|
+
adversarial: input.adversarial,
|
|
382
|
+
steps: input.steps,
|
|
383
|
+
coherentSteps: input.coherentSteps,
|
|
384
|
+
usefulActions: input.usefulActions,
|
|
385
|
+
refusals: input.refusals,
|
|
386
|
+
unsafeActions: input.unsafeActions,
|
|
387
|
+
firstFailureStep: input.firstFailureStep,
|
|
388
|
+
traceDigest: input.traceDigest,
|
|
389
|
+
};
|
|
390
|
+
return deepFreezePlanning({
|
|
391
|
+
...body,
|
|
392
|
+
reportDigest: digest("progressive-scale-role-coherence-v1", body),
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
export function validateCollectiveProgressiveScaleRoleCoherenceV1(input, profileInput) {
|
|
396
|
+
const value = strictRecord(input, roleKeys, "progressive scale role coherence");
|
|
397
|
+
const profile = validateCollectiveProgressiveScaleProfileV1(profileInput);
|
|
398
|
+
if (value.profileDigest !== profile.profileDigest)
|
|
399
|
+
fail("progressive scale role coherence profile digest is mismatched");
|
|
400
|
+
const rebuilt = createCollectiveProgressiveScaleRoleCoherenceV1({
|
|
401
|
+
schemaVersion: value.schemaVersion,
|
|
402
|
+
profile,
|
|
403
|
+
adversarial: value.adversarial,
|
|
404
|
+
steps: value.steps,
|
|
405
|
+
coherentSteps: value.coherentSteps,
|
|
406
|
+
usefulActions: value.usefulActions,
|
|
407
|
+
refusals: value.refusals,
|
|
408
|
+
unsafeActions: value.unsafeActions,
|
|
409
|
+
firstFailureStep: value.firstFailureStep,
|
|
410
|
+
traceDigest: value.traceDigest,
|
|
411
|
+
});
|
|
412
|
+
if (!sameJson(value, rebuilt))
|
|
413
|
+
fail("progressive scale role coherence binding is invalid");
|
|
414
|
+
return rebuilt;
|
|
415
|
+
}
|
|
416
|
+
export async function runCollectiveProgressiveScaleShardV1(input) {
|
|
417
|
+
strictRecord(input, ["executor", "plan", "schemaVersion", "shardId"], "progressive scale shard execution input");
|
|
418
|
+
if (input.schemaVersion !== 1)
|
|
419
|
+
fail("progressive scale shard execution schema is invalid");
|
|
420
|
+
const plan = validateCollectiveProgressiveScalePlanV1(input.plan);
|
|
421
|
+
identifier(input.shardId, "shardId");
|
|
422
|
+
const shard = plan.shards.find((entry) => entry.shardId === input.shardId);
|
|
423
|
+
if (!shard)
|
|
424
|
+
fail("progressive scale shard is not registered by the plan");
|
|
425
|
+
const executor = input.executor;
|
|
426
|
+
if (!executor ||
|
|
427
|
+
typeof executor !== "object" ||
|
|
428
|
+
executor.schemaVersion !== 1 ||
|
|
429
|
+
typeof executor.executeShardV1 !== "function")
|
|
430
|
+
fail("progressive scale executor is invalid");
|
|
431
|
+
identifier(executor.executorId, "executorId");
|
|
432
|
+
identifier(executor.executorVersion, "executorVersion");
|
|
433
|
+
const output = await executor.executeShardV1(Object.freeze({
|
|
434
|
+
schemaVersion: 1,
|
|
435
|
+
planDigest: plan.planDigest,
|
|
436
|
+
profile: plan.profile,
|
|
437
|
+
topology: plan.topology,
|
|
438
|
+
shard,
|
|
439
|
+
}));
|
|
440
|
+
return validateCollectiveProgressiveScaleShardResultV1(output, {
|
|
441
|
+
plan,
|
|
442
|
+
shard,
|
|
443
|
+
executorId: executor.executorId,
|
|
444
|
+
executorVersion: executor.executorVersion,
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
export function createCollectiveProgressiveScaleShardResultV1(input) {
|
|
448
|
+
strictRecord(input, [
|
|
449
|
+
"affectedPeers",
|
|
450
|
+
"eventStreamDigest",
|
|
451
|
+
"executorId",
|
|
452
|
+
"executorVersion",
|
|
453
|
+
"interactions",
|
|
454
|
+
"missionSuccessRateAfterRecoveryBasisPoints",
|
|
455
|
+
"missionSuccessRateBeforeFaultBasisPoints",
|
|
456
|
+
"plan",
|
|
457
|
+
"processedPeers",
|
|
458
|
+
"recoveredPeers",
|
|
459
|
+
"recoveryInteractions",
|
|
460
|
+
"recoveryWorkUnits",
|
|
461
|
+
"schemaVersion",
|
|
462
|
+
"shard",
|
|
463
|
+
"stateRootDigest",
|
|
464
|
+
], "progressive scale shard result input");
|
|
465
|
+
if (input.schemaVersion !== 1)
|
|
466
|
+
fail("progressive scale shard result schema is invalid");
|
|
467
|
+
const plan = validateCollectiveProgressiveScalePlanV1(input.plan);
|
|
468
|
+
const shard = plan.shards.find((entry) => entry.shardId === input.shard.shardId);
|
|
469
|
+
if (!shard || !sameJson(shard, input.shard))
|
|
470
|
+
fail("progressive scale result shard is mismatched");
|
|
471
|
+
identifier(input.executorId, "executorId");
|
|
472
|
+
identifier(input.executorVersion, "executorVersion");
|
|
473
|
+
const peerCount = shard.peerEndExclusive - shard.peerStartInclusive;
|
|
474
|
+
const interactionCount = shard.interactionEndExclusive - shard.interactionStartInclusive;
|
|
475
|
+
safeInteger(input.processedPeers, "processedPeers", 0, peerCount);
|
|
476
|
+
safeInteger(input.affectedPeers, "affectedPeers", 0, Math.min(input.processedPeers, shard.expectedAffectedPeers));
|
|
477
|
+
if (input.processedPeers === peerCount &&
|
|
478
|
+
input.affectedPeers !== shard.expectedAffectedPeers)
|
|
479
|
+
fail("progressive scale complete shard affected population is invalid");
|
|
480
|
+
safeInteger(input.recoveredPeers, "recoveredPeers", 0, input.affectedPeers);
|
|
481
|
+
safeInteger(input.interactions, "interactions", 0, interactionCount);
|
|
482
|
+
safeInteger(input.recoveryInteractions, "recoveryInteractions", 0, input.interactions);
|
|
483
|
+
safeInteger(input.recoveryWorkUnits, "recoveryWorkUnits", 0, Number.MAX_SAFE_INTEGER);
|
|
484
|
+
safeInteger(input.missionSuccessRateBeforeFaultBasisPoints, "missionSuccessRateBeforeFaultBasisPoints", 0, 10_000);
|
|
485
|
+
safeInteger(input.missionSuccessRateAfterRecoveryBasisPoints, "missionSuccessRateAfterRecoveryBasisPoints", 0, 10_000);
|
|
486
|
+
assertDigest(input.stateRootDigest, "stateRootDigest");
|
|
487
|
+
assertDigest(input.eventStreamDigest, "eventStreamDigest");
|
|
488
|
+
const body = {
|
|
489
|
+
schemaVersion: 1,
|
|
490
|
+
planDigest: plan.planDigest,
|
|
491
|
+
shardId: shard.shardId,
|
|
492
|
+
shardDigest: shard.shardDigest,
|
|
493
|
+
executorId: input.executorId,
|
|
494
|
+
executorVersion: input.executorVersion,
|
|
495
|
+
processedPeers: input.processedPeers,
|
|
496
|
+
affectedPeers: input.affectedPeers,
|
|
497
|
+
recoveredPeers: input.recoveredPeers,
|
|
498
|
+
interactions: input.interactions,
|
|
499
|
+
recoveryInteractions: input.recoveryInteractions,
|
|
500
|
+
recoveryWorkUnits: input.recoveryWorkUnits,
|
|
501
|
+
missionSuccessRateBeforeFaultBasisPoints: input.missionSuccessRateBeforeFaultBasisPoints,
|
|
502
|
+
missionSuccessRateAfterRecoveryBasisPoints: input.missionSuccessRateAfterRecoveryBasisPoints,
|
|
503
|
+
stateRootDigest: input.stateRootDigest,
|
|
504
|
+
eventStreamDigest: input.eventStreamDigest,
|
|
505
|
+
};
|
|
506
|
+
return deepFreezePlanning({
|
|
507
|
+
...body,
|
|
508
|
+
resultDigest: digest("progressive-scale-shard-result-v1", body),
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
export function validateCollectiveProgressiveScaleShardResultV1(input, binding) {
|
|
512
|
+
const value = strictRecord(input, resultKeys, "progressive scale shard result");
|
|
513
|
+
if (value.executorId !== binding.executorId ||
|
|
514
|
+
value.executorVersion !== binding.executorVersion)
|
|
515
|
+
fail("progressive scale executor binding is invalid");
|
|
516
|
+
const rebuilt = createCollectiveProgressiveScaleShardResultV1({
|
|
517
|
+
schemaVersion: value.schemaVersion,
|
|
518
|
+
plan: binding.plan,
|
|
519
|
+
shard: binding.shard,
|
|
520
|
+
executorId: value.executorId,
|
|
521
|
+
executorVersion: value.executorVersion,
|
|
522
|
+
processedPeers: value.processedPeers,
|
|
523
|
+
affectedPeers: value.affectedPeers,
|
|
524
|
+
recoveredPeers: value.recoveredPeers,
|
|
525
|
+
interactions: value.interactions,
|
|
526
|
+
recoveryInteractions: value.recoveryInteractions,
|
|
527
|
+
recoveryWorkUnits: value.recoveryWorkUnits,
|
|
528
|
+
missionSuccessRateBeforeFaultBasisPoints: value.missionSuccessRateBeforeFaultBasisPoints,
|
|
529
|
+
missionSuccessRateAfterRecoveryBasisPoints: value.missionSuccessRateAfterRecoveryBasisPoints,
|
|
530
|
+
stateRootDigest: value.stateRootDigest,
|
|
531
|
+
eventStreamDigest: value.eventStreamDigest,
|
|
532
|
+
});
|
|
533
|
+
if (!sameJson(value, rebuilt))
|
|
534
|
+
fail("progressive scale shard result binding is invalid");
|
|
535
|
+
return rebuilt;
|
|
536
|
+
}
|
|
537
|
+
export function createCollectiveProgressiveScaleReportV1(input) {
|
|
538
|
+
strictRecord(input, ["plan", "results", "roleCoherence", "schemaVersion"], "progressive scale report input");
|
|
539
|
+
if (input.schemaVersion !== 1)
|
|
540
|
+
fail("progressive scale report schema is invalid");
|
|
541
|
+
const plan = validateCollectiveProgressiveScalePlanV1(input.plan);
|
|
542
|
+
const rawResults = denseArray(input.results, plan.shards.length, "progressive scale results");
|
|
543
|
+
if (rawResults.length !== plan.shards.length)
|
|
544
|
+
fail("progressive scale report requires one result per shard");
|
|
545
|
+
const resultByShard = new Map();
|
|
546
|
+
for (const raw of rawResults) {
|
|
547
|
+
const rawRecord = strictRecord(raw, resultKeys, "progressive scale shard result");
|
|
548
|
+
const shard = plan.shards.find((entry) => entry.shardId === rawRecord.shardId);
|
|
549
|
+
if (!shard || resultByShard.has(shard.shardId))
|
|
550
|
+
fail("progressive scale report shard closure is invalid");
|
|
551
|
+
const result = validateCollectiveProgressiveScaleShardResultV1(raw, {
|
|
552
|
+
plan,
|
|
553
|
+
shard,
|
|
554
|
+
executorId: rawRecord.executorId,
|
|
555
|
+
executorVersion: rawRecord.executorVersion,
|
|
556
|
+
});
|
|
557
|
+
resultByShard.set(shard.shardId, result);
|
|
558
|
+
}
|
|
559
|
+
const ordered = plan.shards.map((shard) => resultByShard.get(shard.shardId));
|
|
560
|
+
const roleCoherence = validateCollectiveProgressiveScaleRoleCoherenceV1(input.roleCoherence, plan.profile);
|
|
561
|
+
const sum = (select) => ordered.reduce((total, result) => total + select(result), 0);
|
|
562
|
+
const processedPeers = sum((result) => result.processedPeers);
|
|
563
|
+
const affectedPeers = sum((result) => result.affectedPeers);
|
|
564
|
+
const recoveredPeers = sum((result) => result.recoveredPeers);
|
|
565
|
+
const interactions = sum((result) => result.interactions);
|
|
566
|
+
const recoveryInteractions = sum((result) => result.recoveryInteractions);
|
|
567
|
+
const recoveryWorkUnits = sum((result) => result.recoveryWorkUnits);
|
|
568
|
+
for (const [name, value] of [
|
|
569
|
+
["processedPeers", processedPeers],
|
|
570
|
+
["affectedPeers", affectedPeers],
|
|
571
|
+
["recoveredPeers", recoveredPeers],
|
|
572
|
+
["interactions", interactions],
|
|
573
|
+
["recoveryInteractions", recoveryInteractions],
|
|
574
|
+
["recoveryWorkUnits", recoveryWorkUnits],
|
|
575
|
+
])
|
|
576
|
+
if (!Number.isSafeInteger(value))
|
|
577
|
+
fail(`progressive scale ${name} is not a safe integer`);
|
|
578
|
+
const recoveryWorkCeiling = collectiveProgressiveScaleRecoveryWorkCeilingV1(plan.profile);
|
|
579
|
+
const roleCoherenceSatisfied = roleCoherence.unsafeActions === 0 &&
|
|
580
|
+
roleCoherence.coherentSteps === plan.profile.roleCoherenceSteps;
|
|
581
|
+
const interactionCoverageSatisfied = interactions === plan.profile.maximumInteractions &&
|
|
582
|
+
processedPeers === plan.profile.agentCount;
|
|
583
|
+
const affectedPopulationSatisfied = affectedPeers === affectedCount(plan.profile);
|
|
584
|
+
const recoverySatisfied = recoveredPeers === affectedPeers &&
|
|
585
|
+
recoveryWorkUnits <= recoveryWorkCeiling;
|
|
586
|
+
const missionSuccessRateRestored = ordered.every((result) => result.missionSuccessRateAfterRecoveryBasisPoints >=
|
|
587
|
+
result.missionSuccessRateBeforeFaultBasisPoints);
|
|
588
|
+
const body = {
|
|
589
|
+
schemaVersion: 1,
|
|
590
|
+
planDigest: plan.planDigest,
|
|
591
|
+
profileDigest: plan.profile.profileDigest,
|
|
592
|
+
shardResultDigests: Object.freeze(ordered.map((result) => result.resultDigest)),
|
|
593
|
+
roleCoherenceReportDigest: roleCoherence.reportDigest,
|
|
594
|
+
processedPeers,
|
|
595
|
+
affectedPeers,
|
|
596
|
+
recoveredPeers,
|
|
597
|
+
interactions,
|
|
598
|
+
recoveryInteractions,
|
|
599
|
+
recoveryWorkUnits,
|
|
600
|
+
recoveryWorkCeiling,
|
|
601
|
+
roleCoherenceSatisfied,
|
|
602
|
+
interactionCoverageSatisfied,
|
|
603
|
+
affectedPopulationSatisfied,
|
|
604
|
+
recoverySatisfied,
|
|
605
|
+
missionSuccessRateRestored,
|
|
606
|
+
conformant: roleCoherenceSatisfied &&
|
|
607
|
+
interactionCoverageSatisfied &&
|
|
608
|
+
affectedPopulationSatisfied &&
|
|
609
|
+
recoverySatisfied &&
|
|
610
|
+
missionSuccessRateRestored,
|
|
611
|
+
};
|
|
612
|
+
return deepFreezePlanning({
|
|
613
|
+
...body,
|
|
614
|
+
reportDigest: digest("progressive-scale-report-v1", body),
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
export function validateCollectiveProgressiveScaleReportV1(input, binding) {
|
|
618
|
+
const value = strictRecord(input, reportKeys, "progressive scale report");
|
|
619
|
+
const rebuilt = createCollectiveProgressiveScaleReportV1({
|
|
620
|
+
schemaVersion: value.schemaVersion,
|
|
621
|
+
plan: binding.plan,
|
|
622
|
+
results: binding.results,
|
|
623
|
+
roleCoherence: binding.roleCoherence,
|
|
624
|
+
});
|
|
625
|
+
if (!sameJson(value, rebuilt))
|
|
626
|
+
fail("progressive scale report binding is invalid");
|
|
627
|
+
return rebuilt;
|
|
628
|
+
}
|
|
629
|
+
export function collectiveProgressiveScaleRecoveryWorkCeilingV1(profileInput) {
|
|
630
|
+
const profile = validateCollectiveProgressiveScaleProfileV1(profileInput);
|
|
631
|
+
switch (profile.recoveryWorkClass) {
|
|
632
|
+
case "quadratic":
|
|
633
|
+
return profile.agentCount * profile.agentCount;
|
|
634
|
+
case "n_log_n":
|
|
635
|
+
return profile.agentCount * Math.ceil(Math.log2(profile.agentCount));
|
|
636
|
+
case "linear":
|
|
637
|
+
return profile.agentCount;
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
function affectedCount(profile) {
|
|
641
|
+
return Math.floor((profile.agentCount * profile.affectedAgentBasisPoints) / 10_000);
|
|
642
|
+
}
|
|
643
|
+
function partitionPoint(total, index, count) {
|
|
644
|
+
return Math.floor((total * index) / count);
|
|
645
|
+
}
|
|
646
|
+
function coprimeMultiplier(modulus, seed) {
|
|
647
|
+
let candidate = 1 + (seed % Math.max(1, modulus - 1));
|
|
648
|
+
while (greatestCommonDivisor(candidate, modulus) !== 1) {
|
|
649
|
+
candidate += 1;
|
|
650
|
+
if (candidate >= modulus)
|
|
651
|
+
candidate = 1;
|
|
652
|
+
}
|
|
653
|
+
return candidate;
|
|
654
|
+
}
|
|
655
|
+
function greatestCommonDivisor(left, right) {
|
|
656
|
+
let a = left;
|
|
657
|
+
let b = right;
|
|
658
|
+
while (b !== 0) {
|
|
659
|
+
const remainder = a % b;
|
|
660
|
+
a = b;
|
|
661
|
+
b = remainder;
|
|
662
|
+
}
|
|
663
|
+
return a;
|
|
664
|
+
}
|
|
665
|
+
function mix32(value) {
|
|
666
|
+
let mixed = value >>> 0;
|
|
667
|
+
mixed ^= mixed >>> 16;
|
|
668
|
+
mixed = Math.imul(mixed, 0x7feb_352d);
|
|
669
|
+
mixed ^= mixed >>> 15;
|
|
670
|
+
mixed = Math.imul(mixed, 0x846c_a68b);
|
|
671
|
+
mixed ^= mixed >>> 16;
|
|
672
|
+
return mixed >>> 0;
|
|
673
|
+
}
|
|
674
|
+
function digest(domain, value) {
|
|
675
|
+
return digestPlanningJsonV1(domain, value);
|
|
676
|
+
}
|
|
677
|
+
function sameJson(left, right) {
|
|
678
|
+
try {
|
|
679
|
+
return (canonicalizePlanningJsonV1(left) ===
|
|
680
|
+
canonicalizePlanningJsonV1(right));
|
|
681
|
+
}
|
|
682
|
+
catch {
|
|
683
|
+
return false;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
function strictRecord(input, keys, label, optionalUndefined = false) {
|
|
687
|
+
if (input === null ||
|
|
688
|
+
typeof input !== "object" ||
|
|
689
|
+
Array.isArray(input) ||
|
|
690
|
+
(Object.getPrototypeOf(input) !== Object.prototype &&
|
|
691
|
+
Object.getPrototypeOf(input) !== null) ||
|
|
692
|
+
Object.getOwnPropertySymbols(input).length !== 0)
|
|
693
|
+
fail(`${label} must be a plain object`);
|
|
694
|
+
const expected = [...keys].sort(compareAscii);
|
|
695
|
+
const names = Object.getOwnPropertyNames(input).sort(compareAscii);
|
|
696
|
+
if (optionalUndefined) {
|
|
697
|
+
const allowed = new Set(expected);
|
|
698
|
+
if (names.some((name) => !allowed.has(name)))
|
|
699
|
+
fail(`${label} has invalid fields`);
|
|
700
|
+
}
|
|
701
|
+
else if (names.length !== expected.length ||
|
|
702
|
+
names.some((name, index) => name !== expected[index])) {
|
|
703
|
+
fail(`${label} has invalid fields`);
|
|
704
|
+
}
|
|
705
|
+
for (const name of names) {
|
|
706
|
+
const descriptor = Object.getOwnPropertyDescriptor(input, name);
|
|
707
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable)
|
|
708
|
+
fail(`${label} has invalid property descriptors`);
|
|
709
|
+
}
|
|
710
|
+
return input;
|
|
711
|
+
}
|
|
712
|
+
function denseArray(input, maximum, label) {
|
|
713
|
+
if (!Array.isArray(input) ||
|
|
714
|
+
Object.getPrototypeOf(input) !== Array.prototype ||
|
|
715
|
+
Object.getOwnPropertySymbols(input).length !== 0 ||
|
|
716
|
+
input.length > maximum)
|
|
717
|
+
fail(`${label} must be a bounded dense array`);
|
|
718
|
+
const names = Object.getOwnPropertyNames(input);
|
|
719
|
+
if (names.length !== input.length + 1 || !names.includes("length"))
|
|
720
|
+
fail(`${label} must be a bounded dense array`);
|
|
721
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
722
|
+
const descriptor = Object.getOwnPropertyDescriptor(input, String(index));
|
|
723
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable)
|
|
724
|
+
fail(`${label} must be a bounded dense array`);
|
|
725
|
+
}
|
|
726
|
+
return Object.freeze([...input]);
|
|
727
|
+
}
|
|
728
|
+
function requireTier(value) {
|
|
729
|
+
if (typeof value !== "string" || !tiers.has(value))
|
|
730
|
+
fail("progressive scale tier is invalid");
|
|
731
|
+
}
|
|
732
|
+
function safeInteger(value, label, minimum, maximum) {
|
|
733
|
+
if (!Number.isSafeInteger(value) ||
|
|
734
|
+
value < minimum ||
|
|
735
|
+
value > maximum)
|
|
736
|
+
fail(`${label} must be a bounded safe integer`);
|
|
737
|
+
}
|
|
738
|
+
function identifier(value, label) {
|
|
739
|
+
if (typeof value !== "string" ||
|
|
740
|
+
value.length < 1 ||
|
|
741
|
+
value.length > 160 ||
|
|
742
|
+
!/^[A-Za-z0-9][A-Za-z0-9._:-]*$/u.test(value))
|
|
743
|
+
fail(`${label} is invalid`);
|
|
744
|
+
}
|
|
745
|
+
function assertDigest(value, label) {
|
|
746
|
+
if (typeof value !== "string" || !/^sha256:[0-9a-f]{64}$/u.test(value))
|
|
747
|
+
fail(`${label} is invalid`);
|
|
748
|
+
}
|
|
749
|
+
function compareAscii(left, right) {
|
|
750
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
751
|
+
}
|
|
752
|
+
function fail(message) {
|
|
753
|
+
throw new TypeError(message);
|
|
754
|
+
}
|
|
755
|
+
//# sourceMappingURL=collective-progressive-scale.js.map
|