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.
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.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).
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.
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:
object_backend: dev-astra-v1 with capability [email protected]; the worker's host broker (service/asset_broker.py) posts to the DEV asset gateway blender-agent-astra (default preset astra-3h). Only the root process holds credentials; the CLI gets a Unix socket.palatial-blender-procedural-claude at exact commit cc70415834fd30e206336b08a8e35416e75ca2b4 (dependencies.json, .deps/asset-generator). It is never modified here.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.
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].
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.
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).