--- name: interactive-component-authoring description: > Build or repair a reusable scene component through a live LunCoSim Editor session. Use when the work must be decomposed into small component tasks, checked visually after each task, and verified with typed USD queries and Rhai tests. This is the normal cycle for assemblies; do not use a whole vehicle batch as the editing unit. --- # Interactive component authoring cycle This is the repository's agreed editing rule for realistic assemblies. The simulator is an interactive workbench, not a batch USDA generator. Keep the headful production session open, edit one component at a time, inspect what the user can see, and stop at every checkpoint that can change the design. Use this skill with [`edit-usd-assembly`](../edit-usd-assembly/SKILL.md) for the Editor lifecycle and [`assembly-quality`](../assembly-quality/SKILL.md) for dimensions, frames, collision and visual gates. For a new reusable asset also read [`author-usd-component`](../author-usd-component/SKILL.md). For a mission or operations-facing model, read the tailored [mission and engineering quality gates](references/mission-engineering-quality.md) before choosing component boundaries or fidelity. It adds ConOps, interface, fault, verification/validation, deterministic replay, and configuration baseline checks without introducing a vehicle-specific workflow. ## The mandatory cycle Keep one production Editor session open for the assembly and use **Editor Perspective** for every authoring checkpoint. The unit of progress is one component task, not a vehicle-wide script. After each task, stop and inspect the live projection; do not begin the next component until the typed readback and the Rhai gate agree with what is visible. This is the short interactive loop the agent must run itself, even when the user is not watching the terminal: For each component, in order: ```text discover the exact USD document, preview, view, edit target and generation -> define the component contract and its local datum in SI metres -> build one pure Rhai plan using typed USD operations -> review and commit that one component change -> wait for projection_ready and the matching projected generation -> query the authored/composed prims, bounds, relationships and schemas -> inspect the focused Editor view and capture a project-local screenshot -> run the component's source-backed Rhai requirement gate -> show the checkpoint / collect feedback before the next component -> save only after the visual and typed gates agree ``` If a component is wrong, change only that component (or its explicit mount contract), re-project it in the same session, and repeat the checkpoint. Do not accumulate several speculative edits and then ask for a final review. When a task genuinely needs multiple dependent parts, make the dependency boundary explicit (for example, a wheel and its strut), run the local gate, then continue with the next separately named task. Do not queue a bus, tanks, legs, engines, ramps and panels into one unobserved call. A component task may contain the minimum atomic operations needed for that component (for example a wheel plus its strut and mount), but it must produce its own projection, typed evidence and Rhai verdict. Then run an assembly integration gate that checks placement, symmetry, clearances, references, joints and cross-component wiring; an isolated component pass does not prove its mounting. ## Unified editing substrate and format adapters All editable artifacts use the same lower contract in `lunco-doc` and `lunco-doc-bevy`: a stable `DocumentId`, monotonically increasing generation, typed reversible `DocumentOp`, an atomic grouped-apply boundary, optimistic parent-generation checking, journal provenance, lifecycle notifications, and generic undo/redo/save/fork/close verbs. This substrate is the source of shared Editor behaviour; a format must not grow a private history stack, active-tab fallback, or second document identity. Each format adapter implements only what is format-specific: | Format | Adapter owns | Rhai facade owns | |---|---|---| | USD | OpenUSD composition, EditTarget/layer opinions, typed ops, projection and viewport readiness | target resolution, dry plans, proposal/review, component workflow, visual checkpoint | | Modelica | source/AST/diagram lowering, parse scheduling, compile state and runtime projection | operation constructors, generation cursor, compile checkpoint, model/diagram UX | | SysML/KerML | UTF-8 source ranges, parser/resolver snapshot and source-set validation | source edit plans, requirement/verification policy, traceability checkpoint | | Rhai | script document source, UTF-8 edits and hook lifecycle | authored scenario/tool policy and test verdicts | | Shaders/other text domains | existing parser/compiler and resource owner (WGSL currently `CreateShader`/`ImportShader`) | add a source-edit facade only after a document adapter; never write shader files from a generic tool | The dynamic tool boundary is `assets/scripting/tools/*.rhai`. A tool is discoverable and hot-reloadable by name; it may call only the public `cmd` / `query` surface and reusable prelude helpers. New format support should add a small adapter plus a Rhai facade, not a vehicle-specific Rust builder or a copy of the USD/Modelica history machinery. `authoring_session` is the common facade for capability discovery, dry planning, grouped apply, checkpoint, undo and redo. Every adapter must expose the same interaction invariants: 1. **Inspect first:** return document identity, origin, edit target (when applicable), generation/source revision, dirty/read-only state and diagnostics. 2. **Plan before mutate:** validate the complete operation list in Rhai and return a deterministic summary. A dry plan never calls `cmd`. 3. **One intent, one group:** submit the reviewed list through the owner's atomic grouped operation. The owner rejects stale generations, invalid ranges/paths, read-only origins and unsupported schemas with a structured error. 4. **Verify the owner projection:** wait for the matching generation and use the format's typed readback (USD composed stage, Modelica parse/compile, SysML semantic snapshot). A screenshot is an additional visual checkpoint, never the source of truth. 5. **Recover explicitly:** `undo`/`redo` target the same document id; save is a separate approval. There is no implicit active document, alternate writer, silent retry, or fallback format. For Editor UX, keep a single session visible while this cycle runs. The user should see the dry operation count and affected identities, then one coherent change, the projection result, diagnostics and the undo affordance. Selection, camera and view state are presentation state and must survive a source edit; they are never encoded as an extra authored operation. ## Source and requirements gate before geometry Before opening an Editor document for a component, perform a short written analysis and keep it next to the Twin source. The analysis is part of the component contract, not an informal design note. For every component record: 1. the public/reference source (URL, paper, drawing, supplied image, or an explicitly labelled Twin study assumption), access date, and the exact fact extracted from it; 2. the subcomponents and ownership boundary (for example ramp deck, hinge, actuator, latch; or wheel, hub, knuckle, arm and strut), including which parts remain inside this file and which become detached referenced assets; 3. the local Y-up/SI-metre frame, mount datum/socket, handedness, envelope and all dimensional parameters needed to build it; 4. the required USD topology/types, standard schemas, collision and mass/inertia owner, material/purpose policy, and any articulation/limit; 5. a source-backed SysML requirement for each observable fact, with a `source`, `rationale`, `units`, and `verification` relationship; and 6. the Rhai checks that will prove the fact from composed USD (including missing-source, wrong-type, wrong-unit, boundary and reference-identity cases). Use a separate `requirements/_requirements.sysml` and `scenarios/tests/_requirements.rhai` for every independently reusable or articulated component. The SysML file is the single source of truth for names, dimensions, limits and provenance; the Rhai test loads it via `sysml_requirements::source()` and must not repeat numeric literals. Keep the test fixture and component asset detached from the parent assembly so either can be opened and verified independently. The parent assembly gets a separate integration requirement file that checks only instance placement, symmetry, clearance, joints, and cross-component wiring. Do not start detailed geometry when the source or datum is unresolved. Record the uncertainty as a failing requirement or an explicitly named study assumption and stop at that component checkpoint; do not silently invent a fallback dimension. This produces an auditable chain: ```text source evidence -> SysML requirement -> Rhai composed-stage check -> detached USD component -> assembly integration check ``` ## Five-phase delivery workflow Apply this order to every mission, vehicle, habitat, payload, or other model; it is not tied to a particular Twin: 1. **Analyse the implementation seam.** Identify what belongs in the Twin's USD files (identity, topology, geometry, references and transforms), what belongs in Rhai (scenario policy, requirement observation and reports), what belongs in Modelica (continuous equations and parameters), and what generic capability is genuinely missing from Rust (typed document operation, projection, physics or solver seam). Do not put Twin names or requirements into simulation-core Rust. 2. **Split by ownership.** Decompose the root into detached, independently openable components. A component may contain its local subcomponents when they share one datum/body and no independent lifecycle; otherwise give the subcomponent its own USD asset, SysML contract and Rhai gate. The assembly composes references and owns placement, joints and cross-component links. 3. **Find and record specification.** Gather public drawings, papers, product pages, supplied images or measured study assumptions. For each requirement record source URI/title, access date, extracted fact, rationale for including it, confidence/status (`reference`, `derived`, or `study-assumption`), and the SI-unit conversion. Unresolved facts are visible failing requirements, never silent defaults. 4. **Build through the existing tools.** Author or edit one component in the headful Editor with `assembly_edit`, `assembly_builder`, component and measurement facades. Use a pure Rhai plan and typed USD operations; let the document owner maintain ordered transforms, schemas and composition. If a needed standard operation is absent, stop with a loud Rust capability-gap report and add only the smallest generic feature. 5. **Verify and iterate.** Run the component's source-backed Rhai gate, then the parent assembly gate, then the whole mission/vehicle suite. Check topology, dimensions, units, frames, references, joints, collision/mass, limits, determinism and visual evidence. Repeat the one-component cycle for every failing checkpoint until all required verdicts are green; only then save/publish and record the exact evidence. The required handoff is therefore an auditable set of artifacts, not just a final screenshot: an analysis/source record, one SysML contract and Rhai gate per detached component, the USD component files, an assembly contract/gate, and a whole-system test report. ## Decompose by ownership Start with the root datum and contract, then use a dependency order that keeps each checkpoint understandable: 1. chassis/body datum and envelope; 2. one repeated or articulated component (one leg, wheel, tank, nozzle, ramp, or panel) and its local interfaces; 3. the remaining instances through explicit references, patterns or mirrors; 4. joints, sockets, collision and mass ownership; 5. presentation details and materials; 6. the composed assembly and mission-facing runtime behavior. The component owns local geometry, material targets, collision envelope, mass and named attachment frames. The assembly owns references, placement, instance overrides, symmetry, host-facing joints and cross-component links. SysML owns the requirement intent, Modelica owns continuous equations, Rhai owns observation/policy, and Rust owns only generic typed substrate. Never create a vehicle-specific Rust builder or a second scene graph to make a checkpoint convenient. ## Practices adapted from established DCC/CAE tools These are workflow principles, not a request to import a private CAD file or to copy another tool's scene model: | Reference practice | LunCoSim rule | |---|---| | Blender separates Object transforms from Edit Mode geometry; unapplied scale can make downstream dimensions ambiguous. | Establish the component datum, apply/normalize transforms through the typed Editor operation, then measure the composed result. Never hide a scale error in a child translation. | | FreeCAD Part Design uses a Body, local coordinate system, datum geometry and an ordered feature history. | Give each reusable component one root, one local frame, explicit mount datums and a reviewable Rhai plan. Keep operations incremental and named rather than a flattened mesh dump. | | Fusion 360 treats a Component as the unit with its own origin, coordinate system, timeline, joints and parts-list identity; external components are referenced into assemblies. | Keep independently reusable parts in separate Twin assets and compose them by typed USD references and named sockets. Preserve source identity and edit the assembly's placement, not a flattened copy. | | SOLIDWORKS recommends mating to one or two common references, avoiding loops/redundant mates, fixing errors early and solving detail in subassemblies. | Anchor components to explicit assembly datums/sockets, avoid duplicate constraints, fail immediately on ambiguous frames, and verify each subassembly before the top-level assembly. | | COMSOL keeps a geometry sequence and named selections so later physics/material/mesh nodes remain associated after geometry changes. | Use stable USD paths, named frames, sockets, collections and standard schemas as the selection/association boundary. Requirement checks must query those identities, not leaf-name guesses or screenshot pixels. | | OpenUSD composes encapsulated assets through references, payloads and variants, and evaluates transforms through the ordered xform-op stack. | Use the existing typed reference/variant/payload tools and transform planners. Let the USD owner maintain `xformOpOrder`; never hand-edit USDA or patch a generated file behind an open document. | Primary references: - [Blender transform introduction](https://docs.blender.org/manual/en/latest/scene_layout/object/editing/transform/introduction.html) - [FreeCAD Part Design](https://github.com/FreeCAD/FreeCAD-documentation/blob/main/wiki/PartDesign_Workbench.md) - [Fusion components](https://help.autodesk.com/view/fusion360/ENU/?contextId=ASM-COMPONENTS) - [SOLIDWORKS mate best practices](https://help.solidworks.com/2024/English/SolidWorks/sldworks/c_Best_Practices_for_Mates_SWassy.htm) - [COMSOL named selections](https://doc.comsol.com/6.3/doc/com.comsol.help.comsol/comsol_ref_visualizationselection.22.25.html) - [OpenUSD references](https://openusd.org/release/api/class_usd_references.html) and [ordered transforms](https://openusd.org/dev/api/class_usd_geom_xformable.html) ## What an agent may do - Use Editor Perspective and the existing `assembly_edit`, `assembly_builder`, `component_editor` and measurement facades. - Hot-reload a Twin-scoped Rhai tool with `RegisterToolLibrary`, prove a real namespaced call, and reuse it for the next component. - Add a small generic Rust typed operation only when capability discovery shows that the existing owner cannot represent the required standard USD fact. - Use `UndoDocument`/`RedoDocument` for feedback and keep save as an explicit approval boundary. ## What an agent must not do - Do not edit `.usd`/`.usda` text directly, write a shadow USDA file, mutate ECS state to make a preview look correct, or restart the app between every component. - Do not build the whole vehicle in one Rhai batch and reveal only the final frame. Do not infer a socket, transform, dimension, or requirement from a name or screenshot. - Do not duplicate requirement thresholds in Rust or a Rhai tool. Load the Twin's SysML source through `sysml_requirements::source()` and report every missing, stale or unavailable fact as a visible failure. - Do not accept a green component test as proof of assembly placement. Run the parent integration checks separately. ## Checkpoint record Record one short entry per component: document/preview/view handles, source file, edit target and generation; changed paths and operation count; queried dimensions/frames/relationships; screenshot path; Rhai requirement report; and the next feedback decision. A final handoff lists the component gates and the assembly gate separately, plus any known runtime or visual blocker.