Template Scope¶
Overview¶
Templates can be constrained to specific parts of your story using the scope field. This prevents templates from being used in inappropriate contexts.
Scope Levels¶
Global (No Scope)¶
Templates without scope constraints are available everywhere.
templates:
generic_guard:
kind: Actor
# No scope = global
Scene-Scoped (parent_label)¶
Templates declared in a scene are automatically scoped to that scene’s blocks.
scenes:
village:
templates:
village_elder:
kind: Actor
# Inferred: scope.parent_label = "village"
blocks:
square:
roles:
elder: {actor_template_ref: "village_elder"} # ✓ In scope
city:
blocks:
plaza:
roles:
elder: {actor_template_ref: "village_elder"} # ✗ Out of scope!
Block-Scoped (source_label)¶
Templates declared in a block are only available in that specific block.
scenes:
lab:
blocks:
containment:
templates:
specialist:
kind: Actor
# Inferred: scope.source_label = "lab.containment"
roles:
expert: {actor_template_ref: "specialist"} # ✓ In scope
research:
roles:
expert: {actor_template_ref: "specialist"} # ✗ Out of scope!
Scope Override¶
You can explicitly override the inferred scope:
scenes:
village:
templates:
wandering_merchant:
kind: Actor
scope: null # Override to global (available everywhere)
secret_contact:
kind: Actor
scope:
ancestor_tags: ["conspiracy"] # Only in blocks with conspiracy tag
Scope Selectors¶
source_label¶
Template only valid in exact source node:
scope:
source_label: "village.smithy"
# Only works in the "smithy" block of "village" scene
parent_label¶
Template valid in children of parent:
scope:
parent_label: "village"
# Works in any block under "village" scene
ancestor_labels¶
Template valid if ancestor has matching label:
scope:
ancestor_labels: ["village", "city"]
# Works in blocks under scenes labeled "village" OR "city"
Provisioning Behavior¶
When a role/setting references a template:
Template lookup: Find template in
world.template_registryby labelScope check: Validate template is in scope for source node
Instantiation: If valid, create concrete node from template
Rejection: If out of scope, log warning and return no offers
Best Practices¶
Use global templates for truly generic concepts
templates: generic_guard: {...} # Works everywhere
Use scene templates for location-specific variants
scenes: castle: templates: royal_guard: {...} # Only in castle
Use block templates for ultra-specific needs
blocks: throne_room: templates: king_guard: {...} # Only here
Override scope when sharing across scenes
scenes: village: templates: merchant: scope: null # Share with other scenes
Troubleshooting¶
“Template ‘X’ not found”
Template doesn’t exist in registry
Check spelling and declaration location
“Template ‘X’ out of scope”
Template has scope constraint not satisfied
Check scope.parent_label, source_label, etc
Consider overriding scope to null for global access
“No offers for requirement”
Template exists but is out of scope
Check debug logs for scope rejection reason