test(migration): establish W2 native oracle and release removed overlay identities

Add the sequential W2/completion plan and deterministic earthquake ground-raster, geometry, lifecycle and strict runtime QA. Prove the comparator rejects incomplete evidence and release deleted overlay entries from the collision arbiter. Record native dev/preview acceptance and full checkpoint gates.
This commit is contained in:
German Khokhlov committed 2026-10-27 10:48:26 +04:00
1 parent 0600964249
commit e8870a4766
4 files changed
+154 -7

No files matched your search

+47
View File
@@ -0,0 +1,47 @@
// USGS-shaped fixed observations; source parsers remain the production ones.
export const W2_EPOCH_MS = 1792152000000;
export function earthquakeFixture() {
const features = [];
for (const [region, lon, lat] of [
['sf', -122.42, 37.77],
['austin', -97.74, 30.27],
['alaska', -150.4, 61.0],
]) {
for (let i = 0; i < 5; i++) {
features.push({
type: 'Feature',
id: `qa-${region}-${i}`,
geometry: {
type: 'Point',
coordinates: [
lon + (i - 2) * 0.24,
lat + (i % 2) * 0.3,
[8, 70, 300, 301, 45][i],
],
},
properties: {
mag: [2.5, 3, 4, 5, 5.5][i],
place: `W2 ${region} event ${i}`,
time: W2_EPOCH_MS - i * 60000,
},
});
}
}
features.push({
type: 'Feature',
id: 'qa-below',
geometry: { type: 'Point', coordinates: [-122.42, 37.77, 5] },
properties: { mag: 2.4 },
});
features.push({
type: 'Feature',
id: 'qa-missing-mag',
geometry: { type: 'Point', coordinates: [-122.4, 37.7, 5] },
properties: { mag: null },
});
return {
type: 'FeatureCollection',
metadata: { generated: W2_EPOCH_MS },
features,
};
}
+4 -1
View File
@@ -1179,5 +1179,8 @@
"src/globe/navara/movers/frameCamera.test.mjs",
"src/layers/localAdsb/qaDrawn.js",
"src/layers/localAdsb/qaDrawn.test.mjs",
"src/tooling/w1RuntimeEvidence.test.mjs"
"src/tooling/w1RuntimeEvidence.test.mjs",
"scripts/qa-w2-layers.mjs",
"scripts/fixtures/w2/earthquakes.mjs",
"src/tooling/w2QaComparison.test.mjs"
]
+14 -6
View File
@@ -951,6 +951,14 @@ export function registerWorldOverlayPaintLane(laneId, painter, options = {}) {
};
}
// Removed entries cannot paint an exit fade: their source no longer owns
// them. Release the arbiter identity too, so later layout changes cannot
// wake the idle renderer for an invisible minimum-lifetime/fade state.
function forgetOverlayEntry(entry) {
_records.delete(entry._overlayKey);
_domains.get(entry.collisionGroup)?.arbiter.remove(entry._overlayKey);
}
/**
* Replace all entries owned by a source atomically.
* @param {string} sourceId
@@ -968,7 +976,7 @@ export function setOverlayEntries(sourceId, entries, options = {}) {
const next = new Map();
for (const entry of normalized) next.set(entry.id, entry);
for (const entry of source.entries.values()) {
if (!next.has(entry.id)) _records.delete(entry._overlayKey);
if (!next.has(entry.id)) forgetOverlayEntry(entry);
const replacement = next.get(entry.id);
if (replacement && isProtected(entry) !== isProtected(replacement))
getOrCreateDomain(entry.collisionGroup).arbiter.remove(entry._overlayKey);
@@ -1005,9 +1013,10 @@ export function removeOverlayEntry(sourceId, entryId) {
const source = _sources.get(assertSourceId(sourceId));
if (!source) return false;
const id = String(entryId);
const removed = source.entries.delete(id);
if (!removed) return false;
_records.delete(entryKey(source.id, id));
const entry = source.entries.get(id);
if (!entry) return false;
source.entries.delete(id);
forgetOverlayEntry(entry);
rebuildSourceCohorts(source);
updateEntryDiagnostics();
invalidateHost();
@@ -1023,8 +1032,7 @@ export function clearOverlaySource(sourceId) {
if (_destroyed) return false;
const source = _sources.get(assertSourceId(sourceId));
if (!source) return false;
for (const entry of source.entries.values())
_records.delete(entry._overlayKey);
for (const entry of source.entries.values()) forgetOverlayEntry(entry);
source.entries.clear();
source.cohortDomainIds.length = 0;
source.cohortLists.length = 0;
+89
View File
@@ -2378,3 +2378,92 @@ test('the host takes a globe engine and refuses a bare viewer', async () => {
assert.equal(engine.frames.postRender.numberOfListeners, 1);
env.cleanup();
});
// Source deletion is final: invisible candidates must not retain minimum-life
// or fade state which wakes a dormant scene on a later UI/layout invalidation.
for (const [name, remove] of [
["clear", () => clearOverlaySource("deleted-static")],
["remove", () => removeOverlayEntry("deleted-static", "event")],
["replace-empty", () => setOverlayEntries("deleted-static", [])],
]) {
test(`removed static labels stay dormant after ${name}`, () => {
const env = installMockEnvironment();
try {
initWorldOverlay(env.engine);
setOverlayEntries(
"deleted-static",
[
selectedEntry("event", {
selected: false,
protected: false,
variant: "card",
collisionGroup: "deleted-static",
priority: 100,
verticalOnly: true,
}),
],
{ collisionCapacity: 1, maxVisible: 1 },
);
env.advanceTime(600);
env.postRender.raise();
env.advanceTime(600);
env.postRender.raise();
assert.ok(getWorldOverlayDiagnostics().selectedCount > 0);
remove();
env.postRender.raise();
env.viewer.scene.requestRenderCount = 0;
for (let i = 0; i < 16; i++) {
env.advanceTime(250);
for (const observer of env.resizeObservers) observer.callback();
env.postRender.raise();
}
assert.equal(getWorldOverlayDiagnostics().paintedCount, 0);
assert.equal(
env.viewer.scene.requestRenderCount,
0,
"removed source must not retain fades/minimum lifetimes and wake idle",
);
} finally {
env.cleanup();
}
});
}
test("clearing one static source preserves another source in the same label domain", () => {
const env = installMockEnvironment();
try {
initWorldOverlay(env.engine);
for (const [source, x] of [
["left", -0.5],
["right", 0.5],
])
setOverlayEntries(
source,
[
selectedEntry("event", {
position: new Cesium.Cartesian3(x, 0, 0),
selected: false,
protected: false,
collisionGroup: "ambient-card",
verticalOnly: true,
}),
],
{ collisionCapacity: 1, maxVisible: 1 },
);
env.advanceTime(100);
env.postRender.raise();
env.advanceTime(600);
env.postRender.raise();
assert.deepEqual(getWorldOverlayDiagnostics().paintedBySource, {
left: 1,
right: 1,
});
clearOverlaySource("left");
env.postRender.raise();
assert.deepEqual(getWorldOverlayDiagnostics().paintedBySource, {
right: 1,
});
} finally {
env.cleanup();
}
});