MAP Design Spec: Dances, Descriptor Affordances, and Holonic Invocation (v2.3)¶
ChangeLog¶
v2.4¶
- defines the host-to-guest
GetSavedHolonByKeydance boundary for saved-holon lookup and retiresGetSavedHolonsByBaseKey
v2.3¶
- makes
DanceInvocation.AffordingHolonrequired for every Dance and defines its effective afforded dances as the unique DanceName resolution scope - removes the
AffordingHolonRequirementpolicy and subjectless Dance invocation semantics - aligns the current foundation with map-holons #652 and PR #654, which defer structural request/response conformance to the shared Validation track
v2.2¶
- reconciles Issue 17's Dance naming, affordance, and delivery-plan contradictions with the merged Schema 2.0 package layout
- defines
TypeDescriptor.TypeNameas the sole DanceType identity andDanceInvocation.DanceNameas the required uniquely resolved invocation name - standardizes
AffordsDance/DanceAffordedByandRequestType/RequestTypeFor - records required
HolonSpaceaffordance forLoadHolonsandQueryDance - defines shared structural request/response validation at the Dance boundary and separates it from TrustChannel/Agreement disclosure authorization
- replaces legacy-coexistence guidance with the clean contract-cutover posture
v2.1¶
This revision aligns dance invocation, request validation, projections, and query execution with the stable-name and structural-contract posture.
- changes dance invocation identity from descriptor-reference identity to
canonical
DanceName - clarifies that the host resolves
DanceNamethrough the affording holon's effective afforded dances before validation and dispatch - clarifies that dance request validation is structural against the resolved
DanceType.RequestType, not exact descriptor-holon identity on the supplied request holon - distinguishes persistent Projection-shaped contracts from ephemeral Projection-shaped values
- clarifies that query-produced projection holons may be descriptorless because
their shape is a function of the producing
QueryExpression - separates independently invocable Query execution from the Query–Dance adapter, rather than making the Query Schema depend on Dance descriptors
- clarifies that builders create transient invocation and request value holons without minting per-invocation request descriptors
- separates the holonic schema design from Rust wrapper and helper types
- reorganizes the spec so schema artifacts are presented in one complete schema section and Rust/runtime behavior is presented in one runtime section
v2.0¶
The old spec (v1.3) has been moved to the archive. Starting a new changelog here. These are the principal changes from 1.3.
- consolidates the revised holonic dance design as the current target posture
- re-centers dance contracts on
DanceType,DanceInvocation,DanceResponseType,DanceImplementation, andProjection - replaces dance-specific wire envelopes with holon-backed invocation and response records
- clarifies
Projectionas the base shell for value-shaped request, response, and projection-result holons - simplifies implementation binding so active implementations are selected by
ForDancerather than per-target dynamic dispatch - restores concrete guidance for query/navigation dance categories under the new holonic design
- restores a legacy surface disposition appendix, updated to clarify
Deprecatedsuffix strategy for deprecated schema descriptors - distinguishes the canonical descriptor-driven host dance surface from the guest-side primitive persistence surface
- clarifies that guest-side primitives may remain non-descriptor-driven and be
wrapped through
DanceImplementationwhen a canonical host dance needs guest authority -
adds a Dances DSL authoring section and aligns the spec with the updated MAP type-definition DSL work
-
Status: Draft
- Intent: Specify the MAP Dances design: dances are descriptor-afforded behaviors, invocations are holons, responses are holons, and command ingress carries holon references rather than dance-specific wire payloads.
- Scope: Dance type definition, afforded dances, request and response shapes, invocation records, response bodies, implementation binding, ABI, command ingress, dispatch, validation, persistence, audit posture, performance, and test migration posture.
1) Design Summary¶
This spec is organized around two layers:
- The schema layer defines the durable holonic contract: the HolonTypes, PropertyTypes, RelationshipTypes, and invariants that make dances portable, inspectable, and valid across hosts.
- The Rust type layer is an implementation convenience over that contract: typed wrappers, builders, references, and bound execution contexts that make the schema ergonomic and safe to use in code. In short, schema says what a dance is and what structure it promises; Rust types say how a host program reads, constructs, validates, and executes those schema-backed holons without becoming a second source of truth.
The foundational ontology of the MAP is self-describing, active holons and holon relationships. The self-describing part means that holons carry a DescribedBy relationship to their own HolonType descriptor. We say holons are active because they are not just passive information containers, they offer behaviors -- i.e., they can do stuff. These behaviors represent the affordances the holon type offers. We've shortened the term affordances to simply, dances. Thus, a dance is a behavior afforded by a MAP Holon Type and the set of dance types a holon type affords is available through its AffordsDance relationship to schema-backed DanceType
descriptors. A dance's stable canonical DanceName is its inherited TypeDescriptor.TypeName.
Dances can have either statically bound implementations or (in the future) dynamically bound implementations. A dance's implementation is described through its associated DanceImplementation descriptor.
Dances may be invoked through either Command or TrustChannel ingress paths.
A dance is invoked when an ingress adapter delivers a HolonReference to a
DanceInvocation holon to the canonical execute_dance_v2 host executor with
its transaction context. For Commands this is expressed as
TransactionAction::DanceV2 { invocation }; other ingress paths adapt their
own envelopes to the same executor call. A dance invocation is a holon.
DanceInvocation specifies the dance being
invoked by canonical DanceName, the required affording holon that is the
subject of the invocation, the request holon supplied to the dance, and the
ingress source of the invocation. The invocation record is part of the holonic
model; it is not a bespoke request wire object.
A dance is invoked when an ingress adapter, such as Commands or TrustChannels,
calls the canonical executor with a Rust DanceInvocation typed reference
wrapper. That wrapper contains the ordinary HolonReference to the
DanceInvocation holon. The host binds that reference, resolves
DanceInvocation.DanceName through the affording holon's effective afforded
dances, validates the invocation
against the resolved dance contract, selects a DanceImplementation, executes
it, and returns a DanceResponseReference or HolonError.
The supplied request holon is validated structurally against the resolved dance's declared request contract. It may reference a descriptor when one is available, but exact descriptor-holon identity is not the basis for accepting or rejecting the request.
The canonical descriptor-driven dance surface is host-biased and extensible.
The guest is not the general dance runtime. Instead, the guest exposes a small,
stable primitive persistence surface for operations that require HDK or DHT
authority. These runtime surfaces need not be identical. DanceImplementation
is the layer that can wrap guest-side primitives so that canonical host dances
can still execute through one descriptor-driven executor when appropriate.
A successful dance response is a holon whose descriptor extends
DanceResponseType. The response can point to its structured result body
through ResponseBody. Result state lives in normal MAP holon state managers
and is reached by relationship, not embedded in a command payload.
Query execution is independently callable by peer Rust objects. The
Query–Dance adapter provides the ordinary Dance path: it accepts a
QueryDanceRequest, invokes the selected Query, and returns a holonic
response. Query expressions such as seed, expand, filter, order, skip, limit,
and project remain query-domain behavior rather than separate canonical
DanceTypes. Commands invoke this adapter through Dances and do not acquire a
direct Query dependency.
2) Relationship to Descriptor Design¶
The descriptor design owns the structure and interpretation of MAP type descriptors. It defines how holon types declare properties, relationships, commands, dances, inheritance, abstract target endpoint type declarations, and descriptor-local lookup. The Dances design builds on that foundation; it does not define a second descriptor system.
Descriptor design owns:
TypeDescriptor,HolonType, and the meta-type structureExtendsinheritance and effective descriptor flatteningHolonDescriptoras the caller-facing lookup surface for type structure and affordances- relationship source and target endpoint type declarations, including abstract target
declarations such as
HolonType - property and relationship validation for ordinary holon state
Dances design owns:
DanceTypeas the descriptor family for executable behaviorAffordsDanceas the behavior affordance from holon types to dancesDanceImplementationas the executable binding modelDanceInvocationas the holonic execution request recordDanceResponseTypeas the successful response model- dance dispatch, implementation selection, command ingress, runtime-surface adaptation, and audit posture
The Dances design must not introduce a second global dance registry, require
callers to reconstruct Extends inheritance, detach behavior meaning from
descriptors, or make ABI payload encoding the semantic owner of invocation and
response meaning. A caller asks descriptors what a holon affords; the dance
runtime executes the afforded behavior.
3) Foundational Assumptions¶
-
Self-describing types
- MAP types are holons described by descriptor holons.
- Runtime wrappers are typed views over
HolonReference. - Structural and behavioral affordances are discovered through descriptors.
-
Descriptor-owned affordance lookup
- Dances are behaviors afforded by
HolonTypedescriptors. - Effective dance lookup is inherited and flattened through
Extends. HolonDescriptorowns the caller-facing dance discovery surface.
- Dances are behaviors afforded by
-
Holonic execution records
- Dance invocation is represented by
DanceInvocation. - Successful dance response is represented by a holon whose descriptor
extends
DanceResponseType. - Result state is reached through relationships and
HolonReference, not embedded as command payload state.
- Dance invocation is represented by
-
Ingress adapters do not own dance meaning
- Commands and TrustChannels are ingress paths into dance execution.
- They carry references and enforce ingress policy.
- They do not define separate dance request, response, query, or result semantics.
-
Query–Dance invocation is an adapter
- Query execution is independently invocable beneath the Dance layer.
QueryDanceis the ordinary descriptor-afforded adapter for Dance ingress; it does not own query execution semantics.- Query expressions are not separate canonical
DanceTypes. - Plural holon-backed results use
HolonCollection. - Projection records are holonic values. They may be descriptorless when their shape is derived from the producing query graph or query step.
- Row-shaped query result contracts are not part of the Dances design.
-
Value semantics stay with value descriptors
- Dances do not own scalar value meaning or operator semantics.
- Value validation and operator support are resolved through
ValueDescriptor.
4) Dance Schema Design¶
The Dance Schema is the holonic schema contract. It defines the descriptor families, invocation and response holons, implementation binding holons, projection roots, and the property and relationship types that connect them. It does not define Rust wrappers, wire encodings, dispatch algorithms, or runtime state-manager behavior.
4.1 Schema Inventory¶
Core Dance Schema holon types:
Abstract HolonType: DanceType
Abstract HolonType: DanceResponseType
HolonType: DanceImplementation
HolonType: DanceInvocation
HolonType: DanceDiagnostic
HolonType: Projection
Core enum value types:
EnumValueType: InvocationSource
EnumValueType: DanceDiagnosticSeverity
EnumValueType: RequiredExecutionContext
Query–Dance adapter schema types:
DanceType: QueryDance
HolonType: QueryDanceRequest
HolonType: QueryDanceResponse extends DanceResponseType
QueryDance, QueryDanceRequest, and QueryDanceResponse are owned by the
Query–Dance adapter schema, not MAP Core and not the independently loadable
Query Schema. QueryDance participates in Dance's one generic
AffordsDance / DanceAffordedBy relationship as a concrete extension of
DanceType; the adapter defines no QueryDance-specific affordance pair.
MAP Dance Schema-v0.1.0 is a separately loadable package at
map-holons/schema-src/dance/schema.tdl and depends on
MAP Core Schema-v0.0.7. QueryDance depends on Dance, Query, and Core. Dance
must not import QueryDance.
4.2 PropertyTypes¶
Dances use ordinary MAP property descriptors. The Dance Schema owns the following property types:
| PropertyType | Used By | Meaning |
|---|---|---|
DanceName |
DanceInvocation |
Required canonical dance name used to resolve exactly one Dance through the affording holon's effective afforded dances. The resolved DanceType's inherited TypeDescriptor.TypeName is the same canonical identity. |
DanceDescription |
DanceType |
Dance-specific description of what the dance does and when it should be invoked. Shared descriptor metadata still comes from TypeDescriptor. |
RequiredExecutionContext |
DanceType |
Required semantic execution context: ContainerLocal, HostAuthoritative, or SpaceAuthoritative; resolved from the Dance contract, not inferred from ingress, routing, or implementation placement. Its authoring default is SpaceAuthoritative; the other values require an explicit declaration. |
InvocationSource |
DanceInvocation |
Trusted ingress source stamped internally by the ingress adapter; it is never caller-supplied API input. |
Engine |
DanceImplementation |
Implementation engine family, such as built-in Rust or a dynamic module engine. |
ModuleRef |
DanceImplementation |
Executable module identity or built-in implementation identity. |
Entrypoint |
DanceImplementation |
Function, method, or exported entrypoint used by the implementation engine. |
AbiId |
DanceImplementation |
ABI contract identifier expected by the implementation. |
Version |
DanceImplementation |
Implementation version used for compatibility and deterministic selection. |
Compat |
DanceImplementation |
Compatibility declaration for host, engine, ABI, or schema expectations. |
DanceSummary |
DanceImplementation |
Human-readable implementation summary. |
DanceDiagnosticSeverity |
DanceDiagnostic |
Non-fatal diagnostic severity. |
DiagnosticCode |
DanceDiagnostic |
Stable diagnostic code. |
DiagnosticMessage |
DanceDiagnostic |
Human-readable diagnostic message. |
Schema-backed value semantics for these properties come from their
ValueDescriptors. Dance implementations must not reinterpret their scalar
meaning locally.
4.3 RelationshipTypes¶
Dances use ordinary MAP relationship descriptors. The Dance Schema owns the following relationship types:
| RelationshipType | Source | Target | Cardinality | Meaning |
|---|---|---|---|---|
AffordsDance |
HolonType |
DanceType |
0..* |
Instances of the source holon type may invoke the target dance. |
DanceAffordedBy |
DanceType |
HolonType |
0..* |
Inverse of AffordsDance. |
RequestType |
DanceType |
HolonType |
0..1 |
Declares the request-body contract for the dance. Absent means no structured request body. |
Response |
DanceType |
DanceResponseType |
1..1 |
Declares the successful response type for the dance. |
ForDance |
DanceImplementation |
DanceType |
1..1 |
Binds executable implementation metadata to one dance descriptor. |
HasImplementation |
DanceType |
DanceImplementation |
0..* |
Inverse of ForDance. |
AffordingHolon |
DanceInvocation |
HolonType |
0..1 |
Points to the subject holon for a holon-afforded invocation. |
Request |
DanceInvocation |
HolonType |
0..1 |
Points to the request value holon supplied for one invocation. |
ResponseBody |
DanceResponseType |
HolonType |
0..1 |
Declares the structured body type for successful responses of this response type. |
ResponseBodyFor |
HolonType |
DanceResponseType |
0..* |
Inverse of ResponseBody. |
Diagnostics |
DanceResponseType |
DanceDiagnostic |
0..* |
Attaches non-fatal diagnostics to a successful response. |
The Query–Dance adapter request type declares:
| RelationshipType | Source | Target | Cardinality | Meaning |
|---|---|---|---|---|
RequestedQuery |
QueryDanceRequest |
Query |
1..1 |
Reusable query definition to execute. |
InitialInput |
QueryDanceRequest |
HolonCollection |
1..1 |
Initial collection for the query execution. |
RequestParameters |
QueryDanceRequest |
QueryParameterBinding |
0..* |
Invocation-level bindings. |
Relationship target endpoint type declarations that name abstract HolonType may point to any
holon whose concrete descriptor extends HolonType. Descriptorless
Projection values are the special value-shaped exception: they may be used as
request or query-produced response-body values when accepted by the resolved
dance contract or derived from the producing query.
ResponseBody is declared on response descriptors to name the response-body
contract. Response holons described by those descriptors use the same
relationship name to point to the concrete response-body holon produced by an
execution.
4.4 HolonType Definitions¶
Abstract HolonType: DanceType
Properties:
DanceDescription
RequiredExecutionContext
Relationships:
RequestType -> HolonType [0..1]
Response -> DanceResponseType [1..1]
HasImplementation -> DanceImplementation [0..*]
DanceAffordedBy -> HolonType [0..*]
DanceType descriptors are ordinary TypeDescriptor holons. Shared descriptor
metadata such as type_name, display_name, and description comes from the
shared descriptor model. Its TypeDescriptor.TypeName is the stable canonical
DanceName used for lookup and dispatch; descriptor holon IDs are host-local
resolution artifacts, not portable invocation identity.
RequestType is the dance's request contract. If present, it points to the
holon type that defines the structural shape expected as the request body. If
absent, the dance accepts no structured request body. When a dance needs scalar
parameters, its request type can extend Projection and declare the required
instance properties directly.
HolonType: DanceImplementation
Properties:
Engine
ModuleRef
Entrypoint
AbiId
Version
Compat
DanceSummary
Relationships:
ForDance -> DanceType [1..1]
DanceImplementation is executable binding metadata. It is part of the schema
because implementations are discoverable holons, but implementation selection
and execution are runtime concerns.
HolonType: DanceInvocation
Properties:
DanceName
InvocationSource
Relationships:
AffordingHolon -> HolonType [0..1]
Request -> HolonType [0..1]
DanceInvocation records a request to execute a dance. It names the dance by
canonical DanceName; it does not point to a DanceType descriptor as portable
identity. AffordingHolon points to the concrete subject holon when the dance
is holon-afforded. Request points to the concrete request value holon for this
invocation.
Abstract HolonType: DanceResponseType
Relationships:
ResponseBody -> HolonType [0..1]
Diagnostics -> DanceDiagnostic [0..*]
A successful response holon is described by a concrete descriptor extending
DanceResponseType. ResponseBody declares the shape of the structured result
body when one exists. Failure is represented by HolonError, not by a
successful response with an error-shaped status body.
HolonType: DanceDiagnostic
Properties:
DanceDiagnosticSeverity
DiagnosticCode
DiagnosticMessage
DanceDiagnostic records non-fatal diagnostics attached to a successful
response. Diagnostics do not replace HolonError.
HolonType: Projection
Projection is the base holon type for value-shaped holons. It is intentionally
only a shell. Concrete dance request, response-body, parameter, and reusable
projection contracts extend Projection when their state is a property map
rather than a reference to another whole holon.
4.5 EnumValueTypes¶
InvocationSource =
| ClientCommand
| TrustChannel
| Internal
DanceDiagnosticSeverity =
| Info
| Warning
RequiredExecutionContext =
| ContainerLocal
| HostAuthoritative
| SpaceAuthoritative
Every resolved concrete DanceType supplies exactly one
RequiredExecutionContext. It is semantic contract metadata: interchangeable
implementations must satisfy the same requirement. SpaceAuthoritative is the
authoring default. ContainerLocal and HostAuthoritative are explicit
semantic claims, not inferences from where code is currently deployed.
InvocationSource is trusted runtime metadata stamped internally by the
ingress adapter; it is not caller-supplied API input. A client cannot claim
TrustChannel or Internal authority for itself.
4.6 Projection Contracts And Values¶
Projection has two distinct roles:
- persistent schema root for reusable value-shaped contracts, such as a dance request type or response-body type
- ephemeral holonic value shape for query-produced records whose shape is
derived from the producing
QueryExpression
Dance request projections usually have persistent descriptors because their shape is part of the dance contract. The supplied projection value does not need to reference that descriptor, or any descriptor, if it structurally satisfies the resolved contract.
Query-produced projection values may be descriptorless by design. Their shape is a function of the query that produced them. A transient descriptor may be created when useful, but descriptor creation is not required merely to carry projected values.
4.7 Query–Dance Adapter Schema¶
4.7.1 Current Concrete Dances¶
The current TDL defines the following concrete DanceTypes. Both require an
AffordingHolon whose effective descriptor is HolonSpace or extends it, and
which affords the resolved Dance through its effective affordances:
| DanceType | Canonical DanceName | RequestType | Response | Affordance owner |
|---|---|---|---|---|
LoadHolons |
LoadHolons |
HolonLoadSet |
HolonLoadResponse |
Generic HolonSpace -[AffordsDance]-> DanceType relationship |
QueryDance |
QueryDance |
QueryDanceRequest |
QueryDanceResponse |
Generic HolonSpace -[AffordsDance]-> DanceType relationship |
The names in the second column are each DanceType's inherited
TypeDescriptor.TypeName, not values of a separate DanceType property.
4.7.2 Query–Dance Adapter Schema¶
The canonical query affordance is coarse-grained:
DanceType: QueryDance extends DanceType
RequestType -> QueryDanceRequest
Response -> QueryDanceResponse
HolonSpace -[AffordsDance]-> QueryDance
HolonType: QueryDanceRequest
Relationships:
RequestedQuery -> Query [1..1]
InitialInput -> HolonCollection [1..1]
RequestParameters -> QueryParameterBinding [0..*]
HolonType: QueryDanceResponse extends DanceResponseType
Relationships:
ResponseBody -> HolonType [0..1]
QueryDanceResponse.ResponseBody points to the query result
HolonCollection. The adapter passes its selected query, input, and bindings to
the direct Query engine. It does not own the query tree or execution state.
4.8 Schema Invariants¶
- Concrete dance descriptors extend
DanceType. - A DanceType's inherited
TypeDescriptor.TypeNameis its stable canonical DanceName; onlyDanceInvocationcarries aDanceNameproperty. DanceType.RequestType, when present, points to aHolonTypedescriptor.DanceType.Responsepoints to aDanceResponseTypedescriptor.DanceType.RequiredExecutionContextis required declarative contract metadata, independent of ingress, routing, and implementation placement. TDL/schema materialization applies theSpaceAuthoritativeauthoring default, so runtime receives an explicit resolved value rather than supplying a fallback.DanceResponseType.ResponseBody, when present, points to aHolonTypecontract, while query-produced projection values may still be descriptorless runtime values.AffordsDancepoints fromHolonType.TypeDescriptorto the abstractDanceType.HolonType;DanceAffordedByis its inverse.LoadHolonsandQueryDanceextendDanceTypeand are substitutable targets of that one generic relationship.ForDancepoints fromDanceImplementationto exactly oneDanceType;HasImplementationis its inverse.- Dance affordances inherit through
Extendsusing the same descriptor flattening rules as other type affordances. - Request and response-body holon types are owned by the Dance-layer adapter
that declares them. The Dances Schema does not define a generic
Parameterholon type. ResponseStatusCode,OutcomeOf, andDanceEventare not part of the active schema. If event-like artifacts are later needed, they should be modeled as explicit holons related to the invocation, response, or response body they describe.
4.9 Dance Signature DSL¶
The holonic representation is canonical, but verbose for human authors. A Dances DSL is a concise authoring surface for declaring dance signatures. It compiles into the schema artifacts above; it does not define a second semantic model.
Example:
dance Summarize
target Article
request SummarizeRequest extends Projection
properties
max_sentences: PositiveInteger
tone: SummaryTone
response SummarizeResponse
response_body SummaryProjection extends Projection
properties
summary_text: LongString
This compiles to:
- a
DanceTypedescriptor forSummarize - a
SummarizeRequestholon type extendingProjection - a
SummarizeResponseholon type extendingDanceResponseType - a
SummaryProjectionholon type extendingProjection Summarize -[RequestType]-> SummarizeRequestSummarize -[Response]-> SummarizeResponseSummarizeResponse -[ResponseBody]-> SummaryProjectionArticle -[AffordsDance]-> Summarize
The DSL should prefer existing property definitions over generating new ones when projected or parameter fields already correspond to known MAP properties. It may define new property types where genuinely needed, such as aggregate or computed fields that do not correspond to a single existing source property.
5) Runtime And Execution Design¶
The runtime design explains how Rust wrappers, builders, ingress adapters, validation, implementation selection, ABI calls, state managers, and wire boundaries use the Dance Schema. Runtime behavior must not redefine schema meaning.
5.1 Dance Execution Context¶
Every Dance implementation has a natural execution context that determines where that implementation is valid.
The resolved DanceType.RequiredExecutionContext is the declarative source of
that requirement. Implementations realize the Dance contract; they do not
redefine its execution semantics.
Classification is based on the Dance contract's required authority or
capability, not the current Host/Guest topology or the crate containing one
implementation. Extension DanceTypes also default to SpaceAuthoritative.
An extension cannot obtain Host-authoritative execution solely by declaring
HostAuthoritative; future Host execution requires explicit trust/admission
policy for implementation provenance and capability. That policy is separate
from this enum and is not supplied by routing.
Execution context is distinct from routing.
- Execution context determines where the implementation must execute.
- Routing determines how an invocation reaches that execution environment.
The runtime recognizes three execution contexts.
Container-Local¶
A Container-Local Dance executes within the container in which it is invoked.
The same implementation may therefore execute in either Host or Guest when it
is compiled into shared runtime code such as holons_core.
A Container-Local implementation must not require the invocation to escape its invoking container.
Typical examples are pure or shared MAP logic whose required capabilities are available equally in native Host and Guest WASM environments.
Host-Authoritative¶
A Host-Authoritative Dance requires capabilities available only in the native Host environment.
Typical examples include access to operating-system or native facilities that are unavailable within the Holochain Guest WASM sandbox.
Dance implementations should express such dependencies through MAP service
abstractions such as HolonServiceApi, rather than branching directly on
execution environment. The Host service implementation supplies the required
capability; an environment that cannot supply it returns an appropriate
unsupported or error result.
Space-Authoritative¶
A Space-Authoritative Dance must execute in the environment having authoritative access to the relevant holon's Home Space.
For a locally hosted Holochain Space, this normally means execution within the Guest that owns the corresponding DHT authority.
For an externally hosted AgentSpace, reaching the authoritative execution environment may instead require routing through a TrustChannel.
Accordingly, "Guest-only" is a property of the current topology, not the architectural invariant. The invariant is that Space-Authoritative behavior executes against the authoritative Home Space.
Execution Context And Routing¶
Execution context and routing are orthogonal.
Given a Dance invocation, the runtime determines the valid execution context:
- Container-Local -> execute within the current container.
- Host-Authoritative -> execute within the native Host.
- Space-Authoritative -> resolve the relevant Home Space and execute within its authoritative environment.
Routing then determines how that environment is reached.
Depending on deployment topology, execution may require:
- no container boundary crossing,
- Host-to-Guest transport,
- Guest-to-Host transport,
- or TrustChannel routing to another AgentSpace.
This distinction allows Dance execution semantics to remain stable as MAP deployment topology evolves.
5.2 Rust Types¶
Rust types are typed views, builders, and execution contexts over holonic state. They are not additional schema types.
Representative Rust surfaces include:
DanceDescriptor, a typed view over aDanceTypedescriptor holonDanceInvocation, a typed reference wrapper around aHolonReferenceto aDanceInvocationholon at the execution boundaryBoundDanceInvocation, a host-side resolved execution context used after bindingDanceResponseorDanceResponseReference, typed views over response holons whose descriptors extendDanceResponseType- request builders for Projection-shaped request values
TransactionAction::DanceV2, the command ingress variant that carries aHolonReferenceto aDanceInvocation
Representative executor and command-facing Rust shapes:
pub async fn execute_dance_v2(
context: &Arc<TransactionContext>,
invocation: DanceInvocation,
) -> Result<DanceResponseReference, HolonError>{}
pub struct DanceInvocation {
invocation: HolonReference,
}
pub enum TransactionAction {
DanceV2 { invocation: HolonReference },
}
pub enum TransactionActionWire {
DanceV2 { invocation: HolonReferenceWire },
}
Rust helper types may expose the canonical DanceName, host-resolved
DanceType, optional request holon, declared request and response descriptors,
required affording holon and descriptor, invocation source, and state managers. They must
preserve the schema rules: dance identity is name-based, request validation is
structural against the resolved contract, and builders do not mint
per-invocation request descriptors merely to carry request values.
5.3 Ingress And Builders¶
Commands and TrustChannels are ingress paths into the same dance execution core. Ingress does not determine execution context: an invocation arriving through one ingress path may execute locally or be routed onward to the environment required by the selected implementation.
Canonical executor signature:
execute_dance_v2(
context: &Arc<TransactionContext>,
invocation: DanceInvocation
) -> Result<DanceResponseReference, HolonError>
The Rust DanceInvocation argument is a typed reference wrapper around the
ordinary HolonReference to the invocation holon. Ingress adapters construct or
receive the invocation holon reference, wrap it as DanceInvocation, then call
the executor.
Command and wire envelopes remain reference-oriented:
DanceV2(invocation: HolonReference) -> Result<HolonReference, HolonError>
The command input reference points to a DanceInvocation holon. The command
output reference points to the response holon reached through the
DanceResponseReference returned by the executor.
A shared host-side builder creates transient DanceInvocation holons in the
chosen transaction-bound transient manager. When the builder creates a
Projection-shaped request holon, it creates and populates the request value
holon. It does not need to mint a request descriptor for that invocation or
attach the dance's declared request descriptor to the request value. Validation
is performed later against the resolved DanceType.RequestType.
The Dances design does not define DanceInvocationWire, DanceResponseWire,
dance-request wire types, or dance-result wire unions.
5.4 Binding And Dispatch¶
Given a Rust DanceInvocation typed reference wrapper, runtime dispatch:
- Reads the underlying
HolonReferenceto theDanceInvocationholon. - Binds the invocation reference and reads the invocation's canonical
DanceName. - Resolves that name through the affording holon's effective afforded dances.
- Resolves the request holon, required affording holon, invocation source, declared request type, and declared response type.
- Performs executor ingress validation.
- Binds the invocation into a
BoundDanceInvocationor equivalent resolved execution context, includingRequiredExecutionContextfrom the resolvedDanceType. - Resolves candidate implementations through
ForDance; candidates must be compatible with satisfying that resolved context. - Applies activation-time validation and deterministic implementation selection.
- Executes the selected implementation through the dance ABI.
- Places produced state in the correct MAP state manager.
- Receives the final response holon described by
DanceResponseTypefrom the selected implementation. - Returns the response wrapper or reference.
sequenceDiagram
autonumber
actor Caller
participant Executor as execute_dance_v2
participant Invocation as DanceInvocation
participant Bound as BoundDanceInvocation
participant Validator as validation helpers
participant Selector as select_implementation
participant Impl as DanceImplementation
participant ResponseRef as DanceResponseReference
Caller->>Executor: execute_dance_v2(context, DanceInvocation)
Executor->>Invocation: bind()
Invocation->>Invocation: dance_name()
Invocation->>Invocation: resolve_dance_descriptor(dance_name)
Invocation->>Invocation: request()
Invocation->>Invocation: affording_holon()
Invocation->>Invocation: invocation_source()
Invocation-->>Executor: BoundDanceInvocation
Executor->>Validator: validate_bound_invocation(bound_invocation)
Validator->>Bound: request_type()
Validator->>Bound: request()
Validator->>Bound: affording_holon_descriptor()
Validator->>Bound: resolved_dance_descriptor()
Validator->>Bound: response_type()
Validator-->>Executor: validation ok
Executor->>Selector: select_implementation(dance_descriptor)
Selector-->>Executor: DanceImplementation
Executor->>Impl: invoke(bound_invocation)
Impl-->>Executor: DanceResponseReference
Executor-->>Caller: DanceResponseReference
5.5 Runtime Validation¶
The name-addressed schema and binding foundation is implemented by
map-holons #652, delivered
through map-holons PR #654.
It establishes required DanceName and AffordingHolon binding through the
effective AffordsDance surface. It deliberately does not implement full
descriptor-aware request/response conformance or an
AffordingHolonRequirement policy enum.
The remaining structural validation requirements below are a follow-up integration with the shared Validation track. Dance must not introduce a local substitute validator.
Executor ingress validation:
DanceInvocation.DanceNameis required and resolves to exactly one Dance through the required affording holon's effective afforded dances.DanceInvocation.AffordingHolonis required and points to a holon accepted by the relationship constraint.DanceInvocation.Requestis required when the resolved dance declares aRequestType.DanceInvocation.Requestmust be absent when the resolved dance does not declare aRequestType.DanceInvocation.Request, when present, structurally satisfies the resolved dance's declaredRequestType.- A supplied request holon's own descriptor reference is optional and is not the
authority for acceptance. Exact descriptor-holon identity with
RequestTypeis not required. InvocationSourceis valid for the ingress path.- The affording holon's effective descriptor affords the resolved Dance through
AffordsDance; a missing or unaffording subject is rejected.
Once delivered, the shared Descriptor-Aware Holon Validation capability
validates the DanceInvocation and request holon structurally at Dance ingress
and validates the produced response before it is returned.
Dance-specific semantic validation remains the responsibility of the selected
implementation as part of ordinary execution logic. Semantic checks such as
value ranges, cross-reference consistency, cycle prevention, or same-space
constraints fail through the normal HolonError channel.
Response-time validation:
- The returned response holon is described by a concrete type extending
DanceResponseType. - The returned response holon conforms to the resolved dance's declared
Responsedescriptor. ResponseBody, when present, points to a holon compatible with the declared response-body contract.- Response-body values conform to the declared response-body contract when one exists.
- Query-produced projection records may be descriptorless when their shape is
derived from the producing
QueryExpression. Diagnosticspoints toDanceDiagnosticholons.
Structural response validation is the inner execution boundary. A TrustChannel then applies its Agreement's role, permission, and information-access promises before valid response data crosses the outbound trust boundary. That disclosure authorization is not Dance validation or Dance dispatch work.
5.6 Implementation Selection And Routing¶
Implementation selection determines which eligible implementation realizes the
resolved Dance contract. The resolved DanceType.RequiredExecutionContext
determines where the Dance must execute. Routing determines how an invocation
reaches that execution environment.
These concerns are related but distinct:
- Implementation selection chooses an eligible
DanceImplementationfor the resolvedDanceType. - Execution context is declared by
DanceType.RequiredExecutionContextand constrains where an implementation may execute. - Routing moves the invocation to that environment when execution cannot occur in the current container.
The current runtime topology commonly realizes the execution contexts defined in Section 5.1 as follows:
- Container-Local implementations execute directly in the invoking Host or Guest.
- Host-Authoritative implementations execute in the native Host.
- Space-Authoritative implementations for locally hosted Holochain Spaces execute in the Guest that has authoritative HDK/DHT access to that Space.
These mappings are deployment realizations rather than Dance semantic categories. In particular, Guest execution must not be treated as synonymous with Space-Authoritative execution. Future AgentSpaces may place the authoritative Home Space behind a TrustChannel, in which case the same Space-Authoritative Dance semantics are preserved while the routing topology changes.
The current Guest runtime therefore remains intentionally narrow. It provides primitive persistence and authority-bearing operations that require direct HDK or DHT semantics. These Guest primitives do not need to be descriptor-driven in their native form. They may continue to use a stable Guest-side service surface as long as that surface remains an implementation detail and Guest-specific request or response shapes do not leak into canonical Dance contracts.
Representative Guest-side primitives include commit holon, delete holon, get holon by id, get related holons, get all related holons, get all holons, and load holons. These primitives are not automatically canonical Dances. They are capabilities available to Space-Authoritative implementations executing against a locally hosted Holochain Space.
DanceImplementation remains the adaptation layer between the canonical Dance
contract and the capabilities available in a particular execution environment.
For example, a canonical Dance may invoke Guest persistence primitives when its
selected implementation is Space-Authoritative and the relevant Home Space is
locally hosted. A future implementation of the same Dance may instead reach a
remote authoritative AgentSpace through a TrustChannel without changing the
Dance's public request or response contract.
For a given invocation, the runtime resolves candidate implementations from the resolved Dance. Candidate implementations must satisfy:
ForDancepoints to the resolvedDanceTypeEngine,AbiId,Version, andCompatare compatible with the runtime and invocation- runtime policy allows the implementation for the invocation source and required execution context
- the implementation can be executed in, or validly routed to, an environment satisfying that execution context
Implementation eligibility must not depend on incidental current topology. A Dance that is semantically Space-Authoritative remains Space-Authoritative whether its Home Space is reached through local Host-to-Guest transport or through a TrustChannel to another AgentSpace.
Multiple active implementations for the same DanceType must be semantically
interchangeable under that Dance's declared contract. They may differ in engine,
deployment location, routing path, optimization strategy, or underlying service
mechanism, but those differences must not change the externally observable
Dance semantics promised by the descriptor.
Selection is deterministic and independent of traversal order, insertion order,
host-local registration order, or incidental routing topology. If no candidate
is eligible, dispatch fails with HolonError. If policy requires uniqueness and
ordering cannot produce a single winner, dispatch fails rather than choosing
nondeterministically.
Once an implementation is selected, the runtime either executes it within the current container or routes the invocation to an environment satisfying the Dance contract's required execution context. Routing is therefore a consequence of execution-context resolution, not a property of the ingress path through which the Dance invocation originally arrived.
5.7 ABI And Wire Boundary¶
The dance ABI is the contract between the runtime that dispatches a dance and
the implementation that executes it. It carries the resolved invocation context
and returns either a response reference or HolonError.
The implementation receives a bound view containing at least:
- invocation holon reference
- canonical
DanceName - resolved
DanceType - resolved
RequiredExecutionContext - optional request holon
- optional declared request type descriptor
- required affording holon and descriptor
- invocation source
- descriptor and value semantics needed to validate request values, relationships, predicates, and operators
- MAP state managers needed to read or create holon state
ABI output:
Result<DanceResponseReference, HolonError>
At command or host/guest boundaries, the equivalent wire shape is:
Result<HolonReference, HolonError>
Opaque ABI payloads must preserve these distinctions:
- invocation failure versus successful response
- dance identity versus selected implementation identity
- affording holon versus request holon
- invocation source versus authorization or provenance claims
- response holon versus response body holon
- response body references versus separately transferred holon state
- diagnostics attached to a successful response versus fatal
HolonError
The Dances design uses HolonReference, HolonCollection, normal holon
serialization/deserialization, typed Rust wrappers over holonic state, and
command or trust-channel adapters that carry references. It does not use
dance-specific invocation wire types, response wire types, request-body wire
types, result wire unions, direct full-Holon result payloads, row-shaped query
result contracts, or a standalone query command envelope.
5.7.1 GetSavedHolonByKey host-to-guest dance¶
GetSavedHolonByKey is the host-to-guest dance boundary for the public
get_saved_holon_by_key(key) operation. Its request carries the supplied key
to the guest; the guest invokes get_saved_holon_by_key and returns the bound
SmartReference for the sole visible head whose actual Key equals the
requested key on success.
The dance preserves the HolonError result unchanged across its wire boundary.
In particular, HolonNotFound, MultipleLineageHeads, and
LineageIntegrityError remain
distinguishable to host, IPC, and loader callers. The shared error variants and
their meanings are defined by Runtime Shared Types.
GetSavedHolonsByBaseKey is obsolete and must not be exposed, invoked, or
retained as a compatibility name. get_lineage_heads_by_key remains an
internal guest helper; no separate GetLineageHeadsByKey dance is defined.
This dance delegates key-to-lineage resolution and visible-head traversal to
the keyed-Owns index and visible-head selection semantics in the
Knowledge Evolution Architecture.
It does not add a dance-specific error envelope or independently reinterpret
the generic SmartLink service operations.
5.8 Descriptor And Value Semantics¶
Dances use descriptor-owned semantics when interpreting properties, values, relationships, and operators. Dance implementation code may perform business logic, navigation, mutation, projection, and orchestration, but it does not become the semantic owner of MAP value interpretation.
Interpretation rules:
- property legality comes from the affording holon's effective
HolonDescriptorwhen the dance is holon-afforded - relationship legality comes from the relevant relationship descriptor
- scalar value validation comes from
ValueDescriptor - operator availability comes from descriptor-backed operator affordances
- unsupported operators fail explicitly with
HolonError - dance-specific code does not silently reinterpret descriptor semantics
Query step implementations check whether the relevant value descriptor supports the requested operator. Query projection steps return projection values, optionally with transient descriptors when useful, rather than inventing ad hoc row shapes.
5.9 Persistence, Audit, And Performance¶
DanceInvocation holons, their request values for the current vertical slice, and successful DanceResponseType-derived response holons are transaction-bound transient holons. The executor rejects staged or saved invocation and response references; durable audit, provenance, or observability state is modeled separately.
Produced state lives in the appropriate MAP state manager:
Nurseryfor staged holonsTransientHolonManagerfor transient holonsHolonsCachefor saved holons
The Dance Schema does not treat invocation and response holons as a durable
execution log. If durable audit, provenance, or observability records are
needed, they should be separate holons or operational logs that record the
relevant execution facts without changing the lifecycle of DanceInvocation and
DanceResponseType-derived response holons.
Any separate durable audit or provenance record should be able to recover:
- invocation holon
- invocation source
- invoked canonical
DanceName - resolved
DanceType - affording holon
- request holon, when present
- affording holon descriptor used for affordance validation
- selected
DanceImplementation - response holon
- response body holon, when present
- diagnostics, when present
- failure classification for failed dispatch or execution
The Dances design does not introduce a dance-specific caching layer. Dance
execution already benefits from the Shared Objects Layer through
HolonReference. Descriptor caching is a Shared Objects Layer decision, not a
Dances design concern. Performance optimizations must not create a second source
of truth for descriptors, affordances, invocations, responses, or response
bodies.
5.10 Contract Cutover¶
The canonical Dance model is holonic: invocation, response, response body, diagnostics, and implementation bindings are represented as holons and relationships. There is no deployed compatibility requirement for the superseded Dance model. The implementation therefore replaces its schema, runtime, ingress, SDK, and test surfaces as one contract cutover rather than retaining translation bridges.
Cutover guidance:
- direct descriptor-reference invocation is replaced by
DanceInvocationholons carrying canonicalDanceName - legacy request and response bridges are removed in favor of
DanceInvocationandDanceResponseType-derived response holons - old-world query/navigation entry points are replaced by the
QueryDanceadapter over independently invocableQueryexecution - row-shaped query results are replaced by
HolonCollection, projection-result holons, or other response-body holons promised by the resolved dance contract - boundary serialization transfers holon state separately from the response reference when the receiving side needs state hydration
- typed Rust structs remain wrappers over
HolonReference, so behavior can evolve without creating new wire types
The cutover preserves the semantic distinction between the canonical
dance name requested by the caller, the DanceType descriptor resolved through
the affording holon's effective affordances, the descriptor that affords the dance, the implementation selected by
the runtime, the response holon returned by successful execution, the response
body holon that carries result state, and HolonError returned by failed
execution.
6) Deferred Design Decisions¶
DanceEventis deferred until the asynchronous event-handling architecture is designed and a concrete event consumer requires it.
Appendix A) Superseded Surface Removal¶
The following superseded surfaces have no compatibility role in the target contract and are removed with their callers and tests. They must not be renamed, retained as deprecated bridges, or used as a migration path.
| Surface | Target disposition |
|---|---|
DanceInvocation, DanceResponseType, DanceImplementation, Projection, and the canonical ResponseBody relationship |
Active canonical contract |
DanceRequest, DanceResponse, RequestBody, and old response-body wrapper types |
Remove with callers and tests |
ResponseStatusCode, ResponseBodyType, ImplementsDance, ImplementedFor, InvokesDance, InvokedBy, DanceInput, and DanceInputFor |
Remove from schema, generated surfaces, runtime, and tests |
| Old query-navigation DTOs and entry points | Remove only in their separately scoped Query cutover; do not retain them as Dance compatibility bridges |