humanish 0.19.0 → 0.20.0
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/dist/command-failure.d.ts +14 -0
- package/dist/command-failure.js +19 -0
- package/dist/command-failure.js.map +1 -1
- package/dist/computer-use-actor.d.ts +3 -0
- package/dist/computer-use-actor.js +2 -1
- package/dist/computer-use-actor.js.map +1 -1
- package/dist/computer-use.d.ts +9 -0
- package/dist/computer-use.js +57 -2
- package/dist/computer-use.js.map +1 -1
- package/dist/concurrent-shared-world-lab.d.ts +23 -1
- package/dist/concurrent-shared-world-lab.js +431 -41
- package/dist/concurrent-shared-world-lab.js.map +1 -1
- package/dist/cua-actor-lab.d.ts +7 -0
- package/dist/cua-actor-lab.js +4 -1
- package/dist/cua-actor-lab.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/init-templates.js +52 -0
- package/dist/init-templates.js.map +1 -1
- package/dist/lab-config.d.ts +54 -3
- package/dist/lab-config.js +162 -9
- package/dist/lab-config.js.map +1 -1
- package/dist/run.d.ts +46 -2
- package/dist/run.js +226 -1
- package/dist/run.js.map +1 -1
- package/dist/shared-world-lab.d.ts +8 -0
- package/dist/shared-world-lab.js.map +1 -1
- package/docs/architecture/external-public-shared-world.md +117 -0
- package/docs/architecture/state-driven-executor.md +33 -0
- package/docs/contracts/schemas.md +64 -5
- package/docs/goals/current.md +1 -1
- package/docs/principles/invariants-and-defaults.md +16 -0
- package/docs/product/cineguessr-3player-external-public.md +67 -0
- package/docs/ramp/README.md +1 -1
- package/docs/release/0.20.0-external-public-shared-world.md +43 -0
- package/package.json +1 -1
package/dist/run.js
CHANGED
|
@@ -3772,6 +3772,21 @@ function subjectStateFindings(bundle) {
|
|
|
3772
3772
|
}
|
|
3773
3773
|
case "undeclared":
|
|
3774
3774
|
break;
|
|
3775
|
+
case "external-public": {
|
|
3776
|
+
// #164 phase 2: an operator-declared, operator-owned public deployment humanish neither
|
|
3777
|
+
// provisioned nor seeded. There is no in-sandbox state story — a seed record or an external
|
|
3778
|
+
// channel here would contradict the "no subject sandbox" invariant of this plane class.
|
|
3779
|
+
if (subject.source !== "app-url") {
|
|
3780
|
+
findings.push('state marker "external-public" requires subject.source "app-url" — the external-public plane is a real public deployment, not a clone/local-tree subject');
|
|
3781
|
+
}
|
|
3782
|
+
if (seed.length > 0) {
|
|
3783
|
+
findings.push('state marker "external-public" cannot carry seed step records — the external-public plane is neither provisioned nor seeded by the harness');
|
|
3784
|
+
}
|
|
3785
|
+
if ((state.externalEnvNames ?? []).length > 0) {
|
|
3786
|
+
findings.push('state marker "external-public" cannot carry externalEnvNames — the plane is operator-owned, not an uncontrolled external channel');
|
|
3787
|
+
}
|
|
3788
|
+
break;
|
|
3789
|
+
}
|
|
3775
3790
|
default:
|
|
3776
3791
|
findings.push("unknown subject state provenance marker");
|
|
3777
3792
|
}
|
|
@@ -3915,6 +3930,22 @@ const CONCURRENT_REQUIRED_LIMITS = [
|
|
|
3915
3930
|
"state-change-not-isolated-to-actors"
|
|
3916
3931
|
];
|
|
3917
3932
|
const CONCURRENT_FORBIDDEN_LIMITS = ["sequential-only", "no-concurrent-races"];
|
|
3933
|
+
// EXTERNAL-PUBLIC plane class (#164 phase 2): the honest-downgrade required set. Keeps the concurrent
|
|
3934
|
+
// family (an honest ceiling) AND adds the mandatory disclosures for a plane the harness does NOT own:
|
|
3935
|
+
// the operator-attested (not harness-controlled) target, the ABSENCE of a synthetic attestation (you
|
|
3936
|
+
// cannot claim synthetic on a real site), the ABSENCE of an authoritative shared-state proof (no
|
|
3937
|
+
// in-sandbox filesystem to digest), and concurrency evidenced by temporal co-occupancy ONLY. Verify
|
|
3938
|
+
// FAILS CLOSED if any is missing (an absent honest-downgrade limit overclaims) — invariant 5.
|
|
3939
|
+
const EXTERNAL_PUBLIC_EXTRA_LIMITS = [
|
|
3940
|
+
"external-public-plane",
|
|
3941
|
+
"operator-attested-target-not-harness-controlled",
|
|
3942
|
+
"no-synthetic-attestation",
|
|
3943
|
+
"no-authoritative-shared-state-proof",
|
|
3944
|
+
"concurrency-by-temporal-co-occupancy-only"
|
|
3945
|
+
];
|
|
3946
|
+
// Any seeded/synthetic limit on this class is a getHost claim leaking onto a real public site — forbid
|
|
3947
|
+
// it alongside the sequential family. (A synthetic attestation on a plane the harness did not seed is a lie.)
|
|
3948
|
+
const EXTERNAL_PUBLIC_FORBIDDEN_LIMITS = ["sequential-only", "no-concurrent-races", "seeded", "synthetic"];
|
|
3918
3949
|
// A shared-world checkpoint record persists DIGEST-ONLY: exactly these keys, nothing value-shaped.
|
|
3919
3950
|
const SHARED_WORLD_CHECKPOINT_KEYS = new Set(["kind", "name", "digest", "deltaFromPrev"]);
|
|
3920
3951
|
// CONCURRENT stateSeries record is DIGEST-ONLY too (FIX-7): permit ONLY a numeric timestamp + the
|
|
@@ -4087,6 +4118,29 @@ function sequentialSharedWorldFindings(bundle, sw) {
|
|
|
4087
4118
|
* (genuine overlap + a state delta AT/AFTER an overlap start — FIX-6).
|
|
4088
4119
|
*/
|
|
4089
4120
|
function concurrentSharedWorldFindings(bundle, sw) {
|
|
4121
|
+
// The PLANE-class discriminator (#164 phase 2). Absent == the historical provisioned-getHost plane
|
|
4122
|
+
// (byte-stable). EVERY getHost-specific assertion (hostDigest, exposure: synthetic, seeded
|
|
4123
|
+
// provenance, state-delta on pass) is gated on this — it never leaks onto the external-public class,
|
|
4124
|
+
// and the external-public assertions never leak onto getHost.
|
|
4125
|
+
const planeClass = sw.planeClass;
|
|
4126
|
+
if (planeClass === "external-public") {
|
|
4127
|
+
return externalPublicConcurrentFindings(bundle, sw);
|
|
4128
|
+
}
|
|
4129
|
+
if (planeClass !== undefined && planeClass !== "provisioned-getHost") {
|
|
4130
|
+
return [
|
|
4131
|
+
...sharedWorldCommonFindings(bundle, sw),
|
|
4132
|
+
`sharedWorld.planeClass must be "provisioned-getHost" or "external-public" (got "${String(planeClass)}")`
|
|
4133
|
+
];
|
|
4134
|
+
}
|
|
4135
|
+
return provisionedGetHostConcurrentFindings(bundle, sw);
|
|
4136
|
+
}
|
|
4137
|
+
/**
|
|
4138
|
+
* PROVISIONED-getHost concurrent branch (the historical plane; #164 phase 2): a clone/local-tree
|
|
4139
|
+
* subject served + getHost-exposed in-sandbox — the harness MINTED the host, so it asserts the
|
|
4140
|
+
* synthetic-seeded attestation, the harness-minted host identity, and an authoritative in-sandbox
|
|
4141
|
+
* checkpoint state-delta on pass. UNCHANGED from the pre-external-public verify (byte-stable).
|
|
4142
|
+
*/
|
|
4143
|
+
function provisionedGetHostConcurrentFindings(bundle, sw) {
|
|
4090
4144
|
const findings = sharedWorldCommonFindings(bundle, sw);
|
|
4091
4145
|
// FIX-8: shape coherence — concurrent carries laneWindows/stateSeries/outcomes, NOT a timeline.
|
|
4092
4146
|
if (Array.isArray(sw.timeline)) {
|
|
@@ -4235,6 +4289,168 @@ function concurrentSharedWorldFindings(bundle, sw) {
|
|
|
4235
4289
|
}
|
|
4236
4290
|
return findings;
|
|
4237
4291
|
}
|
|
4292
|
+
/**
|
|
4293
|
+
* EXTERNAL-PUBLIC concurrent branch (#164 phase 2): N seats drove ONE real operator-owned public
|
|
4294
|
+
* deployment at once. The honest evidence class for a plane the harness does NOT own. Verify
|
|
4295
|
+
* fail-closed on the honest DOWNGRADES (asserted-absent, never silently dropped): provenance is
|
|
4296
|
+
* "external-public" (NOT seeded), exposure is ABSENT (claiming synthetic on a real site is a lie),
|
|
4297
|
+
* plane control is operator-attested (publicOriginDigest, not a harness-minted hostDigest), there is
|
|
4298
|
+
* NO authoritative shared-state proof (stateSeries omitted — option A), and concurrency is proven by
|
|
4299
|
+
* temporal co-occupancy ONLY (relaxed concurrency-on-pass: ≥2 overlapping windows, no state delta).
|
|
4300
|
+
* Every getHost-only claim (exposure: synthetic / plane.hostDigest / seeded / synthetic limit)
|
|
4301
|
+
* appearing here FAILS CLOSED.
|
|
4302
|
+
*/
|
|
4303
|
+
function externalPublicConcurrentFindings(bundle, sw) {
|
|
4304
|
+
const findings = sharedWorldCommonFindings(bundle, sw);
|
|
4305
|
+
// Shape coherence: concurrent carries laneWindows + outcomes, NOT a timeline. stateSeries is
|
|
4306
|
+
// deliberately OMITTED on this class (no in-sandbox filesystem to authoritatively digest).
|
|
4307
|
+
if (Array.isArray(sw.timeline)) {
|
|
4308
|
+
findings.push("an external-public concurrent bundle must NOT carry a sequential timeline (topologyMode mismatch)");
|
|
4309
|
+
}
|
|
4310
|
+
const laneWindows = Array.isArray(sw.laneWindows) ? sw.laneWindows.filter(isRecord) : null;
|
|
4311
|
+
const outcomes = Array.isArray(sw.outcomes) ? sw.outcomes.filter(isRecord) : null;
|
|
4312
|
+
if (laneWindows === null)
|
|
4313
|
+
findings.push("an external-public concurrent bundle must carry laneWindows");
|
|
4314
|
+
if (outcomes === null)
|
|
4315
|
+
findings.push("an external-public concurrent bundle must carry outcomes");
|
|
4316
|
+
// Option A: NO authoritative shared-state proof — a non-empty stateSeries would falsely imply the
|
|
4317
|
+
// harness digested the plane's backend state (it cannot; there is no in-sandbox filesystem).
|
|
4318
|
+
const stateSeries = sw.stateSeries;
|
|
4319
|
+
if (Array.isArray(stateSeries) && stateSeries.length > 0) {
|
|
4320
|
+
findings.push("an external-public concurrent bundle must NOT carry a stateSeries — the harness cannot authoritatively digest a real public plane's backend state (no in-sandbox filesystem); concurrency is proven by temporal co-occupancy, not a state series");
|
|
4321
|
+
}
|
|
4322
|
+
if (laneWindows === null || outcomes === null) {
|
|
4323
|
+
return findings; // can't reason further without the core series
|
|
4324
|
+
}
|
|
4325
|
+
// Attribution ceiling: the concurrent family AND every external-public honest-downgrade disclosure
|
|
4326
|
+
// must be present; the sequential family + any seeded/synthetic limit must be absent.
|
|
4327
|
+
const limits = Array.isArray(sw.attributionLimits) ? sw.attributionLimits : [];
|
|
4328
|
+
for (const required of [...CONCURRENT_REQUIRED_LIMITS, ...EXTERNAL_PUBLIC_EXTRA_LIMITS]) {
|
|
4329
|
+
if (!limits.includes(required)) {
|
|
4330
|
+
findings.push(`attributionLimits is missing the mandatory external-public disclosure "${required}" — an absent honest-downgrade ceiling overclaims`);
|
|
4331
|
+
}
|
|
4332
|
+
}
|
|
4333
|
+
for (const forbidden of EXTERNAL_PUBLIC_FORBIDDEN_LIMITS) {
|
|
4334
|
+
if (limits.includes(forbidden)) {
|
|
4335
|
+
findings.push(`attributionLimits carries the forbidden disclosure "${forbidden}" — the external-public plane cannot claim a sequential guarantee or a seeded/synthetic attestation on a real site`);
|
|
4336
|
+
}
|
|
4337
|
+
}
|
|
4338
|
+
// Phantom/dropped role: laneWindows + outcomes each cover exactly roleCount.
|
|
4339
|
+
if (laneWindows.length !== sw.roleCount) {
|
|
4340
|
+
findings.push(`phantom/dropped role: laneWindows count (${laneWindows.length}) must equal roleCount (${sw.roleCount})`);
|
|
4341
|
+
}
|
|
4342
|
+
if (outcomes.length !== sw.roleCount) {
|
|
4343
|
+
findings.push(`phantom/dropped role: outcomes count (${outcomes.length}) must equal roleCount (${sw.roleCount})`);
|
|
4344
|
+
}
|
|
4345
|
+
// laneWindows: numeric well-ordered windows; sim/stream resolve; route-host digest present.
|
|
4346
|
+
for (const window of laneWindows) {
|
|
4347
|
+
const roleId = typeof window.roleId === "string" ? window.roleId : "(unnamed)";
|
|
4348
|
+
if (typeof window.startedAt !== "number" || typeof window.endedAt !== "number" || !(window.startedAt <= window.endedAt)) {
|
|
4349
|
+
findings.push(`laneWindow "${roleId}" must carry numeric startedAt <= endedAt on one clock`);
|
|
4350
|
+
}
|
|
4351
|
+
if (typeof window.routeHostDigest !== "string" || !COMMAND_DIGEST_PATTERN.test(window.routeHostDigest)) {
|
|
4352
|
+
findings.push(`laneWindow "${roleId}" must record a sha256-16 routeHostDigest of the origin it reached`);
|
|
4353
|
+
}
|
|
4354
|
+
if (!bundle.simulations.some((sim) => sim.id === window.simId)) {
|
|
4355
|
+
findings.push(`laneWindow "${roleId}" references unknown simId "${String(window.simId)}"`);
|
|
4356
|
+
}
|
|
4357
|
+
if (!bundle.streams.some((stream) => stream.id === window.streamId)) {
|
|
4358
|
+
findings.push(`laneWindow "${roleId}" references unknown streamId "${String(window.streamId)}"`);
|
|
4359
|
+
}
|
|
4360
|
+
}
|
|
4361
|
+
// Plane identity (the honest analog of invariant 2, WEAKER + disclosed): the convergence proof is
|
|
4362
|
+
// about what the seats OBSERVED, not what was DECLARED. plane.publicOriginDigest is the OBSERVED
|
|
4363
|
+
// origin the seats converged on; verify requires every seat's CDP-OBSERVED routeHostDigest to agree
|
|
4364
|
+
// on ONE origin, and that publicOriginDigest BE that origin. Convergence on one observed origin proves
|
|
4365
|
+
// inter-seat co-location — NOT harness control of the plane. IMPORTANT: operator OWNERSHIP rests on
|
|
4366
|
+
// the subject.publicTarget.authorized attestation + the declared appUrl, NOT on digest equality — a
|
|
4367
|
+
// normal cross-origin redirect (apex->www, http->https) makes the observed origin differ from the
|
|
4368
|
+
// DECLARED one, which is expected and must NEVER fail verify (declaredOriginDigest is evidence-only).
|
|
4369
|
+
const plane = isRecord(sw.plane) ? sw.plane : {};
|
|
4370
|
+
const publicOriginDigest = typeof plane.publicOriginDigest === "string" ? plane.publicOriginDigest : undefined;
|
|
4371
|
+
if (!publicOriginDigest || !COMMAND_DIGEST_PATTERN.test(publicOriginDigest)) {
|
|
4372
|
+
findings.push("sharedWorld.plane.publicOriginDigest (sha256-16 of the OBSERVED origin the seats converged on) is required on the external-public plane class");
|
|
4373
|
+
}
|
|
4374
|
+
// The observed origins across seats must agree on exactly ONE (that agreement IS the convergence).
|
|
4375
|
+
const observedOrigins = laneWindows
|
|
4376
|
+
.map((window) => (typeof window.routeHostDigest === "string" ? window.routeHostDigest : undefined))
|
|
4377
|
+
.filter((digest) => digest !== undefined);
|
|
4378
|
+
const distinctObserved = [...new Set(observedOrigins)];
|
|
4379
|
+
if (distinctObserved.length > 1) {
|
|
4380
|
+
findings.push(`the seats did not converge on ONE OBSERVED origin — distinct observed origin digests: ${distinctObserved.join(", ")}`);
|
|
4381
|
+
}
|
|
4382
|
+
else if (publicOriginDigest && distinctObserved.length === 1 && distinctObserved[0] !== publicOriginDigest) {
|
|
4383
|
+
findings.push(`sharedWorld.plane.publicOriginDigest (${publicOriginDigest}) must equal the single OBSERVED origin the seats converged on (${distinctObserved[0]})`);
|
|
4384
|
+
}
|
|
4385
|
+
// declaredOriginDigest is recorded for evidence ONLY. Validate its shape when present, but NEVER
|
|
4386
|
+
// assert it equals the observed origin — a cross-origin redirect is normal and expected.
|
|
4387
|
+
if (plane.declaredOriginDigest !== undefined
|
|
4388
|
+
&& (typeof plane.declaredOriginDigest !== "string" || !COMMAND_DIGEST_PATTERN.test(plane.declaredOriginDigest))) {
|
|
4389
|
+
findings.push("sharedWorld.plane.declaredOriginDigest, when present, must be a sha256-16 digest of the operator-declared origin (evidence-only; not asserted equal to the observed origin)");
|
|
4390
|
+
}
|
|
4391
|
+
// INVERT the getHost gate: exposure MUST be absent (claiming synthetic on a real site is a lie) and
|
|
4392
|
+
// the harness-minted hostDigest MUST be absent (the harness minted no host here).
|
|
4393
|
+
if (plane.exposure !== undefined) {
|
|
4394
|
+
findings.push('sharedWorld.plane.exposure must be ABSENT on the external-public plane class — the harness neither provisioned nor exposed the plane, so it cannot attest "synthetic" on a real site');
|
|
4395
|
+
}
|
|
4396
|
+
if (plane.hostDigest !== undefined) {
|
|
4397
|
+
findings.push("sharedWorld.plane.hostDigest must be ABSENT on the external-public plane class — a harness-minted host identity is a getHost claim; this plane is operator-attested, not harness-minted");
|
|
4398
|
+
}
|
|
4399
|
+
// Provenance is the NEW external-public marker — NOT seeded (nothing was seeded), NOT unpinned.
|
|
4400
|
+
if (bundle.subject?.state.provenance !== "external-public") {
|
|
4401
|
+
findings.push(`the external-public plane class requires subject.state.provenance == "external-public" (got "${bundle.subject?.state.provenance ?? "absent"}") — a seeded/unpinned/undeclared claim on an operator-owned public deployment is dishonest`);
|
|
4402
|
+
}
|
|
4403
|
+
if (bundle.subject?.source !== "app-url") {
|
|
4404
|
+
findings.push('the external-public plane class requires subject.source == "app-url" — the plane is a real public deployment, not a provisioned subject');
|
|
4405
|
+
}
|
|
4406
|
+
// Single-plane provenance: every laneWindow shares ONE (commit, seedDigest) matching plane. commit
|
|
4407
|
+
// is absent on this class (nothing cloned); seedDigest is the constant empty-recipe digest.
|
|
4408
|
+
const planeKeys = new Set(laneWindows.map((window) => `${String(window.commit ?? "")}::${String(window.seedDigest ?? "")}`));
|
|
4409
|
+
if (planeKeys.size > 1) {
|
|
4410
|
+
findings.push("laneWindows reference divergent plane provenance (commit/seedDigest) — a shared-world run drives ONE plane");
|
|
4411
|
+
}
|
|
4412
|
+
for (const window of laneWindows) {
|
|
4413
|
+
if (String(window.seedDigest ?? "") !== String(plane.seedDigest ?? "")
|
|
4414
|
+
|| String(window.commit ?? "") !== String(plane.commit ?? "")) {
|
|
4415
|
+
const roleId = typeof window.roleId === "string" ? window.roleId : "(unnamed)";
|
|
4416
|
+
findings.push(`laneWindow "${roleId}" plane provenance diverges from sharedWorld.plane`);
|
|
4417
|
+
break;
|
|
4418
|
+
}
|
|
4419
|
+
}
|
|
4420
|
+
// The lobby-convergence proof (optional-but-strong): if present it must be a sha256-16 digest of the
|
|
4421
|
+
// shared /lobby/CODE path all seats converged on (digest-only; the raw CODE never lands).
|
|
4422
|
+
const lobbyConvergenceDigest = sw.lobbyConvergenceDigest;
|
|
4423
|
+
if (lobbyConvergenceDigest !== undefined
|
|
4424
|
+
&& (typeof lobbyConvergenceDigest !== "string" || !COMMAND_DIGEST_PATTERN.test(lobbyConvergenceDigest))) {
|
|
4425
|
+
findings.push("sharedWorld.lobbyConvergenceDigest must be a sha256-16 digest (digest-only; the raw lobby code never lands)");
|
|
4426
|
+
}
|
|
4427
|
+
// The RELAXED concurrency-on-pass gate: a PASSED external-public run MUST show genuine temporal
|
|
4428
|
+
// co-occupancy (≥2 laneWindows overlapping in time). There is NO state-delta requirement — the
|
|
4429
|
+
// observed co-occupancy of one declared origin (plus the optional lobby convergence) carries the
|
|
4430
|
+
// "they shared a world" claim, disclosed as concurrency-by-temporal-co-occupancy-only.
|
|
4431
|
+
if (bundle.review.verdict === "pass") {
|
|
4432
|
+
let overlap = false;
|
|
4433
|
+
for (let i = 0; i < laneWindows.length && !overlap; i += 1) {
|
|
4434
|
+
for (let j = i + 1; j < laneWindows.length; j += 1) {
|
|
4435
|
+
const a = laneWindows[i];
|
|
4436
|
+
const b = laneWindows[j];
|
|
4437
|
+
const aStart = a.startedAt;
|
|
4438
|
+
const aEnd = a.endedAt;
|
|
4439
|
+
const bStart = b.startedAt;
|
|
4440
|
+
const bEnd = b.endedAt;
|
|
4441
|
+
if (typeof aStart === "number" && typeof aEnd === "number" && typeof bStart === "number" && typeof bEnd === "number"
|
|
4442
|
+
&& aStart < bEnd && bStart < aEnd) {
|
|
4443
|
+
overlap = true;
|
|
4444
|
+
break;
|
|
4445
|
+
}
|
|
4446
|
+
}
|
|
4447
|
+
}
|
|
4448
|
+
if (!overlap) {
|
|
4449
|
+
findings.push("review verdict is pass but no two laneWindows overlap in time — the external-public run was not actually concurrent (concurrency is proven by temporal co-occupancy on this class)");
|
|
4450
|
+
}
|
|
4451
|
+
}
|
|
4452
|
+
return findings;
|
|
4453
|
+
}
|
|
4238
4454
|
/**
|
|
4239
4455
|
* Advisory (never flips ok): a LIVE clone bundle whose subject env is provisioned while its
|
|
4240
4456
|
* state story is undeclared probably points at state the lab does not control. Emitted at
|
|
@@ -4534,6 +4750,14 @@ function isSharedWorldEvidence(value) {
|
|
|
4534
4750
|
return false;
|
|
4535
4751
|
if (plane.exposure !== undefined && typeof plane.exposure !== "string")
|
|
4536
4752
|
return false;
|
|
4753
|
+
if (plane.publicOriginDigest !== undefined && typeof plane.publicOriginDigest !== "string")
|
|
4754
|
+
return false;
|
|
4755
|
+
if (plane.declaredOriginDigest !== undefined && typeof plane.declaredOriginDigest !== "string")
|
|
4756
|
+
return false;
|
|
4757
|
+
if (value.planeClass !== undefined && typeof value.planeClass !== "string")
|
|
4758
|
+
return false;
|
|
4759
|
+
if (value.lobbyConvergenceDigest !== undefined && typeof value.lobbyConvergenceDigest !== "string")
|
|
4760
|
+
return false;
|
|
4537
4761
|
if (!(Array.isArray(value.attributionLimits) && value.attributionLimits.every((limit) => typeof limit === "string")))
|
|
4538
4762
|
return false;
|
|
4539
4763
|
// Tolerant: validate the TYPE of each present field only (the coherence + topologyMode dispatch
|
|
@@ -4627,7 +4851,8 @@ function isRunSubjectProvenance(value) {
|
|
|
4627
4851
|
if (!isRecord(state))
|
|
4628
4852
|
return false;
|
|
4629
4853
|
if (state.provenance !== "seeded" && state.provenance !== "unpinned"
|
|
4630
|
-
&& state.provenance !== "declared-not-run" && state.provenance !== "undeclared"
|
|
4854
|
+
&& state.provenance !== "declared-not-run" && state.provenance !== "undeclared"
|
|
4855
|
+
&& state.provenance !== "external-public") {
|
|
4631
4856
|
return false;
|
|
4632
4857
|
}
|
|
4633
4858
|
if (state.seed !== undefined
|