Status: design, not implemented. The highest-design-risk item in TASKS.md,
written up before code because the open questions in §5 are real and would
otherwise get answered by accident.
Why it exists: docs/direction.md §5.2. All four wanted units of reuse —
component library, study recipe, agent workflow, provenance harness — are
composition units, and §4 finding 5 is that a structured format can compose if
it has instancing plus exported parameters. Studio has neither today, which is
why the reuse story currently runs through the script and falls off the cliff.
Three systems solve this problem, and they agree on the two things that looked hardest.
A definition lives in its own file. Godot saves any scene subtree as a
.tscn and instances it by reference. An Onshape custom feature is a
FeatureScript function in a separate document, referenced by version. Jsonnet
imports a function from another file. All three, independently. That settles the
crux — definitions are documents, not inline fragments.
An instance supplies arguments; it does not reach inside. Godot allows arbitrary property overrides on an instance, and that is exactly where its recurring bugs live — exported values resetting to scene defaults, references shared between instances that should be independent. The lesson is available for free: parameters only, no arbitrary overrides. An instance may set what the definition declared and nothing else.
The useful observation. A document already carries variables and
variable_bounds; together they are a signature in everything but name:
"variables": { "n": 10, "radius": 0.023, "stagger": "=360/(2*n)" },
"variable_bounds": { "n": { "integer": true, "allowed": [3, 40] } }Instancing is mostly letting another document supply those. A definition is not a new kind of object — it is a scene document whose variables are treated as its parameters.
An instance is one event, in the same log as everything else:
{
"id": "e7",
"op": "instance",
"target": "ring1",
"definition": "rings/halbach.magpy.json",
"sha256": "…",
"args": { "n": 12, "radius": 0.03 }
}_build resolves it the way it resolves everything else — one more case in the
fold: load the definition, bind args over its variable defaults, fold its
events into a Collection, attach that Collection as target. The copies a
pattern makes are already built this way, so the machinery for "objects that
exist without a spec of their own" is in place.
to_script emits a call. That is the shape a person would write by hand, and it
is what makes a definition exportable as a function.
- Component library — a folder of definition documents.
- Study recipe — sweep an instance's
argsrather than a global variable. - FEM (
docs/fem.md) — validated assemblies become definitions; thesha256is already the pin a fixture needs. - Provenance — a scene names exactly which version of which part it used.
The document stays the artifact. This is not a step toward code-as-truth — it is
the feature that makes code-as-truth unnecessary, which is docs/direction.md
§7's whole argument.
-
What a hash mismatch does. Whether to record one is not open: an instance puts part of the scene in a file that can change underneath it, so without a hash the same document stops describing the same scene over time — and
docs/fem.md§12.1 keys the FEM cache on field-affecting events, so an unpinned instance lets the cache hand back a solve computed for geometry that is no longer there. The precedent is already in the repo rather than in an argument:mesh_sourcecarriessha256for exactly this, andmeshes.pysays why — "sha256 is for telling a person their STL changed". A definition document is an STL with parameters.What is open is the response. Meshes warn. Instances may want to refuse until the reference is re-pinned, lockfile-style, because a changed mesh gives you a visibly different shape while a changed definition can move a field a few percent and look entirely normal. Godot does not pin at all and its instances break; Onshape pins to a version and updating is deliberate.
-
Nested instances. A definition containing an instance. Needs cycle detection —
move_objectalready cycle-checks a reparent, so the idea exists, but this one spans files. -
Composition with patterns.
duplicate_aroundon an instance should work, since an instance resolves to a Collection and that is what the pattern ops already take. Verify rather than assume. -
Editing through an instance. Godot allows it; it is where the bugs are. Proposal: refuse, by name, the way
mirrorrefuses a Tetrahedron. Editing an instance means editing its definition. -
Are a document's variables really its signature? Simplest is yes, and §2 argues it. The risk is that every scratch variable becomes public API. If that bites, the fix is a declared subset — but adding the distinction up front is a concept nobody asked for yet.
-
Is a same-document definition worth having? A named fragment, for when a second file is overkill. Prior art says no — all three put it in a file — and it is an extra concept. Probably no.
- If most reuse turns out to be within one document, definitions-as-files is overhead and question 6 flips.
- If parameters-only proves too restrictive. Godot allows overrides for a reason, even if the reason costs it bugs. If real use keeps hitting the wall, the answer is more declared parameters, not arbitrary overrides — but that is a prediction, and it should be checked rather than assumed.