"use strict"; const assert = require("assert"); const fs = require("fs"); const path = require("path"); const vm = require("vm"); const ROOT = path.resolve(__dirname, ".."); const read = rel => fs.readFileSync(path.join(ROOT, rel), "utf8"); const render = read("js/render.js"); assert(!render.includes("insertionSortNearPrevious"), "custom insertion sort still exists"); assert(!render.includes("_renderPrevDynamicLayeredIds") && !render.includes("_renderBackSortMap"), "previous-order render bookkeeping still exists"); assert(render.includes("dynamicBack.sort(compareBackItems)") && render.includes("dynamicLayered.sort(compareRenderEntries)"), "native render sort is not active"); console.log("[OK] previous-order Map and custom insertion sort are removed"); const pathfinding = read("js/world_pathfinding_system.js"); assert(!pathfinding.includes("_sharedRouteCache") && !pathfinding.includes("trySharedRoute") && !pathfinding.includes("storeSharedRoute"), "shared route cache still exists"); assert(pathfinding.includes("actor._routeCache"), "actor-local route cache was removed accidentally"); console.log("[OK] shared route cache is removed while actor-local throttling remains"); const profiler = read("js/perf_profiler.js"); const budget = read("js/world_spatial_budget.js"); assert(profiler.includes("diagnosticsEnabled"), "diagnostic-mode gate is missing"); assert(budget.includes("diagnostics ?") && budget.includes("this.workStats = diagnostics ?"), "production detailed diagnostic allocation is still unconditional"); assert(profiler.includes("transitionHoldSeconds") && profiler.includes("pendingProfileSeconds"), "performance-profile hysteresis hold timers are missing"); console.log("[OK] production diagnostics are gated and auto profile switching uses hysteresis"); const environment = read("js/world_environment.js"); assert(environment.includes("`${this.routingObstacleVersion || 0}:${qx},${qy},${qr},${cacheLimit},${maxRects}`"), "obstacle cache is not keyed by routingObstacleVersion only"); assert(!environment.includes("`${this.spatialVersion || 0}:${this.spatialDirtyMarksTotal || 0}:${qx}"), "obstacle cache still invalidates on generic spatial movement"); console.log("[OK] obstacle cache invalidation is isolated from generic spatial movement"); const simCore = read("js/sim_core.js"); const start = simCore.indexOf("class SpatialGrid {"); const end = simCore.indexOf("\nfunction drawHeartShape", start); assert(start >= 0 && end > start, "SpatialGrid source could not be isolated"); const context = { console, Map, Set, Math, Number, Array, globalThis: {} }; vm.createContext(context); vm.runInContext(`${simCore.slice(start, end)}\nglobalThis.SpatialGrid = SpatialGrid;`, context); const SpatialGrid = context.globalThis.SpatialGrid; const grid = new SpatialGrid(100); const a = { id: "a", x: 10, y: 10, dead: false }; const b = { id: "b", x: 40, y: 40, dead: false }; grid.rebuildTarinai([a, b]); const firstKey = a._spatialTarinaiCellKey; a.x = 50; assert.strictEqual(grid.syncTarinai([a, b]), 0, "same-cell movement should not rewrite the grid"); a.x = 150; assert.strictEqual(grid.syncTarinai([a, b]), 1, "cell crossing should update exactly one entity"); assert.notStrictEqual(a._spatialTarinaiCellKey, firstKey, "cell key did not change after crossing"); b.dead = true; assert(grid.syncTarinai([a, b]) >= 1, "dead entity was not removed incrementally"); assert(!grid._indexedTarinai.has(b), "dead entity remains in the Tarinai spatial index"); console.log("[OK] Tarinai spatial grid updates only cell crossings/removals instead of full rebuilds"); class World {} global.World = World; global.TarinaiHistory = { trimMemory() { return 0; } }; require(path.join(ROOT, "js", "world_spatial_budget.js")); const world = new World(); world.time = 100; world.tarinai = Array.from({ length: 120 }, (_, i) => ({ id: `T${i}`, dead: false, relationships: { D: { affinity: 1 } } })); world.liveTarinai = new Map(world.tarinai.map(t => [t.id, { target: t }])); world._deadTarinaiIdsPendingCleanup = new Set(["D"]); world.tarinaiCollisionMemo = new Map(); world.relationNotices = {}; world.fightPairCooldowns = {}; world.resolvedFightIds = {}; assert(world.queueTarinaiRuntimeCachePrune("audit", { resetRelationPeerCaches: true }), "cleanup job was not queued"); world.processTarinaiRuntimeCachePruneStep(24); assert(world._tarinaiRuntimePruneJob, "cleanup finished in one frame instead of being chunked"); assert.strictEqual(world._tarinaiRuntimePruneJob.cursor, 24, "cleanup chunk size was not respected"); while (world._tarinaiRuntimePruneJob) world.processTarinaiRuntimeCachePruneStep(24); assert(world.tarinai.every(t => !Object.prototype.hasOwnProperty.call(t.relationships, "D")), "chunked cleanup left dead references behind"); console.log("[OK] death-reference cleanup runs in bounded per-frame chunks"); console.log("Performance cleanup regression audit passed.");