diff --git a/Aetheria.State.Daemon/AetheriaDaemonZoneGenerator.cs b/Aetheria.State.Daemon/AetheriaDaemonZoneGenerator.cs index db92be6e0..c858637d0 100644 --- a/Aetheria.State.Daemon/AetheriaDaemonZoneGenerator.cs +++ b/Aetheria.State.Daemon/AetheriaDaemonZoneGenerator.cs @@ -90,17 +90,8 @@ internal static class AetheriaDaemonZoneGenerator GravityTerrainDepthExponent = 1.18, GravityTerrainBoundaryFog = 0.25, GravityTerrainWaveFrequency = 0.55, - NextPickupIndex = 1, - DroppedPickups = - [ - new AetheriaDroppedPickupSnapshot - { - PickupIndex = 0, - Position = Vec3(-50, 0, 40), - Velocity = Vec3(0, 0, 0), - Item = new AetheriaLoadoutItem { ItemKey = "scrap-metal", Quantity = 1 } - } - ] + NextPickupIndex = 0, + DroppedPickups = Array.Empty() }).ConfigureAwait(false); for (var i = 0; i < entities.Length; i++) @@ -230,7 +221,7 @@ internal static class AetheriaDaemonZoneGenerator Entity(loadouts, availabilityFactions, "Torch Three", "ship", -235, 210, 8, -4, "player", 500, keys[7], [keys[0], keys[1], keys[7]], ["micro-missile", "coolant-pack"]), Entity(loadouts, availabilityFactions, "Foundry Tug", "ship", 330, -155, -2, 3, "player", 390, keys[6], [keys[0], keys[1], keys[6], keys[10]], ["ore-canister", "field-rations"]), Entity(loadouts, availabilityFactions, "Derelict Relay", "station", -390, 270, 0, 0, "neutral", 160, "", [keys[0], keys[3]], ["ancient-transponder"]), - Entity(loadouts, availabilityFactions, "Ash Raider", "ship", 20, -30, -5, -2, "raider", 320, "", [keys[0], keys[1], keys[2], keys[4]], ["scrap-metal", "stolen-capacitor"]), + Entity(loadouts, availabilityFactions, "Ash Raider", "ship", 20, -30, -5, -2, "raider", 320, "", [keys[0], keys[1], keys[2], keys[4]], []), Entity(loadouts, availabilityFactions, "Cinder Knife", "ship", 585, -115, -7, 1, "raider", 280, "", [keys[0], keys[3]], ["volatile-fuel"]), Entity(loadouts, availabilityFactions, "Blackwake", "ship", 690, 300, -4, -3, "raider", 230, "", [keys[2]], ["ore-cache", "burned-relay-core"]), Entity(loadouts, availabilityFactions, "Vesper Sloop", "ship", 960, 620, -3, -5, "raider", 250, "", [keys[4]], ["stolen-map-fragment"]), @@ -246,6 +237,51 @@ internal static class AetheriaDaemonZoneGenerator Items = Array.Empty() } ]; + entities[6].StatGrids = + [ + StatGrid("hull", 1), + StatGrid("shield", 0), + StatGrid("heat", 0) + ]; + var salvage = entities[6].Equipment.FirstOrDefault() + ?? throw new InvalidOperationException("The starter raider loadout produced no canonical salvage item."); + var salvageSelection = entities[6].LoadoutGeneration.Selections.First(selection => + string.Equals(selection.Role, "equipment", StringComparison.Ordinal) && + string.Equals(selection.ItemKey, salvage.ItemKey, StringComparison.Ordinal)); + entities[6].CargoContents = + [ + new AetheriaCargoBayLoadout + { + Items = + [ + new AetheriaLoadoutItemSlot + { + Item = new AetheriaLoadoutItem + { + ItemKey = salvage.ItemKey, + Quality = salvage.Quality, + Durability = salvage.Durability, + Quantity = 1, + Enabled = true + } + } + ] + } + ]; + entities[6].Equipment = Array.Empty(); + entities[6].WeaponGroups = Array.Empty(); + entities[6].LoadoutGeneration.Selections = entities[6].LoadoutGeneration.Selections + .Where(selection => string.Equals(selection.Role, "hull", StringComparison.Ordinal)) + .Append(new AetheriaLoadoutGenerationSelection + { + Role = "cargo", + ItemKey = salvageSelection.ItemKey, + ManufacturerKey = salvageSelection.ManufacturerKey, + Price = salvageSelection.Price, + ManufacturerDistance = salvageSelection.ManufacturerDistance, + Allegiance = salvageSelection.Allegiance + }) + .ToArray(); entities[2].AgentTaskCapabilities = ["attack", "defend", "explore"]; entities[3].AgentTaskCapabilities = ["attack", "defend"]; entities[4].AgentTaskCapabilities = ["mine", "haul", "tow", "explore"]; diff --git a/Aetheria.Unity/Packages/manifest.json b/Aetheria.Unity/Packages/manifest.json index 8847f1a1a..7a0210b7e 100644 --- a/Aetheria.Unity/Packages/manifest.json +++ b/Aetheria.Unity/Packages/manifest.json @@ -6,9 +6,9 @@ "com.unity.modules.physics": "1.0.0", "com.unity.modules.uielements": "1.0.0", "com.unity.render-pipelines.universal": "17.4.0", - "org.gamecult.cultlib": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.13", + "org.gamecult.cultlib": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.14", "org.gamecult.eve.plugin-fields": "https://github.com/GameCult/EvePlugins.git?path=/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields#eve-plugin-fields-unity-v0.2.3", "org.gamecult.eve.surface": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.surface#eveunity-surface-v0.2.2", - "org.gamecult.eve.unity-scene": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.49" + "org.gamecult.eve.unity-scene": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.50" } } diff --git a/Aetheria.Unity/Packages/packages-lock.json b/Aetheria.Unity/Packages/packages-lock.json index 0524e8dd8..7e8820524 100644 --- a/Aetheria.Unity/Packages/packages-lock.json +++ b/Aetheria.Unity/Packages/packages-lock.json @@ -119,11 +119,11 @@ } }, "org.gamecult.cultlib": { - "version": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.13", + "version": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.14", "depth": 0, "source": "git", "dependencies": {}, - "hash": "feb5c71513e71d681699f462fe3682b3168c6f73" + "hash": "4b7162022a8976f7941b5a7a69acf50f1b6d532b" }, "org.gamecult.eve.plugin-fields": { "version": "https://github.com/GameCult/EvePlugins.git?path=/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields#eve-plugin-fields-unity-v0.2.3", @@ -144,18 +144,18 @@ "hash": "140e1bd963a0033e66777a3b2c5fe6e9c97dfe32" }, "org.gamecult.eve.unity-scene": { - "version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.49", + "version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.50", "depth": 0, "source": "git", "dependencies": { - "org.gamecult.cultlib": "1.0.13", + "org.gamecult.cultlib": "1.0.14", "org.gamecult.eve.plugin-fields": "0.2.3", "org.gamecult.eve.surface": "0.2.2", "com.unity.mathematics": "1.3.2", "com.unity.render-pipelines.universal": "17.4.0", "com.unity.modules.particlesystem": "1.0.0" }, - "hash": "e6ba1a36f6f0bce8df2c9834c25a8a980f03413c" + "hash": "7c8442e12264806a53a9e0e08b7b090dcddb8c90" }, "com.unity.modules.assetbundle": { "version": "1.0.0", diff --git a/Packages/manifest.json b/Packages/manifest.json index 574e650d1..bc9e905b9 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -21,7 +21,7 @@ "org.gamecult.aetheria.eve-runtime": "file:org.gamecult.aetheria.eve-runtime", "org.gamecult.aetheria.state": "file:org.gamecult.aetheria.state", "org.gamecult.cultmath": "file:../../CultMath", - "org.gamecult.cultlib": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.13", + "org.gamecult.cultlib": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.14", "org.gamecult.eve.surface": "file:../../EveUnity/packages/org.gamecult.eve.surface", "org.gamecult.eve.plugin-fields": "https://github.com/GameCult/EvePlugins.git?path=/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields#eve-plugin-fields-unity-v0.2.3", "org.gamecult.eve.unity-scene": "file:../../EveUnity/packages/org.gamecult.eve.unity-scene", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index 583d4eaf3..576c21a4d 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -311,11 +311,11 @@ } }, "org.gamecult.cultlib": { - "version": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.13", + "version": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.14", "depth": 0, "source": "git", "dependencies": {}, - "hash": "feb5c71513e71d681699f462fe3682b3168c6f73" + "hash": "4b7162022a8976f7941b5a7a69acf50f1b6d532b" }, "org.gamecult.cultmath": { "version": "file:../../CultMath", @@ -345,7 +345,7 @@ "depth": 0, "source": "local", "dependencies": { - "org.gamecult.cultlib": "1.0.13", + "org.gamecult.cultlib": "1.0.14", "org.gamecult.eve.plugin-fields": "0.2.3", "org.gamecult.eve.surface": "0.2.2", "com.unity.mathematics": "1.3.2", diff --git a/docs/aetheria-perfect-machine-map.md b/docs/aetheria-perfect-machine-map.md index e664abe05..5c02ad71f 100644 --- a/docs/aetheria-perfect-machine-map.md +++ b/docs/aetheria-perfect-machine-map.md @@ -2433,6 +2433,21 @@ predicate that still needs legacy DTO objects must earn that dependency by using behavior objects or simulation-only methods that typed facets do not yet expose. +The released-package proof keeps two lifecycle claims separate. The +`cold-start-lowering` profile begins with an empty cache, receives and verifies +the 46,412,384-byte provider body through `cultmesh.content.v1`, promotes the +exact hash with no partial, and proves generic world, field-volume, movement, +environment, and pilot/map camera lowering. The `full-session-gameplay` profile +starts a fresh warm daemon session, begins with no pickup, destroys the +deterministic salvage target, observes its canonical cargo drop, and collects +it exactly once from a persisted Ymir Begin fact. Witness runners use the +daemon's native 20 ms wall interval for its 20 ms simulation delta; download +latency is not allowed to redefine transient world lifetime. The managed +network content path is proven, while negotiated mapped/zero-copy body delivery +remains CultMesh work. The fog contract and provider shader execute, but the +current brown-black output is not visual parity with the fossil's blue gravity +sea. + Ymir restart ownership is deliberately private and asymmetric: - Owner: `AetheriaYmirPersistenceCoordinator` owns reconstruction durability; diff --git a/docs/original-game-migration-matrix.md b/docs/original-game-migration-matrix.md index a1d0133c3..c65c30b40 100644 --- a/docs/original-game-migration-matrix.md +++ b/docs/original-game-migration-matrix.md @@ -34,12 +34,12 @@ validation proves contract shape, not wiring, exclusivity, lowering, or parity. | Pilot camera | ARPG follow/dock cameras | Eve view semantics + runtime | camera rig and semantic view id | EveUnity camera rig | daemon dock state selects distinct contracts instead of collapsing both fossil cameras: undocked flight advertises the entity-forward `Third Person Rig` framing (distance 30, screen 0.64/0.19, FOV 60, lens 1-4096) and the shared `aim.presentation` convergence point as its look-at; Aetheria translates the fossil Cinemachine top-origin screen Y of `0.81` to Eve's bottom-origin viewport Y of `0.19`; EveUnity solves native pose while preserving both optical aim and advertised entity framing, without provider types; the retained dock projection remains separate | reproduce the dock camera's separate follow/look-at subjects, blend timeline, noise, and reconnect state | | Render channels | Unity layers/culling masks | provider surface policy + runtime asset variant | semantic channel exclusions | EveUnity native layer mapping | wired, exclusive, and lowered: the pilot surface excludes the semantic `map` channel; the Unity asset variant maps `map` to its authored native layer; EveUnity subtracts that layer from the configured camera mask; portable state contains no Unity layer or mask; the released warm witness proves the pilot camera excludes map glyphs while the map camera retains them | preserve the channel proof while world presentation and transport continue to evolve | | Minimap/tactical map | `ZoneRenderer`, map cameras | daemon world facts | explicit map projections | Unity and Electron | facts fragmented; generic lowerers absent | same state in both runtimes | -| Fields/fog/gravity | zone renderer and shaders | daemon/plugin semantics | Fields plugin documents | EveUnity fields lowerer | daemon publishes canonical gravity/fog splat layers through `field.volume3d`; Eve Fields `0.2.3` owns portable `PowerPulse` and `AnimatedRadialCosine` semantics; Aetheria emits the fossil global animated simplex/cellular/ambient stack, body-owned radial waves, and separate negative gameplay `gravity.height` and positive visual `fog.surface_height`; the field viewport matches the fossil splat cameras' 2000-by-2000 orthographic footprint while the larger 3000-scale brush parent remains brush coverage, not sampling extent; daemon entities follow fossil terrain height plus hull grid offset after Ymir XZ motion; released EveUnity `0.3.49` lowers the authored 2048/256/512 layer topology, provider shader ABI, pre-postprocess URP pass, authoritative flow time, explicit camera matrix, and float32 packed-output diagnostics without provider code. Translating the fossil camera's top-origin screen Y into Eve's bottom-origin convention places the camera above the field and restores a live fog horizon with the original `-36.17` noise amplitude; both camera-channel screenshots pass | restore the old blue tint, luminance, patch structure, gravity-wave readability, and surrounding world geometry; visual parity remains explicitly open | +| Fields/fog/gravity | zone renderer and shaders | daemon/plugin semantics | Fields plugin documents | EveUnity fields lowerer | daemon publishes canonical gravity/fog splat layers through `field.volume3d`; Eve Fields `0.2.3` owns portable `PowerPulse` and `AnimatedRadialCosine` semantics; Aetheria emits the fossil global animated simplex/cellular/ambient stack, body-owned radial waves, and separate negative gameplay `gravity.height` and positive visual `fog.surface_height`; the field viewport matches the fossil splat cameras' 2000-by-2000 orthographic footprint while the larger 3000-scale brush parent remains brush coverage, not sampling extent; daemon entities follow fossil terrain height plus hull grid offset after Ymir XZ motion; released EveUnity `0.3.50` lowers the authored 2048/256/512 layer topology, provider shader ABI, pre-postprocess URP pass, authoritative flow time, explicit camera matrix, and float32 packed-output diagnostics without provider code. Translating the fossil camera's top-origin screen Y into Eve's bottom-origin convention places the camera above the field and restores a live fog horizon with the original `-36.17` noise amplitude; both camera-channel screenshots pass | restore the old blue tint, luminance, patch structure, gravity-wave readability, and surrounding world geometry; visual parity remains explicitly open | | HUD/schematic | ARPG HUD and `SchematicDisplay` | Eve composition from daemon facts | semantic status/components | EveUnity UI | provider-authored transparent cockpit is wired, projected, and lowered through generic UI Toolkit panes, metrics, and progress components for hull, shield, capacitor, temperature, cargo, weapon cooldown/groups, selected target, target lock, target shield, and target hull; the original armor/equipment schematic and transient warning choreography remain reference-only | schematic topology, warning timelines, dynamic action state, and composited live capture | | Hit/lock/warnings | `ActionGameManager` feedback | daemon event facts | transient feedback stream | VFX/UI/audio | bounded deduplicated game-event ledger and Eve `feedback.stream` wired for pickup outcomes, projectile launch/impact, entity damage, alive-to-dead destruction, authoritative weapon reload chronology, and episode-deduplicated `weapon.fire.refused` facts for insufficient energy or missing ammunition; refusal identity, authored weapon, target, reason, and remaining magazine state are runtime-independent cockpit inputs | add lock transitions, thermal and docking event families, negative transaction fixtures, and runtime effect consumption | -| Assets | `Assets/Resources` | Aetheria provider | asset catalog + CultMesh CDN | runtime cache/load | provider manifests name deterministic bundle-internal paths; the authoring build derives presentation-only prefabs, strips missing and non-Eve `MonoBehaviour` components, verifies both saved prefabs and the loaded bundle, and publishes the immutable bundle through CultMesh; released-client warm-cache loading, content verification, and rendered provider identity are proven, while cold transfer still times out because the 46.1 MB body travels through batched snapshot records | mapped/network body transport followed by empty-cache download, atomic promotion, and cache reuse proof | +| Assets | `Assets/Resources` | Aetheria provider | asset catalog + CultMesh CDN | runtime cache/load | provider manifests name deterministic bundle-internal paths; the authoring build derives presentation-only prefabs, strips missing and non-Eve `MonoBehaviour` components, verifies both saved prefabs and the loaded bundle, and publishes the immutable bundle through CultMesh; the released cold profile starts empty, receives and verifies the 46,412,384-byte body through `cultmesh.content.v1`, atomically promotes the exact hash with no partial, and lowers rendered provider identity; the warm profile reuses the committed body. Negotiated mapped/zero-copy delivery remains unproven | negotiated mapped/network body selection and same-machine zero-copy proof | | Save/resume | original persistence paths | daemon/CultCache | published current state | clients rehydrate | owner-exists; not parity-proven | mid-loop restart | -| Terminus loop | original game composition | daemon/Ymir/Eve | pilot surface | Aetheria.Unity | live minimum-loop proof: generic Unity discovers the provider, lowers the pilot world/assets, single-steps dock and undock while paused, buys daemon-priced station stock, single-steps Ymir salvage collection, resumes, moves, targets, fires, and presents authoritative receipts/shot outcome | destruction-created loot pickup, richer trade content, docking transitions, and sustained combat encounters | +| Terminus loop | original game composition | daemon/Ymir/Eve | pilot surface | Aetheria.Unity | live minimum-loop proof: generic Unity discovers the provider, lowers the pilot world/assets, single-steps dock and undock while paused, buys daemon-priced station stock, single-steps Ymir salvage collection, resumes, moves, targets, fires, and presents authoritative receipts/shot outcome; the released full-session profile starts with no pickup, destroys a deterministic target, observes its canonical cargo drop, tractors it into a Ymir Begin contact, and proves exactly one `ymir-fact:` collection receipt plus cargo `0` to `1` | richer trade content, docking transitions, and sustained combat encounters | | Starbridge | original/shared architecture intent | one daemon session | pilot + commander surfaces | Unity + Electron | commander task board and autonomous explore execution wired; Electron Eve lowering and split-target proof missing | commander orders plus four pilots and autonomous workers | | Behavior engine | `ServerShared/Behaviors` composition | daemon | executable action/status projection | action bar and feedback | tick reconciles equipped catalog payloads into persistent behavior state; shared evaluated-stat query proven; execution families remain partial | every behavior family, ordering, resource transaction and modifier lifecycle | | Sensors/visibility | installed sensor sensitivity, decaying signature sources, and observer information thresholds | daemon | contacts and ping events | indicators/maps | passive reach derives from enabled installed Sensor behaviors with diminishing-return array composition regardless of entity kind; station-scale arrays are ordinary gear installed into larger hull-authored sensor hardpoints, with smaller same-type arrays remaining valid fallbacks; generation prefers the largest fitting footprint and contains no station/ship sensor-count branch; contact refresh no longer overwrites emitted visibility; docked craft consume one daemon-derived union of craft and dock-parent contacts through both Eve rows and SoA bodies, with sensor-source provenance; the old station range survives only as obsolete snapshot compatibility | prove shutdown, threshold decay, ping, classification timelines, and canonical catalog station-array data | @@ -151,12 +151,13 @@ These are source-confirmed ownership failures, not feature backlog: gameplay assemblies. EveUnity now publishes each committed SoA generation through a read-only presented-entity registry; richer selection and HUD adapters still need to consume it instead of rebuilding parallel indexes. -11. **Remote provider asset delivery remains unproven.** The authoring build now - derives deterministic presentation-only variants, strips missing and - non-Eve scripts, verifies the saved prefabs and loaded AssetBundle, and the - daemon advertises those bundle-internal paths. A clean EveUnity client must - still prove cold download, content verification, cache reuse, and rendered - identity without access to the authoring project. +11. **Remote provider asset delivery is proven through the managed content + session.** The authoring build derives deterministic presentation-only + variants, strips missing and non-Eve scripts, verifies the saved prefabs and + loaded AssetBundle, and the daemon advertises those bundle-internal paths. + A clean released EveUnity client downloads, verifies, atomically promotes, + reuses, and renders the provider body without access to the authoring + project. This does not prove the negotiated mapped/zero-copy representation. 12. **The negotiated local SoA fast path remains unproven.** The daemon publishes exact immutable generations; the external Unity client rejects stale or mismatched bodies and now resolves the same generation through the diff --git a/scripts/run-aetheria-unity.ps1 b/scripts/run-aetheria-unity.ps1 index dcefb9734..8daa0f2b5 100644 --- a/scripts/run-aetheria-unity.ps1 +++ b/scripts/run-aetheria-unity.ps1 @@ -54,7 +54,7 @@ $daemon = Start-Process dotnet -ArgumentList @( "--client-cultmesh-host", "127.0.0.1", "--client-cultmesh-advertise-host", "127.0.0.1", "--client-cultmesh-port", $Port, - "--tick-interval-ms", 250, + "--tick-interval-ms", 20, "--fixed-delta-ms", 20, "--no-odin-announcements" ) -PassThru -WindowStyle Hidden -RedirectStandardOutput $daemonLog -RedirectStandardError "$daemonLog.error" diff --git a/scripts/verify-aetheria-unity-client.ps1 b/scripts/verify-aetheria-unity-client.ps1 index 484befd27..f0517e730 100644 --- a/scripts/verify-aetheria-unity-client.ps1 +++ b/scripts/verify-aetheria-unity-client.ps1 @@ -14,14 +14,14 @@ $manifest = Get-Content (Join-Path $ProjectPath "Packages/manifest.json") -Raw | $lock = Get-Content (Join-Path $ProjectPath "Packages/packages-lock.json") -Raw | ConvertFrom-Json $expected = @{ "org.gamecult.cultlib" = @( - "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.13", - "feb5c71513e71d681699f462fe3682b3168c6f73") + "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.14", + "4b7162022a8976f7941b5a7a69acf50f1b6d532b") "org.gamecult.eve.surface" = @( "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.surface#eveunity-surface-v0.2.2", "140e1bd963a0033e66777a3b2c5fe6e9c97dfe32") "org.gamecult.eve.unity-scene" = @( - "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.32", - "817912a041ac1911e1e27a4b88617754d90ad4b7") + "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.50", + "7c8442e12264806a53a9e0e08b7b090dcddb8c90") } foreach ($packageName in $expected.Keys) { @@ -34,7 +34,7 @@ foreach ($packageName in $expected.Keys) { $cultLibPackage = Get-ChildItem (Join-Path $ProjectPath "Library/PackageCache") -Directory | Where-Object Name -Like "org.gamecult.cultlib@*" | - Where-Object { (Get-Content (Join-Path $_.FullName "package.json") -Raw | ConvertFrom-Json).version -eq "1.0.13" } | + Where-Object { (Get-Content (Join-Path $_.FullName "package.json") -Raw | ConvertFrom-Json).version -eq "1.0.14" } | Select-Object -First 1 if (-not $cultLibPackage) { throw "Resolved CultLib package is missing from Library/PackageCache." }