wip: Core.Liminal.Field v1 recipe, 4 seed-selected variants between fixed mouths (L144, fails mouth joins)
Plans and draws flat field+monolith, repeating hills, road over cloud floor and pillar grid in a 3-strata fixture, binding passage/0-1 and 1-2 as fixed endpoints. Composed W1 probes: 3/4 seeds fail one passage interface, 4/4 fail the liminal walk audit near the mouths (support itself passes). Stopped per AGENTS.md. Same mouth-ownership failure class as FI (L133/L140) and VS seed 2 (L139). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
No files matched your search
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Build the 3-strata composed Core.Liminal.Field fixture."""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[4]
|
||||
OWNER = Path(os.environ.get("VOXELFORGE_OWNER_DATA",
|
||||
ROOT / "Standalone/data/owner_world.json"))
|
||||
OUT_DEFAULT = Path(os.environ.get("VOXELFORGE_VERIFY_OUT", ROOT / "Saved/Linux/l144"))
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--out", type=Path, default=OUT_DEFAULT / "fixtures")
|
||||
args = parser.parse_args()
|
||||
args.out.mkdir(parents=True, exist_ok=True)
|
||||
world = json.loads(OWNER.read_text(encoding="utf-8"))
|
||||
if len(world.get("strates", [])) < 3:
|
||||
raise SystemExit("owner fixture needs at least three authored strate slots")
|
||||
|
||||
world["strates"] = world["strates"][:3]
|
||||
world["total_strates"] = 3
|
||||
world["settings_asset"]["TotalStrates"] = 3
|
||||
world["settings_asset"]["FixedStrates"] = world["settings_asset"]["FixedStrates"][:3]
|
||||
# Keep the resolved arrival near the departure depth. The owner's 5000-unit
|
||||
# reach clamps to liminal bedrock on most seeds and leaves no field floor.
|
||||
world["strates"][0]["passage_config"]["ReachMin"] = 1536
|
||||
world["strates"][0]["passage_config"]["ReachMax"] = 1792
|
||||
world["surface_profile_override"] = {
|
||||
"version": 1,
|
||||
"kind": "flatField",
|
||||
"minimum_arena_clearance_m": 0.0,
|
||||
}
|
||||
middle = world["strates"][1]
|
||||
middle["asset"]["GeneratorType"] = 4 # ECaveGeneratorType::SurfaceWorld
|
||||
middle["asset"]["StrateName"] = "Liminal Field"
|
||||
# Keep the departure mouth 24–32 m above liminal bedrock so every variant
|
||||
# has room for its floor, road landing and support footings.
|
||||
middle["passage_config"]["ReachMin"] = 192
|
||||
middle["passage_config"]["ReachMax"] = 256
|
||||
world["core_liminal_field"] = {
|
||||
"version": 1,
|
||||
"strate_index": int(middle["index"]),
|
||||
"variant_policy": "seed_modulo_4",
|
||||
}
|
||||
|
||||
output = args.out / "core-liminal-field-3-strata.json"
|
||||
output.write_text(json.dumps(world, separators=(",", ":")) + "\n", encoding="utf-8")
|
||||
print(f"[L144Fixture] path={output} strates=SurfaceWorld,Core.Liminal.Field,TunnelNetwork status=PASS")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,243 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Capture the four seed-selected Core.Liminal.Field v1 variants."""
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import math
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[4]
|
||||
HERE = Path(__file__).resolve().parent
|
||||
OUT = ROOT / "Saved/Linux/l144"
|
||||
CAPTURES = HERE / "captures"
|
||||
LIMIT = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--"]
|
||||
Q_PER_METRE = 1024.0
|
||||
|
||||
sys.path.insert(0, str(ROOT / "Standalone/Tools/verify"))
|
||||
from runner import bounded_run, current_stamp, first_stamp
|
||||
|
||||
|
||||
def fmt(values) -> str:
|
||||
return ",".join(f"{value:.6f}" for value in values)
|
||||
|
||||
|
||||
def sha256(path: Path) -> str:
|
||||
digest = hashlib.sha256()
|
||||
with path.open("rb") as stream:
|
||||
for block in iter(lambda: stream.read(1024 * 1024), b""):
|
||||
digest.update(block)
|
||||
return digest.hexdigest()
|
||||
|
||||
|
||||
def run_step(name: str, command: list[object], log: Path, env: dict[str, str],
|
||||
stamped: bool = False) -> str:
|
||||
expected_stamp = current_stamp() if stamped else None
|
||||
if stamped:
|
||||
binary = Path(str(command[0]))
|
||||
probe = bounded_run([str(binary), "--print-source-stamp"], timeout=15)
|
||||
if probe is None or probe.returncode != 0 \
|
||||
or first_stamp(probe.stdout or "") != expected_stamp:
|
||||
raise RuntimeError(f"{name} refused a stale executable: {binary}")
|
||||
started = time.monotonic()
|
||||
log.parent.mkdir(parents=True, exist_ok=True)
|
||||
with log.open("w", encoding="utf-8") as stream:
|
||||
result = subprocess.run([*LIMIT, "timeout", "1740s", *map(str, command)],
|
||||
cwd=ROOT, env=env, stdout=stream, stderr=subprocess.STDOUT,
|
||||
timeout=1745, check=False)
|
||||
output = log.read_text(encoding="utf-8", errors="replace")
|
||||
elapsed = time.monotonic() - started
|
||||
print(f"[L144Run] step={name} elapsed_s={elapsed:.3f} exit={result.returncode} log={log}",
|
||||
flush=True)
|
||||
if stamped and (first_stamp(output) != expected_stamp
|
||||
or current_stamp() != expected_stamp):
|
||||
raise RuntimeError(f"{name} source stamp mismatch; see {log}")
|
||||
if result.returncode != 0:
|
||||
raise RuntimeError(f"{name} exit={result.returncode}; see {log}")
|
||||
return output
|
||||
|
||||
|
||||
def camera_angles(camera, target):
|
||||
dx, dy, dz = (target[i] - camera[i] for i in range(3))
|
||||
return math.degrees(math.atan2(dx, dy)), math.degrees(
|
||||
math.atan2(dz, math.hypot(dx, dy)))
|
||||
|
||||
|
||||
def route_views(manifest_path: Path, layout_path: Path, name: str):
|
||||
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
|
||||
layout = json.loads(layout_path.read_text(encoding="utf-8"))
|
||||
plan = next(row for row in manifest["plan"]["strates"]
|
||||
if row["strate_index"] == 1 and row.get("liminal_field", {}).get("version") == 1)
|
||||
points = [tuple(value / Q_PER_METRE for value in row["position_q"])
|
||||
for row in plan["route"]]
|
||||
first, second = points[0], points[1]
|
||||
dx, dy = second[0] - first[0], second[1] - first[1]
|
||||
length = math.hypot(dx, dy)
|
||||
if length <= 1.0e-6:
|
||||
raise RuntimeError("Core.Liminal.Field arrival tangent is degenerate")
|
||||
tx, ty = dx / length, dy / length
|
||||
eye_camera = (first[0] - tx * 1.5, first[1] - ty * 1.5, first[2] + 1.6)
|
||||
third = points[min(2, len(points) - 1)]
|
||||
dx, dy = third[0] - first[0], third[1] - first[1]
|
||||
tangent_length = math.hypot(dx, dy)
|
||||
tx, ty = dx / tangent_length, dy / tangent_length
|
||||
dz_per_metre = (third[2] - first[2]) / tangent_length
|
||||
eye_target = (first[0] + tx * 40.0, first[1] + ty * 40.0,
|
||||
first[2] + dz_per_metre * 40.0 + 1.6)
|
||||
|
||||
middle = len(points) // 2
|
||||
before, center, after = points[middle - 1], points[middle], points[middle + 1]
|
||||
dx, dy = after[0] - before[0], after[1] - before[1]
|
||||
length = math.hypot(dx, dy)
|
||||
if length <= 1.0e-6:
|
||||
raise RuntimeError("Core.Liminal.Field wide-view tangent is degenerate")
|
||||
tx, ty = dx / length, dy / length
|
||||
nx, ny = -ty, tx
|
||||
floor = plan["liminal_field"]["floor_height_q"] / Q_PER_METRE
|
||||
if name == "flatField-monolith":
|
||||
monolith = next(row for row in layout.get("stamps", [])
|
||||
if row.get("stable_id") == "core/liminal-field/monolith/000")
|
||||
monolith_center = tuple(value / 1.0e6 for value in monolith["position_um"])
|
||||
floor = monolith_center[2] - monolith["half_extents_um"][2] / 1.0e6
|
||||
wide_camera = (monolith_center[0] - tx * 30.0 + nx * 18.0,
|
||||
monolith_center[1] - ty * 30.0 + ny * 18.0, floor + 25.0)
|
||||
wide_target = monolith_center
|
||||
elif name == "periodicHills":
|
||||
wide_camera = (center[0] - 20.0, center[1] - 25.0, floor + 10.0)
|
||||
wide_target = (center[0] + 10.0, center[1] + 8.0, floor + 1.0)
|
||||
elif name == "pillar-grid":
|
||||
pillars = [row for row in layout.get("stamps", [])
|
||||
if row.get("stable_id", "").startswith("core/liminal-field/pillars/")]
|
||||
if not pillars:
|
||||
raise RuntimeError("pillar-grid layout has no resolved grid stamps")
|
||||
pairs = []
|
||||
for i, first_pillar in enumerate(pillars):
|
||||
for second_pillar in pillars[i + 1:]:
|
||||
a = first_pillar["position_um"]
|
||||
b = second_pillar["position_um"]
|
||||
dx, dy = (b[0] - a[0]) / 1.0e6, (b[1] - a[1]) / 1.0e6
|
||||
separation = math.hypot(dx, dy)
|
||||
if 60.0 <= separation <= 90.0:
|
||||
mx = (a[0] + b[0]) / 2.0e6
|
||||
my = (a[1] + b[1]) / 2.0e6
|
||||
pairs.append((math.hypot(mx - center[0], my - center[1]),
|
||||
mx, my, dx / separation, dy / separation,
|
||||
(a[2] + b[2]) / 2.0e6,
|
||||
first_pillar["half_extents_um"][2] / 1.0e6))
|
||||
if not pairs:
|
||||
raise RuntimeError("pillar-grid has no neighboring resolved columns")
|
||||
_, mx, my, tx, ty, pillar_z, half_height = min(pairs)
|
||||
floor = pillar_z - half_height
|
||||
nx, ny = -ty, tx
|
||||
wide_camera = (center[0] - tx * 20.0 + nx * 25.0,
|
||||
center[1] - ty * 20.0 + ny * 25.0, center[2] + 8.0)
|
||||
wide_target = (center[0], center[1], floor + 2.0)
|
||||
else:
|
||||
wide_camera = (center[0] - tx * 20.0 + nx * 25.0,
|
||||
center[1] - ty * 20.0 + ny * 25.0, center[2] + 8.0)
|
||||
wide_target = (center[0], center[1], floor + 2.0)
|
||||
return {"eye": (eye_camera, eye_target), "wide": (wide_camera, wide_target)}
|
||||
|
||||
|
||||
def capture_variant(seed: int, name: str, *, headless: Path, renderer: Path,
|
||||
fixture: Path, env: dict[str, str]):
|
||||
stem = f"core-liminal-{name}-seed{seed:02d}"
|
||||
plan_dir = OUT / "capture-plans" / stem
|
||||
plan_dir.mkdir(parents=True, exist_ok=True)
|
||||
manifest = plan_dir / "manifest.json"
|
||||
layout = plan_dir / "layout.json"
|
||||
command = [headless, fixture, "--workers=1", f"--seed={seed}",
|
||||
"--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline",
|
||||
"--force-generate", "--clip-radius=1", "--max-clip-level=0", "--max-level=0",
|
||||
"--render-distance-chunks=0", "--camera=0,0,-540,0,0",
|
||||
f"--world-assembler-manifest-output={manifest}",
|
||||
f"--resolved-layout-output={layout}"]
|
||||
output = run_step(f"plan-{stem}", command, OUT / "logs" / f"capture-{stem}-plan.log",
|
||||
env, stamped=True)
|
||||
if "[CoreLiminalFieldDraw]" not in output:
|
||||
raise RuntimeError(f"{stem} plan omitted its Core liminal deck")
|
||||
views = route_views(manifest, layout, name)
|
||||
for view, (eye, target) in views.items():
|
||||
work = OUT / "captures" / f"{stem}-{view}"
|
||||
work.mkdir(parents=True, exist_ok=True)
|
||||
view_manifest = work / "manifest.json"
|
||||
view_layout = work / "layout.json"
|
||||
mesh = work / "world.vfmesh"
|
||||
yaw, pitch = camera_angles(eye, target)
|
||||
camera = (*eye, yaw, pitch)
|
||||
view_clip_radius = (5 if view == "wide" and name in {
|
||||
"flatField-monolith", "periodicHills"} else
|
||||
3)
|
||||
command = [headless, fixture, "--workers=12", f"--seed={seed}",
|
||||
"--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline",
|
||||
"--force-generate", f"--clip-radius={view_clip_radius}",
|
||||
"--max-clip-level=0", "--max-level=0",
|
||||
"--render-distance-chunks=0", "--capture-skip-walkability",
|
||||
f"--camera={fmt(camera)}", f"--mesh-export={mesh}",
|
||||
f"--world-assembler-manifest-output={view_manifest}",
|
||||
f"--resolved-layout-output={view_layout}"]
|
||||
output = run_step(f"export-{stem}-{view}", command,
|
||||
OUT / "logs" / f"capture-{stem}-{view}-export.log", env, stamped=True)
|
||||
if "[CoreLiminalFieldDraw]" not in output or not mesh.is_file() \
|
||||
or mesh.stat().st_size == 0:
|
||||
raise RuntimeError(f"{stem}-{view} export omitted its Core liminal deck or mesh")
|
||||
png = work / f"{view}.png"
|
||||
image = CAPTURES / f"{stem}-{view}.jpg"
|
||||
fog = {
|
||||
"flatField-monolith": (30, 180, "0.66,0.73,0.77", -708.0, 46.0),
|
||||
"periodicHills": (140, 850, "0.78,0.84,0.88", -720.0, 14.0),
|
||||
"road-over-cloud-floor": (24, 420, "0.88,0.93,0.95", -720.0, 65.0),
|
||||
"pillar-grid": (180, 1200, "0.82,0.88,0.91", -720.0, 80.0),
|
||||
}[name]
|
||||
fog_start, fog_end, fog_color, height_center, height_range = fog
|
||||
render = [renderer, mesh, png, "--size=1600x900", "--fov-deg=72",
|
||||
f"--camera-m={fmt(eye)}", f"--yaw-deg={yaw:.6f}", f"--pitch-deg={pitch:.6f}",
|
||||
"--tile-skirts=on", "--shade=readable", "--headlamp=off", "--height-tint=on",
|
||||
f"--height-center-m={height_center:.6f}", f"--height-range-m={height_range:.6f}",
|
||||
"--light-direction=-0.42,-0.58,0.70", "--fog=on", f"--fog-start-m={fog_start}",
|
||||
f"--fog-end-m={fog_end}", f"--fog-color={fog_color}"]
|
||||
run_step(f"render-{stem}-{view}", render,
|
||||
OUT / "logs" / f"capture-{stem}-{view}-render.log", env, stamped=True)
|
||||
run_step(f"jpeg-{stem}-{view}", ["ffmpeg", "-nostdin", "-hide_banner", "-loglevel",
|
||||
"error", "-y", "-i", png, "-frames:v", "1", "-q:v", "4", image],
|
||||
OUT / "logs" / f"capture-{stem}-{view}-jpeg.log", env)
|
||||
run_step(f"quality-{stem}-{view}", [sys.executable,
|
||||
ROOT / "Standalone/Tools/verify/capture_quality.py", image],
|
||||
OUT / "logs" / f"capture-{stem}-{view}-quality.log", env)
|
||||
print(f"[L144Capture] variant={name} seed={seed} view={view} "
|
||||
f"eye_height={'1.600m' if view == 'eye' else 'wide'} bytes={image.stat().st_size} "
|
||||
f"sha256={sha256(image)} status=PASS", flush=True)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
headless = ROOT / "Standalone/bin/linux/VoxelForgeCoreHeadless-clang19"
|
||||
renderer = ROOT / "Standalone/bin/linux/VoxelForgeOffscreenCapture-clang19"
|
||||
fixture = OUT / "fixtures/core-liminal-field-3-strata.json"
|
||||
env = os.environ.copy()
|
||||
env["VOXELFORGE_VERIFY_OUT"] = str(OUT)
|
||||
env["VOXELFORGE_OWNER_DATA"] = str(ROOT / "Standalone/data/owner_world.json")
|
||||
env["LP_NUM_THREADS"] = "12"
|
||||
env["XDG_CACHE_HOME"] = str(OUT / "xdg-cache")
|
||||
CAPTURES.mkdir(parents=True, exist_ok=True)
|
||||
variants = ("flatField-monolith", "periodicHills",
|
||||
"road-over-cloud-floor", "pillar-grid")
|
||||
selected = set(os.environ.get("L144_CAPTURE_VARIANTS", "").split(","))
|
||||
for seed, name in enumerate(variants):
|
||||
if selected and name not in selected:
|
||||
continue
|
||||
capture_variant(seed, name, headless=headless, renderer=renderer,
|
||||
fixture=fixture, env=env)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
raise SystemExit(main())
|
||||
except Exception as error:
|
||||
print(f"[L144Capture] status=FAIL error={error}", file=sys.stderr, flush=True)
|
||||
raise SystemExit(1)
|
||||
@@ -0,0 +1,44 @@
|
||||
# Linux144 — Core.Liminal.Field v1
|
||||
|
||||
| Variant (seed) | Arrival at eye height | Wide view |
|
||||
|---|---|---|
|
||||
| Flat field + monolith (0) |  |  |
|
||||
| Repeating hills (1) |  |  |
|
||||
| Road over cloud floor (2) |  |  |
|
||||
| Pillar grid (3) |  |  |
|
||||
|
||||
**Result: stopped at the mouth-join gate; this is not ready to ship.** The new `Core.Liminal.Field` v1 recipe plans and draws all four seed-selected looks between fixed mouths. In the final composed probe, three of four seeds failed one of their two passage interfaces, and all four failed the liminal walk audit. The requested eight-seed-per-variant matrix was not run after the stop condition was reached.
|
||||
|
||||
## What changed
|
||||
|
||||
- Added one data-driven recipe, `Core.Liminal.Field` v1. `seed % 4` selects flat field with monolith, repeating hills, road over cloud floor, or pillar grid.
|
||||
- The liminal plan binds the existing `passage/0-1/0` arrival and `passage/1-2/0` departure as fixed endpoints. It draws an 8-point route deck and structural supports; the road variant uses that deck as its route. The pillar variant resolved 221 grid pillars after route clearance.
|
||||
- Added a three-strata fixture: Surface World → liminal → Tunnel Network. `BuildL144Fixtures.py` and `CaptureL144.py` reproduce the fixture and the eight captures.
|
||||
|
||||
## Composed probe
|
||||
|
||||
The final composed audit window was one run for each seed 0–3 at W1, using Clang 19 source stamp `8acbb7c3dfdb0484100d3d55036db20743ce76d74097b69362bb7d1a1c1d6302`. These are audit counts, not timing comparisons.
|
||||
|
||||
| Variant | Passage interfaces passed | Liminal walk audit | Passage shell / seam audit | Liminal negative control |
|
||||
|---|---:|---|---|---|
|
||||
| Flat field + monolith, seed 0 | 1/2 — FAIL | 222 blocked samples, 7 grade failures — FAIL | PASS | altered departure rejected — PASS |
|
||||
| Repeating hills, seed 1 | 2/2; composed summary FAIL | 1 blocked sample — FAIL | PASS | altered departure rejected — PASS |
|
||||
| Road over cloud floor, seed 2 | 1/2 — FAIL | 3 blocked samples — FAIL | FAIL, 1 floor violation | altered departure rejected — PASS |
|
||||
| Pillar grid, seed 3 | 1/2 — FAIL | 289 blocked samples, 9 grade failures — FAIL | PASS | altered departure rejected — PASS |
|
||||
|
||||
The three partial passage-interface failures reached the requested stop threshold. Every liminal walk probe reported zero unsupported samples and zero structural-support failures; support alone therefore does not explain the blocked routes. The top Surface World route audit passed all four seeds. Passage naturalness and mouth-profile negative controls also detected their injected faults in all four logs.
|
||||
|
||||
## Captures and limits
|
||||
|
||||
All eight 1600×900 images passed `capture_quality.py`. Arrival cameras are 1.6 m above the fixed arrival mouth and look along the route. Capture exports used `--capture-skip-walkability` to preserve render evidence despite the failing composed audits; this flag was not used for the audit runs. The wide pillar view shows the overhead deck and one support rather than a legible field of grid columns, and the other images also expose the current route/deck defects.
|
||||
|
||||
No additional geometry change was attempted after the three-interface-failure threshold. Earlier diagnostics found the short terminal secant exaggerated the mouth grade; widening the tangent probe interval did not make the final composed walk pass. It remains unproven which combination of terminal connector geometry and nearby field solids accounts for the blocked capsule samples.
|
||||
|
||||
## Checks
|
||||
|
||||
- Clang 19 headless build completed; the final audit and capture executables report the source stamp above.
|
||||
- Four composed probes ran at W1, one seed per variant. Planning/drawing and the per-audit results are in `Saved/Linux/l144/logs/probe8-seed00.log` through `probe8-seed03.log`.
|
||||
- Eight capture quality checks passed. `git diff --check` passed.
|
||||
- Not run after the stop gate: eight seeds per variant, GCC or W8/W12 determinism, owner canonical-hash comparison, fast tier, and one near-ready run. No performance timing window was collected.
|
||||
|
||||
Changed Unreal `Source/` files: none. Changed standalone sources include `StreamBenchmarkHeadless.cpp`, `StreamBenchmarkPipeline.h`, and `WorldAssemblyPrototype.h`.
|
||||
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 30 KiB |