import { describe, expect, it } from "vitest"; import { BufferGeometry, Float32BufferAttribute } from "three"; import { readFileSync } from "node:fs"; import { resolve } from "node:path"; import { buildPartyNavigationGraph } from "./partyNavigation"; import { auditOrderedObjectiveRoutes } from "../../scripts/runewaker-pipeline/lib/objective-route-audit.mjs"; describe("RuneWaker ordered objective route audit", () => { it("does not substitute the last reachable point for an unreachable predecessor", () => { const geometry = new BufferGeometry(); geometry.setAttribute("position", new Float32BufferAttribute([ 0, 0, 0, 4, 0, 0, 0, 0, 4, 20, 0, 0, 21, 0, 0, 20, 0, 1, ], 3)); const graph = buildPartyNavigationGraph(geometry); const routes = auditOrderedObjectiveRoutes(graph, [1, 0, 1], [ { id: "island-boss", name: "Island Boss", position: [20, 0, 0] }, { id: "home-boss", name: "Home Boss", position: [2, 0, 1] }, ]); expect(routes.map(({ from, to, reachable }) => ({ from, to, reachable }))).toEqual([ { from: "entrance", to: "Island Boss", reachable: false }, { from: "Island Boss", to: "Home Boss", reachable: false }, ]); }); it("keeps the reviewed navigation blockers deterministic and fail-closed", () => { const report = JSON.parse(readFileSync(resolve( "scripts/runewaker-pipeline/RUNEWAKER_NAVIGATION_GAP_REPORT.json", ), "utf8")); expect(report.schemaVersion).toBe(2); expect(report).not.toHaveProperty("generatedAt"); expect(report.unreachableLegs).toBe(19); expect(report.dungeons).toHaveLength(8); expect(report.resolutionSummary).toEqual({ sourceAuthoredFixedOrders: 0, authoredOffMeshLinksAdded: 0, requirementDungeonCounts: { "dynamic-navigation-transition": 5, "encounter-gate-state": 3, "encounter-teleport-state": 2, "modular-environment-assembly": 3, "navigation-geometry-review": 1, "nonlinear-objectives": 1, "source-objective-review": 6, }, }); expect(report.dungeons.every((dungeon: { objectiveOrdering: { authoritative: boolean }; reviewedFinding: { safeAutomaticLink: boolean; requirements: string[] }; }) => ( dungeon.objectiveOrdering.authoritative === false && dungeon.reviewedFinding.safeAutomaticLink === false && dungeon.reviewedFinding.requirements.length > 0 ))).toBe(true); expect(report.dungeons.find((dungeon: { id: string }) => ( dungeon.id === "kalins-shrine" ))?.reviewedFinding.objectiveOrderStatus).toBe("source-randomized-not-linear"); }); });