# Declarative asset authoring API — research and session handoff

Status: design proposal, 2026-11-02. The library extraction and npm publication are deferred. This document is the starting point for a new session; it does not describe an implemented public API.

## Decision

Keep TypeScript as the authoring language and use a versioned, JSON-serializable asset description as the canonical intermediate representation. Express most placement through named parts, anchors, attachments and bounded repetition. Compile those relationships into coordinates deterministically. Preserve explicit coordinates for unusual geometry. Keep the mesh compiler independent of a game, renderer, React and the browser.

The purpose is higher LLM task success, not a claim that shorter or more natural-looking syntax is automatically better. Validate that purpose with a controlled generation-and-editing benchmark before freezing the API.

## Current implementation: what exists today

The current host project authors models in TypeScript using `Master.box`, `cylinder`, `tube`, `beam` and `funnel`, then combines fixed-colour and brand-colour layers. Numeric arguments encode position, dimensions, materials and bevels. These are authored low-poly meshes in a voxel-inspired style, not a strict integer voxel volume.

Relevant modules in the current host checkout:

- `src/infrastructure/render/isometric/masters.ts`: geometry primitives and palette.
- `src/infrastructure/render/isometric/authored.ts`: layer and mesh composition.
- `src/infrastructure/render/isometric/expansionProducts.ts` and `factoryMasters.ts`: examples to migrate, not dependencies for a public library.
- `src/infrastructure/render/isometric/AssetRegistry.ts`: host-specific model lookup.
- `src/infrastructure/render/isometric/thumbnail.ts` and `bake.ts`: deterministic CPU previews.
- `src/infrastructure/render/isometric/collectionThumbnails.ts`: lazy worker thumbnails with a bounded cache.
- `src/infrastructure/render/voxel/AssetPreviewRenderer.ts` and `GpuDevice.ts`: host browser/GPU adapters.
- `.agents/skills/authored-voxel-art/SKILL.md`: current art/reference/qualification workflow.

The authoring source is written during development and compiled into the application bundle. Browser code constructs meshes when assets are requested and uploads them for rendering. Neutral menu atlases and sprite fallbacks are baked during development and shipped. Brand-colour thumbnails can also be rendered on demand in a browser worker and cached. Runtime construction is deterministic asset processing; no LLM or Recraft request runs when a player opens an asset.

The separate library should support both offline baking and optional runtime parameterization. Prefer publishing precompiled meshes and bakes for ordinary fixed assets; reserve runtime compilation for deliberate variation, editors and development. A migration must measure loading time, bundle size and memory before changing the host's current strategy.

## Proposed representation

This is illustrative proposed TypeScript data. `AssetSpec` is a future contract, not an existing import. Plain JSON can represent the same description.

```ts
const desk = {
  schema: "asset-assembly/0.1",
  units: "meters",
  parameters: { width: 1.2 },
  materials: {
    brand: { color: "#409c94", tintable: true },
    frame: { color: "#283c51", tintable: false },
  },
  parts: {
    top: {
      shape: {
        type: "box",
        size: { width: { parameter: "width" }, height: 0.06, depth: 0.6 },
        bevel: 0.01,
      },
      material: "brand",
      placement: {
        type: "absolute",
        selfAnchor: "bottom-center",
        position: { x: 0, y: 0.72, z: 0 },
      },
    },
    legs: {
      shape: { type: "box", size: { width: 0.06, height: 0.72, depth: 0.06 } },
      material: "frame",
      placement: {
        type: "repeat",
        pattern: "corners",
        target: { part: "top", face: "bottom" },
        selfAnchor: "top-center",
        edgeInset: { x: 0.04, z: 0.04 },
      },
    },
  },
};
```

Changing only `parameters.width` preserves the four leg attachments. A numeric-coordinate version requires the author or LLM to recalculate dependent leg positions. The compiler expands the repeated part into stable instance IDs and rejects a tabletop too small to contain the requested insets and legs.

### Positioning contract

Use a right-handed frame: +X right, +Y up, -Z front. Units are declared per asset. The asset's published ground pivot is independent of its internal part origins. Part anchors refer to geometric bounds before material tinting or camera fitting.

