Holons Shared Objects Layer Design Spec (v0.1)¶
Status¶
Proposed
Purpose¶
The Holons Shared Objects Layer defines the runtime object model that is shared across MAP host, guest, command, dance, query, loader, and SDK-facing execution surfaces. It is the home for in-memory holon lifecycle semantics, transaction staging semantics, relationship mutation intent, and commit-facing runtime contracts.
For the broader architectural frame that relates this layer to integrity-layer
persistence, the reference layer, and typed core structs, see
holon-layered-representation-design-spec.md.
This spec is intentionally scoped to the shared runtime objects that determine how holons move through transient, staged, saved, abandoned, and committed states. It does not define persistence storage formats, descriptor schema structure, command routing, or user-facing SDK ergonomics except where those surfaces depend on shared object semantics.
Layer Boundary¶
The Holons Shared Objects Layer owns:
- runtime holon variants such as
TransientHolon,StagedHolon, andSavedHolon - references to those runtime objects
HolonState,StagedState,SavedState, andValidationStateHolonCollectionand relationship map phase semantics- nursery-held staged object state
- mutation-time classification of staged changes
- the commit-facing meaning of staged actions and relationship anchors
It does not own:
- Holochain entry or link storage mechanics
- descriptor schema definitions
- descriptor-owned semantic metadata such as
IsDefinitional - command, dance, query, or SDK-specific public API shape
- issue-specific implementation sequencing
Descriptors remain the semantic source of truth for relationship metadata. The shared objects layer consumes descriptor metadata to classify runtime mutation intent.
Core Concepts¶
HolonState¶
HolonState is an access-control state for a runtime holon object.
Mutablemeans the object may accept write operations permitted by its phase.Immutablemeans the object may be read, cloned, committed where applicable, or abandoned where applicable, but may not accept ordinary writes.
HolonState is orthogonal to StagedState. A staged holon can be mutable while
it is being edited and immutable after it is committed or abandoned.
ValidationState¶
ValidationState records whether the runtime holon has descriptor-backed
validation work outstanding or completed. It does not determine whether commit
creates a new holon node, updates an existing holon node, or performs graph-only
relationship persistence.
StagedHolon¶
A StagedHolon is a transaction-scoped runtime object held by the Nursery. It
can represent:
- a new holon that has never been persisted
- an existing holon cloned for possible update
- an existing holon used only as a graph mutation context
- a version-producing update to an existing holon
- a completed or abandoned staged object
Staging an existing holon is not itself a persistence obligation. It is a statement of intent and a place to collect possible mutation intent. Commit work is created only when an accepted mutation changes the staged action.
StagedState Contract¶
StagedState is the action state machine for staged holons. It is not merely a
flag that a holon is in the Nursery. It tells commit what kind of action, if
any, is required.
Canonical staged action states:
| State | Meaning |
|---|---|
ForCreate |
A new holon will create a new persisted holon node during commit. |
ForUpdate |
An existing holon has been staged for possible update, but no commit-relevant mutation has occurred. |
ForUpdateGraphOnly |
An existing holon has only non-definitional relationship mutations. Commit performs graph writes without creating a new holon node version. |
ForUpdateNewVersion |
An existing holon has a version-producing mutation. Commit creates a new persisted holon node version. |
Committed(LocalId) |
Commit has completed for this staged holon and resolved the local relationship anchor. |
Abandoned |
The staged holon has been intentionally abandoned and will not be committed. |
If an implementation currently exposes a legacy ForUpdateChanged name, that
name denotes the same semantic role as ForUpdateNewVersion: an existing holon
has been changed in a way that requires a new persisted version. Runtime
contracts should converge on the semantic state names above.
Mutation Triggers¶
State transitions should be labeled and implemented by trigger, not by effect. The target state expresses the effect.
Property Mutation¶
A property mutation means any accepted operation that adds, changes, or removes a property value on an existing staged holon.
Property mutations are always version-producing for existing holons.
Relationship Mutation¶
A relationship mutation means any accepted operation that adds or removes a relationship occurrence on an existing staged holon.
Relationship mutations must be classified by the relationship descriptor's
schema-backed IsDefinitional value:
IsDefinitional == truemeans the relationship mutation is version-producing.IsDefinitional == falsemeans the relationship mutation is graph-only.
Mutation APIs must resolve the relevant relationship descriptor before accepting
a relationship mutation that affects staged action. If the descriptor cannot be
resolved, or if IsDefinitional cannot be read, the mutation must fail loudly.
The shared objects layer must not silently default either to graph-only or to
version-producing behavior.
For ForCreate, IsDefinitional does not decide whether a node is created. A
new holon creates a new node by construction. Descriptor metadata may still
matter for validation and relationship legality.
StagedHolon State Machine¶
stateDiagram-v2
state "Committed(LocalId)" as Committed
[*] --> ForCreate: new_for_create / new_from_clone_model / stage_new_holon
[*] --> ForUpdate: stage_new_version / stage_for_update
ForCreate --> Abandoned: abandon_staged_changes
ForCreate --> Committed: commit
ForUpdate --> Abandoned: abandon_staged_changes
ForUpdate --> ForUpdate: commit with no mutation
ForUpdate --> ForUpdateNewVersion: property mutation
ForUpdate --> ForUpdateNewVersion: relationship mutation, IsDefinitional == true
ForUpdate --> ForUpdateGraphOnly: relationship mutation, IsDefinitional == false
ForUpdateGraphOnly --> Abandoned: abandon_staged_changes
ForUpdateGraphOnly --> Committed: commit
ForUpdateGraphOnly --> ForUpdateGraphOnly: relationship mutation, IsDefinitional == false
ForUpdateGraphOnly --> ForUpdateNewVersion: property mutation
ForUpdateGraphOnly --> ForUpdateNewVersion: relationship mutation, IsDefinitional == true
ForUpdateNewVersion --> Abandoned: abandon_staged_changes
ForUpdateNewVersion --> Committed: commit
ForUpdateNewVersion --> ForUpdateNewVersion: property mutation
ForUpdateNewVersion --> ForUpdateNewVersion: relationship mutation
Committed --> Committed: commit
Transition Semantics¶
ForCreate¶
ForCreate is entered when a new staged holon is created from a transient holon
or clone model whose result is intended to be a new holon rather than an update
to an existing persisted holon.
Commit creates a new holon node and resolves Committed(LocalId) to the new
node's local id.
ForUpdate¶
ForUpdate is entered when a caller stages an existing holon for possible
update. This usually requires cloning the previous version into a transaction
editing context.
ForUpdate is only a statement of intent. If the caller does not make a
property mutation or relationship mutation, there is nothing to persist. Commit
must perform no node write and no graph write for that staged holon.
ForUpdateGraphOnly¶
ForUpdateGraphOnly is entered when an existing staged holon receives at least
one relationship mutation whose descriptor has IsDefinitional == false, and no
version-producing mutation has occurred.
Commit must not create a new holon node version for this state. It must persist
only the relevant graph relationship changes and resolve Committed(LocalId) to
the existing source holon's local id.
ForUpdateNewVersion¶
ForUpdateNewVersion is entered when an existing staged holon receives either:
- a property mutation
- a relationship mutation whose descriptor has
IsDefinitional == true
Commit creates a new persisted holon node version and resolves
Committed(LocalId) to the new version's local id.
Once an existing staged holon reaches ForUpdateNewVersion, later
non-definitional relationship mutations must not downgrade it to
ForUpdateGraphOnly. Definitional mutations dominate graph-only mutations.
Committed(LocalId)¶
Committed(LocalId) records that commit has completed the staged action and
resolved the source local id to use for relationship persistence.
The LocalId means:
| Source state before commit | Committed(LocalId) value |
|---|---|
ForCreate |
the new holon node id |
ForUpdateGraphOnly |
the existing/original holon node id |
ForUpdateNewVersion |
the new holon node version id |
Because Committed(LocalId) is the relationship anchor result, all relationship
persistence paths must consume a single resolved anchor rather than duplicating
source-selection logic.
Abandoned¶
Abandoned is terminal for ordinary mutation. Commit skips abandoned staged
holons. Abandoning a staged holon makes it immutable.
Relationship Mutation and Baseline Content¶
A staged clone may contain baseline properties and baseline relationship content copied from a previous version so the caller can inspect and edit the holon inside the transaction.
Baseline content is not itself write intent.
For update states, relationship persistence must be based on accepted staged relationship mutations, not merely on every relationship collection present in the editing snapshot. Otherwise a no-op update or graph-only update could accidentally duplicate existing relationship writes or create a new version without an accepted version-producing trigger.
Relationship Anchoring¶
Commit must expose exactly one resolved source LocalId for relationship
persistence for each staged holon that has relationship work to perform.
The anchoring rule is:
| Staged action | Node persistence | Relationship anchor |
|---|---|---|
ForCreate |
create new node | new node LocalId |
ForUpdate |
none | none |
ForUpdateGraphOnly |
none | existing/original LocalId |
ForUpdateNewVersion |
create new version | new version LocalId |
Abandoned |
none | none |
Committed(LocalId) |
already resolved | contained LocalId |
Forward and inverse SmartLink persistence must use the same resolved
relationship anchor. Inverse persistence must not independently infer a source
from stale staged state.
Invariants¶
ForUpdaterepresents intent to update, not a persistence obligation.- Property mutations on existing holons are always version-producing.
- Relationship mutations on existing holons are classified by descriptor-backed
IsDefinitional. IsDefinitional == truerelationship mutations are version-producing.IsDefinitional == falserelationship mutations are graph-only unless the staged holon has already become version-producing.- Version-producing mutations dominate graph-only mutations.
- A staged holon must never downgrade from
ForUpdateNewVersiontoForUpdateGraphOnly. - Descriptor lookup failure during relationship mutation classification is an explicit error.
- Commit source anchoring must be centralized and shared by all relationship persistence paths.
- Baseline relationships copied into a staged update context are not themselves relationship write intent.