Operating and extension guide for the Palatial scene director (PalatialSim/palatial-scene-gen-agent) and its hosted DEV wiring through Agent Lab. Written 2026-09-09 against scene dev at 11d6324 (deployed Modal app v22), the skills-reconciliation worktree at 168a906 (not yet merged) and Agent Lab dev at 012e770. Updated the same day after DEV release 2: scene dev at d762f19 (merges 75e74ef, d762f19; Modal app v24, image im-m7kgVvhGsA6J7OJwFG4EC7), eleven skills merged, Agent Lab dev at 10251b9 (Worker version 14434798-561c-4ea9-8ab4-d9e16b9ef88c). Unverified points are listed at the end.

1. Architecture of the scene director

One director, capabilities instead of phases

The runtime is one persistent model agent (src/palatial_scene_gen/model_agent.py, ModelSceneAgent) driven by the durable engine in engine.py and launched by the scene-run CLI (run_cli.py). There are no phase, room-role or acceptance enums: the director chooses work from observed needs and ends each advance with one submit_scene_agent_result (checkpoint, delivered, needs_input, blocked, failed). The caller's GOAL.md is the sole instruction source; plans, images, filenames, checkpoints and tool output are data. docs/scene-quality-contract.md fixes the design: one flexible director, an advisory critic that cannot veto, the pinned 3D builder untouched, paid work reconciled rather than replayed.

Intake and normalization

intake.py inventories an input folder from filesystem and image-header facts; normalize.py copies exact bytes, re-verifies digests and derives bounded evidence (PDF page renders, previews of oversized images, requested video frames via --prepare-videos). Admitted inputs include plans, photos, PDFs, .blend, .glb, videos, point clouds (PLY, PCD, E57, LAS/LAZ, XYZ, PTS) and Gaussian splats (3DGS PLY, SPLAT, SPZ, KSPLAT). A PLY is classified by its vertex header (f_dc_*, opacity, scale_*, rot_*), never by suffix (geometry_import.ply_semantics).

Planning and references

publish_scene_plan and revise_scene_plan (production_actions.py) bind the governing plan to GOAL and evidence digests; planning.py fans out evidence analysis and one synthesis pass. create_scene_reference_board (reference_board_tool.py, gpt-image-2) generates an optional appearance target that informs materials and construction language but never overrides measured layout or counts as render evidence.

Delegation to the independent 3D builder

Substantial standalone assets go to the builder through director-authored briefs: object_component.py compiles each frozen asset design into the object GOAL.md the unchanged pipeline expects, including a "Construction and review expectations" section (≈1.2k characters). Two paths:

The director owns architecture, layout, integration, lights, cameras, scene-level scatter and small repairs. A failed builder is recovered as an unapproved working copy (stage_failed_scene_asset), not replayed.

Assembly in a live Blender session

blender_runtime.SceneBlenderRuntime wraps the pinned runtime with cancellation that retires the owned Blender process and never replays. execute_blender_code runs inline code or a workspace file (absolute __file__, __name__ == "__main__"); both mutate the live session. candidate_execution.py adds protected runs: back up the live scene to live-before.blend, open a staged copy of a registered source, verify named targets, save, reopen, publish, report live_session_now; revert_to_incumbent reopens the backup. import_scene_geometry uses pinned KIRI 3DGS Render 5.1.0 and Point Cloud I/O 0.5.2, converting SPLAT/SPZ/KSPLAT with [email protected].

Observation and measurement

visual_inspection.py and scene_measure.py provide read-only primitives: render_view, crop_image (native pixels), inspect_objects, measure, check_facing, ground_contact, audit_materials, audit_geometry, inspect_scene_visuals (whole, detail and neglected-region views of a saved candidate with pixel-to-object mapping and overlap probes) and compare_scene_candidates (byte identity, changed-pixel fraction and region, object deltas, camera and renderer fingerprints). Reports are complete or paged and persisted as scene_observation artifacts. input_images.py presents user inputs at the reading provider's documented maximum (PROVIDER_IMAGE_LIMITS) with native-resolution tiles for larger originals; the dependency's 1024-pixel downscale is never used, and crop_scene_evidence crops originals natively.

Advisory critic

critic_tool.py is read-only, with no score, verdict or mutation tools. It receives the GOAL/plan lineage and host-registered images by ID, can inspect the saved candidate natively, separates the whole-scene target gap from relative improvement, and returns ranked causal findings with expected observable results and uncertainty. QUALITY_LOOP_PROMPT requires whole-scene, grouping, close-up, reverse-angle and neglected-region views before judging. Depth is unbounded: MAX_VISUALS_PER_REVIEW (64) is a context split and ITERATION_RUNAWAY_GUARD (200) a defect guard; reports persist as paged history (scene_critic_history/, read_scene_critiques).