- `absolute`: move the specified `selfAnchor` to an explicit point in the parent frame.
- `attach`: align `selfAnchor` with a named target part anchor, then apply an optional offset expressed in that target's local frame.
- `repeat/corners`: place four instances against the four corners of the target's bottom or top face. `edgeInset` is the distance from the target edge to the instance's outer bound, not to the instance centre. In the desk example, leg centres are at ±(width/2 - 0.04 - 0.03).
- Hierarchical groups own local frames. References resolve by stable IDs, not declaration order. A future rotation feature must define whether rotations are local or parent-relative before release.

Start with one canonical spelling for each relationship. Avoid accepting unvalidated free text such as “near the back.” Do not silently interpret an unknown anchor, omit an unresolved part, relax a conflicting relationship, or change the intended part count. Explicit coordinates remain useful for curved handles and unusual silhouettes.

Keep expression support small: finite numeric literals and named scalar parameter references in the first version. Arbitrary callbacks, JavaScript evaluation, a general arithmetic language, mirror patterns and soft constraints can wait. They enlarge both the implementation and the LLM's failure surface.

## Compiler and diagnostics

The core pipeline is: parse schema → validate references and parameters → expand patterns → order the attachment graph → resolve transforms and anchors → generate indexed meshes → validate geometry/bounds → produce a manifest. Cycles and contradictory placement specifications fail explicitly. Compilation does not depend on object-key insertion order, a camera, global application state or simulator randomness.

Keep material roles, roofs, animated surfaces and future joints as named data where required. Geometry resolution must not consume a host's random stream. Any stochastic variation receives an explicit seed in the asset specification.

Return structured diagnostics suitable for an LLM repair loop:

```json
{
  "code": "UNKNOWN_ANCHOR",
  "path": "/parts/handle/placement/target/anchor",
  "part": "handle",
  "targetPart": "top",
  "received": "upper-surface",
  "expected": ["top-center", "bottom-center", "center"],
  "message": "Choose an anchor exported by part top."
}
```

Validation must distinguish schema errors, missing references, dependency cycles, impossible bounds, non-finite values and geometry-budget errors. Diagnostics identify the smallest editable location. Render artifacts, resolved bounds and anchor overlays support visual repair; a successful type check alone does not establish a correct object.

Proposed public operations: `validateAsset(spec)` returns diagnostics; `compileAsset(spec)` returns mesh layers, resolved part/instance transforms, bounds and a source hash; `bakeAsset(compiled, camera)` returns images and metadata. These names and signatures remain provisional. Agent tools can wrap validation and rendering without introducing a second semantic API.

## Scientific basis and limits

The following are primary sources. The design implications are our hypotheses, not results measured for this API.

