tools: per-strate density dispatch report in the fast tier (L132)

--density-dispatch-report prints each strate's bound path and tile shares. Owner world: SW native heightfield;
FI, TN, VS on compiled-analytic legacy fallback (FI lacks an imported FloatingIslandPlan; TN/VS have legacy recipes).
A native FI candidate broke the composed owner walk/shell gates, so the owner stays on its path. Output unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-31 02:40:58 +01:00
1 parent ebae71b142
commit 0065ee68e6
5 files changed
+277 -7

No files matched your search

@@ -0,0 +1,44 @@
#!/usr/bin/env python3
"""Create the isolated L132 owner snapshot with a native plan for existing FI strate 1."""
from __future__ import annotations
import json
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
SOURCE = ROOT / "Standalone/data/owner_world.json"
MANIFEST = ROOT / "Saved/Linux/l132/fixtures/owner-native-fi.world-assembly.json"
LAYOUT = ROOT / "Saved/Linux/l132/fixtures/owner-native-fi.resolved-layout.json"
OUTPUT = ROOT / "Saved/Linux/l132/fixtures/owner_world_native_fi.json"
def main() -> int:
owner = json.loads(SOURCE.read_text(encoding="utf-8"))
manifest_text = MANIFEST.read_text(encoding="utf-8").strip()
layout_text = LAYOUT.read_text(encoding="utf-8").strip()
manifest = json.loads(manifest_text)
layout = json.loads(layout_text)
islands = manifest.get("floating_islands", [])
native = [row for row in islands if row.get("strate_index") == 1]
resolved = [row for row in layout.get("strates", [])
if row.get("strate_index") == 1]
if len(native) != 1 or len(resolved) != 1:
raise SystemExit("native FI snapshot must contain exactly one strate-1 island plan/layout")
if (resolved[0].get("generator_kind") != "FloatingIslands"
or resolved[0].get("recipe_id") != "FloatingIslands.ClusterField"
or resolved[0].get("recipe_version") != 8):
raise SystemExit("resolved strate 1 is not FloatingIslands.ClusterField v8")
owner["world_assembly"] = manifest
owner["core_world_assembly_json"] = manifest_text
owner["resolved_layout_json"] = layout_text
OUTPUT.parent.mkdir(parents=True, exist_ok=True)
OUTPUT.write_text(json.dumps(owner, separators=(",", ":")) + "\n", encoding="utf-8")
print(f"[L132NativeFISnapshot] path={OUTPUT.relative_to(ROOT)} "
f"islands={len(native[0].get('manifest', {}).get('plan', {}).get('islands', []))} "
"strate=1 recipe=FloatingIslands.ClusterField/v8 status=PASS")
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,41 @@
# L132 — owner density dispatch
## Result
With Core enabled in the owner headless pipeline, the four strates bind to four paths. Unreal’s `bUseVoxelForgeCore` remains opt-in and defaults off. The fast-tier diagnostic reports the Core bindings at the four L80 owner poses and attributes hashed tiles by tile-center height within the resolved stratum bounds.
| Strate | Owner recipe | Bound path | Tile centers / share |
|---|---|---|---:|
| SW (0) | `SurfaceWorld.Heightfield2D` v2 | `SurfaceWorld-native` | 2,640 / 100% |
| FI (1) | `FloatingIslands.ClusterField` v0 | `compiled-analytic/FloatingIslands` | 2,128 / 100% |
| TN (2) | `legacy.TunnelNetwork` v0 | `compiled-analytic/TunnelNetwork` | 2,208 / 100% |
| VS (3) | `legacy.VerticalShafts` v0 | `compiled-analytic/VerticalShafts` | 1,392 / 100% |
SW has a matching strate/bounds `SurfaceWorld` plan, and its `Heightfield2D` evaluator is valid. FI has a legacy v0 layout record but no matching `FloatingIslandPlan`, so `FloatingIslandFieldV1` cannot bind. The Core owner manifest has zero island plans. TN and VS have legacy recipe IDs, not `Core.Caves.PrimitiveField` v1 or `Core.Lattice.PrimitiveField` v1. Their resolved layouts therefore lack the matching graph recipe and native-field capability. All three fall through to `FLegacyGeneratorFieldAdapter`.
The dispatch check is in the fast tier and can also be requested from the headless binary with `--density-dispatch-report`. It prints the per-strate bound adapter/path and hashed tile-center path shares. Its tile counts aggregate the four standard owner poses; tiles whose centers fall outside an interior interval are excluded, and a tile spanning a boundary is assigned by its center. Per-view logs are `Saved/Linux/l132/owner-density-dispatch-s*-clang.log`; the printed shares are in `Saved/Linux/l132/logs/verify-fast.log` and `Saved/Linux/l132/fast-summary.json`.
Across the 8,368 classified tile centers, path shares are 31.5% SurfaceWorld-native, 25.4% compiled-analytic/FloatingIslands, 26.4% compiled-analytic/TunnelNetwork, and 16.6% compiled-analytic/VerticalShafts.
## Native FI decision
The native evaluator is present. `BuildFloatingIslandStratumPlan` can convert the owner’s legacy island parameters to a v8 plan, but the owner’s imported manifest does not contain that plan. The existing automatic-plan branch is guarded by `bImportedOverride` inside the generated-assembly branch, so it does not fill this owner’s missing imported plan.
I built a candidate v8 plan for the existing owner FI strate without changing the default owner data. Its raw island-route audit passed: 29 route points, 78,336 capsule samples, zero blocked samples, zero unsupported probes, and zero grade failures. The composed owner audit did not pass:
- Existing compiled-analytic owner: all 3 passage interfaces pass; shell floor violations 0; ripple checks 3/3.
- Native FI candidate: only 2/3 interfaces pass; the added FI route is not walkable (1/2 strate routes walkable); shell floor violations 13; ripple checks 2/3.
- Passage tile seams passed for both bindings: 4 pairs, 4,900 shared samples, zero mismatches.
Native FI is a quality regression on the owner’s current passages, despite its standalone route plan passing. I did not switch the owner. The conditional captures, W8/W12 timing matrix, and Clang/GCC W1/W8/W12 matrix were not run because the candidate failed the composed walk/shell gate. No Core version or output baseline changed; the default owner output remains on its existing bindings. No Linux UE host build was run because there was no qualifying native change or timing matrix.
## TN/VS graph translation size
The active TN `GenerationParams` block has 47 fields; VS `VerticalShaftParams` has 11. Each also has 15 passage settings. Both have `CoreGeometry.GeneratorRecipe=0` and empty `Rooms`, `Tunnels`, and `Stamps` arrays. Native cave/lattice authoring requires at least one explicit room and one edge, with geometry, links, and route data. There is no adapter translating those legacy generator blocks into graph records. This is a substantial procedural migration, not a small recipe mapping, so I did not build it this round.
## Verification
- Fast tier: PASS, 304.0 s, 84 runs and 273 checks; includes four-pose dispatch output.
- Passage tile seams: compiled-analytic and native FI candidate both PASS at the FI owner pose.
- Owner walk/shell comparison: default PASS; native candidate FAIL as detailed above.
- Build stamp: `766b94ca7638475975b0345e5907eebb96158360c384f5d916c78eccbb1aa815`.
+73 -3
View File
@@ -70,6 +70,8 @@ namespace
bool HasRenderDistanceOverride=false;
int RenderDistanceOverride=0;
bool FloatingIslandsRecipe=false;
bool NativeOwnerFloatingIslandsRecipe=false;
bool DensityDispatchReport=false;
bool CavesRecipe=false;
bool LatticeRecipe=false;
int LatticeStrateIndex=-1;
@@ -1432,6 +1434,8 @@ namespace
" --core-snapshot=FILE (benchmark the exact resolved Core snapshot from Unreal)\n"
" --profile-column-overlap --far-horizon-lod8-step=N --force-generate\n"
" --seed=N --recipe=surface-world|floating-islands|caves|lattice\n"
" --native-owner-fi (build the existing owner FI plan; leave other strates intact)\n"
" --density-dispatch-report (print bound path per strate and tile hashes)\n"
" --lattice-strate=N (opt one Maze or VerticalShafts strate into Core.Lattice)\n"
" --landmark-chamber-demo (opt-in SW cavern room and swept tunnel)\n"
" --ore-veins-demo (opt-in material-only SW capsule veins)\n"
@@ -1490,6 +1494,9 @@ namespace
else if(arg=="--resolved-layout-only")options.ResolvedLayoutOnly=true;
else if(arg=="--audit-resolved-layout-boundaries")options.AuditResolvedLayoutBoundaries=true;
else if(arg=="--audit-resolved-layout-passages")options.AuditResolvedLayoutPassages=true;
else if(arg=="--native-owner-fi")options.NativeOwnerFloatingIslandsRecipe=true;
else if(arg=="--density-dispatch-report")
{options.DensityDispatchReport=true;options.StreamHash=true;options.StreamHashTiles=true;}
else if(arg=="--audit-landmark-reachability")options.AuditLandmarkReachability=true;
else if(arg=="--audit-native-caves")options.AuditNativeCaves=true;
else if(arg=="--audit-native-lattice")options.AuditNativeLattice=true;
@@ -1819,7 +1826,9 @@ int main(int argc,char** argv)
else if(!StandaloneWorldAssemblyPrototype::AttachRound1WorldAssemblyPrototype(
*ownerWorld,ownerJsonRoot,error,{},&worldAssembly))
{std::fprintf(stderr,"World assembler prototype setup failed: %s\n",error.c_str());return 2;}
if(!useExportedCorePlan&&options.FloatingIslandsRecipe
if(((!useExportedCorePlan&&options.FloatingIslandsRecipe)
||(options.NativeOwnerFloatingIslandsRecipe
&&worldAssembly.floatingIslands.empty()))
&&!StandaloneWorldAssemblyPrototype::AttachFloatingIslandWorldAssembly(
*ownerWorld,ownerJsonRoot,worldAssembly,error))
{std::fprintf(stderr,"Floating-island assembly setup failed: %s\n",error.c_str());return 2;}
@@ -1852,15 +1861,17 @@ int main(int argc,char** argv)
const std::string variant=options.LatticeRecipe
?"lattice/"+std::to_string(options.LatticeStrateIndex)
:options.CavesRecipe?"caves"
:options.FloatingIslandsRecipe?"floating-islands":"surface-world";
:(options.FloatingIslandsRecipe||options.NativeOwnerFloatingIslandsRecipe)
?"floating-islands":"surface-world";
const bool layoutResolved=useExportedCorePlan
&&!options.NativeOwnerFloatingIslandsRecipe
?StandaloneWorldAssemblyPrototype::ImportExportedResolvedLayout(
ownerJsonRoot,resolvedLayout,error)
:StandaloneWorldAssemblyPrototype::BuildResolvedLayoutSnapshot(
*ownerWorld,worldAssembly,variant,resolvedLayout,error);
if(!layoutResolved)
{std::fprintf(stderr,"Resolved-layout snapshot failed: %s\n",error.c_str());return 2;}
if(useExportedCorePlan
if(useExportedCorePlan&&!options.NativeOwnerFloatingIslandsRecipe
&&!StandaloneWorldAssemblyPrototype::ValidateExportedCorePlanMatchesOwner(
*ownerWorld,worldAssembly,resolvedLayout,error))
{std::fprintf(stderr,"Unreal-resolved Core plan/owner slot validation failed: %s\n",error.c_str());return 2;}
@@ -2113,6 +2124,65 @@ int main(int argc,char** argv)
controls.controlsRejectedAsExpected,controls.controlsRun,controls.passed?"PASS":"FAIL");
if(!controls.passed)
{for(const auto& failure:controls.failures)std::printf("[ResolvedLayoutValidatorControlFailure] %s %s\n",failure.code.c_str(),failure.detail.c_str());return 2;}
if(options.DensityDispatchReport)
{
const auto& slots=ownerWorld->Manager->GetLayout();
for(const auto& stratum:resolvedLayout.strates)
{
const auto slot=std::find_if(slots.begin(),slots.end(),[&](const auto& candidate)
{return candidate.StrateIndex==stratum.strateIndex;});
bool native=false;
std::string path,adapter;
if(slot!=slots.end()&&stratum.generatorKind=="SurfaceWorld")
{
const auto plan=std::find_if(worldAssembly.plan.strates.begin(),
worldAssembly.plan.strates.end(),[&](const auto& candidate)
{return candidate.strateIndex==stratum.strateIndex
&&candidate.bottomChunkZ==slot->BottomChunkZ
&&candidate.topChunkZ==slot->TopChunkZ;});
if(plan!=worldAssembly.plan.strates.end())
{
const VoxelForgeCore::Heightfield2D field(worldAssembly.recipe,*plan);
native=field.isValid();
}
if(native){path="SurfaceWorld-native";adapter="FSurfaceWorldFieldAdapter";}
}
else if(slot!=slots.end()&&stratum.generatorKind=="FloatingIslands")
{
const auto plan=std::find_if(worldAssembly.floatingIslands.begin(),
worldAssembly.floatingIslands.end(),[&](const auto& candidate)
{return candidate.strateIndex==stratum.strateIndex
&&candidate.bottomChunkZ==slot->BottomChunkZ
&&candidate.topChunkZ==slot->TopChunkZ;});
if(plan!=worldAssembly.floatingIslands.end())
{
const VoxelForgeCore::FloatingIslandFieldV1 field(
plan->manifest.recipe,plan->manifest.plan);
native=field.isValid();
}
if(native){path="FloatingIslands-native";adapter="FFloatingIslandFieldAdapter";}
}
else if(VoxelForgeCore::HasNativeGraphField(stratum)
&&(VoxelForgeCore::IsNativeCaveFieldStratum(stratum)
?stratum.passageCapabilities.hasNativeCaveField
:stratum.passageCapabilities.hasNativeLatticeField))
{
native=true;
path=VoxelForgeCore::IsNativeLatticeFieldStratum(stratum)
?"Lattice-native":"Caves-native";
adapter="FCavesFieldAdapter";
}
if(!native)
{
path=stratum.generatorKind=="SurfaceWorld"
?"SurfaceWorld-legacy":"compiled-analytic/"+stratum.generatorKind;
adapter="FLegacyGeneratorFieldAdapter";
}
std::printf("[DensityDispatch] strate=%d generator=%s recipe=%s version=%u bound_path=%s adapter=%s\n",
stratum.strateIndex,stratum.generatorKind.c_str(),stratum.recipeId.c_str(),
stratum.recipeVersion,path.c_str(),adapter.c_str());
}
}
if(!options.ResolvedLayoutOutputPath.empty())
std::printf("[ResolvedLayoutSnapshotOutput] path=%s\n",options.ResolvedLayoutOutputPath.c_str());
if(auto* root=std::get_if<VFJson::Value::Object>(&ownerJsonRoot.Data))
+115
View File
@@ -89,6 +89,9 @@ TILE_HASH_RE = re.compile(
r"^\[PipelineTileHash\] lod=(-?\d+) x=(-?\d+) y=(-?\d+) z=(-?\d+) "
r"density=(0x[0-9a-f]+) mesh=(0x[0-9a-f]+) "
r"payload=(0x[0-9a-f]+) topology=(0x[0-9a-f]+)$", re.M)
DENSITY_DISPATCH_RE = re.compile(
r"^\[DensityDispatch\] strate=(\d+) generator=([^ ]+) recipe=([^ ]+) "
r"version=(\d+) bound_path=([^ ]+) adapter=([^ ]+)$", re.M)
TILE_MATERIAL_HASH_RE = re.compile(
r"^\[PipelineTileMaterialHash\] lod=(-?\d+) x=(-?\d+) y=(-?\d+) z=(-?\d+) "
r"material=(0x[0-9a-f]+)$", re.M)
@@ -493,6 +496,117 @@ def run_new_owner_plan_stage(runner: VerificationRunner, binary: Path) -> None:
+ ", ".join(deferred_failures))
def run_density_dispatch_report(runner: VerificationRunner, binary: Path) -> None:
"""Report selected owner density paths and generated tile shares by path."""
cameras = {
0: (8.0, 16.0, -372.2626953125),
1: (25.8369140625, 3.19921875, -737.0),
2: (19.166015625, -14.2001953125, -753.3740234375),
3: (-20.0625, -5.068359375, -900.353515625),
}
aggregate: dict[int, dict[str, int]] = {}
bound_paths: dict[int, tuple[str, str, str, int, str]] = {}
failures: list[str] = []
for focus_strate, position in cameras.items():
name = f"owner-density-dispatch-s{focus_strate}-clang"
camera = "--camera=" + ",".join(
f"{value:.12f}" for value in (*position, 0.0, 0.0))
layout_path = OUT / "layouts" / f"{name}.json"
try:
row, output = runner.run_cpp(name, binary, OWNER_NEW, "surface-world",
["--density-dispatch-report", "--render-distance-chunks=0", camera],
expected_style=1, workers=8, max_level=8, clip_radius=3,
layout_path=layout_path)
except VerificationFailure as error:
failures.append(f"{name}: {error}")
continue
dispatch_rows = DENSITY_DISPATCH_RE.findall(output)
dispatch = {int(index): (path, generator, recipe, int(version), adapter)
for index, generator, recipe, version, path, adapter in dispatch_rows}
if len(dispatch_rows) != 4 or set(dispatch) != {0, 1, 2, 3}:
failures.append(f"{name}: expected four unique dispatch rows, got {dispatch_rows}")
continue
if not layout_path.is_file():
failures.append(f"{name}: resolved layout missing at {layout_path}")
continue
try:
layout = json.loads(layout_path.read_text(encoding="utf-8"))
strata = {int(value["strate_index"]): value for value in layout.get("strates", [])}
if set(strata) != {0, 1, 2, 3}:
raise ValueError(f"expected four strata, got {sorted(strata)}")
voxel_size_um = int(strata[0]["voxel_size_um"])
if voxel_size_um <= 0:
raise ValueError(f"invalid voxel_size_um={voxel_size_um}")
except (OSError, json.JSONDecodeError, KeyError, TypeError, ValueError) as error:
failures.append(f"{name}: cannot classify tiles from resolved layout: {error}")
continue
tile_rows = TILE_HASH_RE.findall(output)
camera_counts = {index: 0 for index in strata}
for lod_text, _x, _y, z_text, *_hashes in tile_rows:
lod, z = int(lod_text), int(z_text)
if lod < 0 or lod > 30:
failures.append(f"{name}: invalid tile lod={lod}")
continue
extent_voxels = 32 << lod
center_um = (z * extent_voxels + extent_voxels // 2) * voxel_size_um
matches = [index for index, stratum in strata.items()
if int(stratum["interior_bottom_um"]) <= center_um
< int(stratum["interior_top_um"])]
if len(matches) == 1:
index = matches[0]
camera_counts[index] += 1
aggregate.setdefault(index, {}).setdefault(dispatch[index][0], 0)
aggregate[index][dispatch[index][0]] += 1
if not tile_rows:
failures.append(f"{name}: --density-dispatch-report emitted no tile hashes")
observed = sum(camera_counts.values())
print(f"[DensityDispatchView] focus_strate={focus_strate} tiles={len(tile_rows)} "
f"classified_by_center={observed} status={'PASS' if observed else 'FAIL'}",
flush=True)
runner.require(f"{name}:dispatch-and-tile-counts",
observed > 0 and row["status"] == "PASS",
f"dispatch={dispatch} center_attributed_tiles={camera_counts} "
f"hashed_tiles={len(tile_rows)}")
for index, value in dispatch.items():
previous = bound_paths.get(index)
if previous is not None and previous != value:
failures.append(f"strate {index}: bound path changed between views: "
f"{previous} vs {value}")
bound_paths[index] = value
global_path_counts: dict[str, int] = {}
for index in range(4):
path, generator, recipe, version, adapter = bound_paths.get(
index, ("MISSING", "?", "?", 0, "?"))
path_counts = aggregate.get(index, {})
total = sum(path_counts.values())
for path_name, count in path_counts.items():
global_path_counts[path_name] = global_path_counts.get(path_name, 0) + count
details = ",".join(
f"{key}:{value}/{total} ({100.0 * value / max(1, total):.1f}%)"
for key, value in sorted(path_counts.items())) or "no tile centers observed"
print(f"[DensityDispatchStrate] strate={index} generator={generator} recipe={recipe} "
f"version={version} bound_path={path} adapter={adapter} "
f"tile_centers={total} path_shares={details}", flush=True)
if path == "MISSING" or total == 0:
failures.append(f"strate {index}: dispatch path or tile-center share missing")
else:
runner.require(f"owner-density-dispatch-strate-{index}", True,
f"bound_path={path} tile_center_path_shares={details}")
all_tiles = sum(global_path_counts.values())
for path_name, count in sorted(global_path_counts.items()):
share = 100.0 * count / max(1, all_tiles)
print(f"[DensityDispatchPathShare] path={path_name} tiles={count}/{all_tiles} "
f"share={share:.1f}%", flush=True)
if not all_tiles:
failures.append("no tile centers were attributed to any bound path")
runner.require("owner-density-dispatch-report", not failures,
"; ".join(failures) if failures else
"four owner poses reported per-strate bound paths and tile-center path shares")
def run_landmark_reachability(runner: VerificationRunner,
binaries: tuple[Path, ...]) -> None:
for binary in binaries:
@@ -3144,6 +3258,7 @@ def main() -> int:
except VerificationFailure as error:
new_plan_failure = str(error)
print(f"[{runner.tier}] new-owner-plan-stage FAIL {error}", flush=True)
run_density_dispatch_report(runner, CLANG)
run_landmark_reachability(runner, (CLANG,))
run_regression_controls(runner)
run_hash_pairs(runner, owners)