| Source | What it studies | Implication to test here | Boundary |
| --- | --- | --- | --- |
| [ShapeAssembly, Jones et al., ACM TOG 2020](https://doi.org/10.1145/3414685.3417812) | Programs with cuboid parts, attachments, hierarchy and symmetry for generated shape structures. | Make assembly relationships and repeated structure explicit. | A learned shape-program system, not an evaluation of general-purpose LLMs or our syntax. |
| [LayoutGPT, Feng et al., NeurIPS 2023](https://proceedings.neurips.cc/paper_files/paper/2023/hash/3a7f9e485845dac27423375c934cb4db-Abstract.html) | LLM visual planning using structured layout descriptions and in-context examples. | Provide compact structured data plus complete worked examples. | Layout/scene generation differs from authoring a reusable mesh library. |
| [Holodeck, Yang et al., CVPR 2024](https://openaccess.thecvf.com/content/CVPR2024/html/Yang_Holodeck_Language_Guided_Generation_of_3D_Embodied_AI_Environments_CVPR_2024_paper.html) | LLM-generated spatial relationships optimized into 3D room layouts; its layout ablation compares relational constraints with absolute coordinates. | Let the LLM specify intent and let deterministic code resolve placement. | Its room-layout human rankings do not prove better object-API generation accuracy. |
| [Gorilla, Patil et al., NeurIPS 2024](https://proceedings.neurips.cc/paper_files/paper/2024/hash/e4c61f578ff07830f5c37378dd3ecb0d-Abstract-Conference.html) | API calling with documentation retrieval and evaluation of correct calls and hallucinations. | Version the schema and reference documentation; measure unknown operations and bad arguments separately. | Retrieval/training results do not establish a superior geometry DSL. |
| [Text2CAD, Khan et al., NeurIPS 2024](https://proceedings.neurips.cc/paper_files/paper/2024/hash/0e5b96f97c1813bb75f6c28532c2ecc7-Abstract.html) | Text-conditioned sequential parametric CAD construction and geometry evaluation. | Evaluate geometric outcomes as well as generated syntax. | CAD sketches/extrusions and this low-poly assembly system have different representations. |

Do not present these studies as evidence that a particular JSON schema, field name, TypeScript wrapper or package name has been scientifically validated. No LLM comparison experiment for this proposal has been run yet.

## LLM evaluation before API freeze

Compare three representations: today's positional primitive calls, named coordinate arguments, and the proposed relational specification. Keep model versions, task prompts, documentation budgets, available examples, generation settings and repair limits comparable. Include a no-render-feedback condition and an equal-render-feedback condition. Track first-pass success independently from repaired success.

Prepare 60 tasks across 12 asset families: creation, proportional resizing, repeated-part changes, attachment edits and repair of deliberately invalid specifications. Split by asset family so evaluation tasks are not minor variants of the examples shown to the model. Include coordinate/axis traps, missing IDs, cycles, too-small targets, intentional joints and a request that the API cannot express. Models must diagnose unsupported requests rather than invent operations.

Use at least three model families and repeated trials; record exact model snapshots and provider reproducibility limits. Primary metric: the fraction of held-out tasks producing valid geometry that satisfies all declared predicates. Additional metrics: part/instance count, attachment residuals in model units, symmetry error, ground contact, hallucinated operations/arguments, edit locality, repair rounds, output tokens, latency and total tool cost. Use paired comparisons and uncertainty intervals over held-out tasks; repeated samples of one task are not independent task coverage.

A candidate can proceed only if relational correctness improves meaningfully without unacceptable regressions in unsupported-request handling, mesh validity, tokens or repair cost. Set numerical acceptance thresholds before running the experiment. Visual reviewers assess silhouette and edit quality separately from mathematical predicates. Report failed cases, not just selected attractive renders.

## Deferred extraction plan

1. In a fresh session, refresh the host checkout, active work and applicable instructions. Read this document, the art skill, and current Ludic repository contribution/release documentation. Preserve unrelated changes.
2. Create a separate, generically named library repository; choose a package name after checking availability. Do not move game-specific catalogs, names, save formats, sprites, economy code or private application examples into Ludic's public repository.
3. Extract pure geometry, named layers, bounds and CPU bake logic behind a small adapter. Maintain a temporary adapter to today's imperative master API so migration can be incremental and visually compared.
4. Implement and schema-test the minimal relationship compiler and diagnostic contract. Add golden tests for resizing, ordering, references, repeats, winding, normals and deterministic hashes.
5. Migrate three generic fixtures first: furniture with repeated supports, an articulated lamp, and a small machine. Compare geometry, silhouettes, material tinting, bakes, runtime rendering and disposal with the originals.
6. Run the LLM evaluation above. Revise the schema using observed error patterns. Keep the public API provisional until the evidence supports a choice.
7. Package TypeScript/ESM declarations and a JSON schema, with separate core, optional browser and offline-tool entry points. Adopt Ludic's style of versioned API reference, complete examples, explicit ownership/disposal and documented limits. React integration is optional.
8. In that later session, set up the repository's release workflow and publish only after package, documentation, clean-consumer and runtime verification. Follow current Ludic Changesets/OIDC practices rather than copying historical commands or version numbers.

Definition of completion for that future work: an independently installable package, no host-game dependencies, documented schema semantics, measured LLM usability, reproducible asset outputs, a verified documentation deployment and an explicit migration adapter. This session publishes the proposal and handoff only; it does not implement or publish the library.
