Test Harness Design Spec
TestReference — Normative Definition with Structural & Rust-Level Detail¶
This section defines what a TestReference is, what it does, and how it is represented structurally and in Rust.
It is normative for fixture support, execution support, and the dance test language.
What a TestReference Is¶
A TestReference is an immutable, fixture-time specification of a single test step.
It is the sole artifact passed from the fixture phase to the execution phase that completely specifies:
- What holon the step should operate on, and
- What holon state the step is expected to produce.
A TestReference does not represent runtime state, execution results, or mutable entities.
It is a declarative contract describing intent (source) and expectation (result) for exactly one test step.
Structural Overview¶
A TestReference consists of two role-specific components:
TestReference
├─ SourceHolon (execution input)
└─ ExpectedHolon (execution expectation)
These two components use a shared lifecycle vocabulary but serve distinct purposes.
Shared Lifecycle Vocabulary¶
All fixture-time holon intent is expressed using a shared descriptive enum.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum TestHolonState {
Transient,
Staged,
Saved,
Abandoned,
Deleted,
}
This enum is:
- Descriptive, not behavioral
- Interpreted differently depending on context (source vs expected)
- Used by fixture support and execution support
SourceHolon — Execution Input¶
Purpose¶
SourceHolon specifies the starting holon that a test step should operate on.
It exists solely to support execution-time resolution.
Rust Structure¶
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SourceHolon {
snapshot: TransientReference,
state: TestHolonState,
}
Field Semantics¶
-
snapshot- Identifies a fixture-time transient snapshot
- Serves as the source snapshot token
- Its
TemporaryIdis used to:- locate the logical FixtureHolon
- resolve the execution-time source holon
- May be redirected via fixture-level head advancement (commit)
-
state- Intended lifecycle state when the step executes
- Guides resolution behavior
- Never mutated
Conceptual Meaning¶
The SourceHolon answers:
“Given everything that has happened so far, which execution-time holon should this step run against?”
It does not describe what the step produces.
ExpectedHolon — Execution Expectation¶
Purpose¶
ExpectedHolon specifies the holon state that should exist after the step executes.
It is used only for validation and chaining.
Rust Structure¶
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ExpectedHolon {
snapshot: Option<TransientReference>,
state: TestHolonState,
}
Field Semantics¶
-
snapshotSome(snapshot)for all non-deleted outcomesNoneiffstate == TestHolonState::Deleted- Identifies the expected snapshot produced by this step
- Not subject to execution-time source redirection
- Immutable historical fact
-
state- Expected lifecycle state after execution
- Used only for assertions
Conceptual Meaning¶
The ExpectedHolon answers:
“What holon state should exist as a result of this step?”
It is never resolved to a runtime holon.
However, fixture-time adders may still reinterpret a target token through
FixtureHolons when constructing a new expected relationship graph. In that
case, the adder embeds the logical target holon's current expected head
snapshot, not the literal historical snapshot carried by the token.
TestReference — Combined Contract¶
Rust Structure¶
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct TestReference {
source: SourceHolon,
expected: ExpectedHolon,
}
Semantics¶
- Immutable once created
- Opaque to TestCase authors and adder authors
- Safe to pass and reuse across steps
- The sole artifact executors receive to understand step intent
A TestReference binds together:
- Source intent (what to operate on)
- Expected outcome (what should result)
for exactly one test step.
Tight Chaining Rule (Essential Invariant)¶
The design enforces tight chaining:
The ExpectedHolon snapshot produced by step N is the conceptual SourceHolon snapshot for step N+1.
This chaining is fixture-time and intent-based.
In Rust terms, this is supported by an explicit conversion:
impl ExpectedHolon {
pub fn as_source(&self) -> SourceHolon {
SourceHolon {
snapshot: self
.snapshot
.as_ref()
.expect("Deleted holons cannot be used as source")
.clone(),
state: self.state,
}
}
}
Fixture-Time Head Advancement (Commit Semantics)¶
commit introduces a critical special case.
- Commit mints new TestReferences with new snapshot identities
- These snapshots become the head for a logical FixtureHolon
- TestCase authors continue using older TestReferences
As a result, the SourceHolon.snapshot inside an older TestReference may no
longer be the snapshot a later adder should use as the next source. Adders use
FixtureHolons during fixture construction to choose the logical holon's
current head and mint a new TestReference for the later step.
Key constraints:
- Only SourceHolon snapshots participate in fixture-time source derivation
- ExpectedHolon snapshots are never used for execution-time source lookup
- Relationship adders may still resolve target tokens to the current expected head snapshot during fixture-time graph construction
- TestReferences themselves are never mutated
This preserves immutability while allowing logical continuity across commit boundaries.
What a TestReference Is Not¶
A TestReference is not:
- a runtime handle
- a mutable reference
- a unique holon identity
- an execution result
- a guarantee that its embedded snapshot will be the execution source
One-Sentence Definition¶
A TestReference is an immutable fixture-time contract that specifies, for a single test step, the intended source holon to execute against and the expected holon state the step should produce — while
FixtureHolonsseparately tracks logical fixture-holon heads so later adders can interpret older tokens correctly after commit.
This definition should be treated as foundational and normative across the Dance Test Framework.
FixtureHolons & FixtureHolon — Normative Definition with Structural & Rust-Level Detail¶
This section defines what FixtureHolons and FixtureHolon are, why they exist, and how they are represented structurally and in Rust.
It is normative for fixture support, commit semantics, and fixture-time source and relationship-target selection.
Why FixtureHolons Exist¶
TestReferences describe individual test steps.
They do not describe entity identity across steps.
However, the Dance Test Framework must reason about:
- which snapshots refer to the same logical holon
- which snapshot is the current head of that holon
- how
commitadvances holon state across multiple steps - how older TestReferences remain valid after commit
This requires an explicit fixture-time concept of logical holon identity.
That concept is FixtureHolon.
FixtureHolon — Logical Holon Identity (Fixture-Time)¶
What a FixtureHolon Is¶
A FixtureHolon represents a single logical holon as it evolves across multiple test steps during the Fixture Phase.
It is:
- fixture-time only
- mutable
- authoritative for lifecycle state and head selection
- never exposed to TestCase authors or executors
A FixtureHolon answers the question:
“Across all the snapshots created so far, what is the current state of this logical holon?”
Rust Structure¶
#[derive(Clone, Debug)]
pub struct FixtureHolon {
pub id: FixtureHolonId,
pub state: TestHolonState,
pub head_snapshot: TransientReference,
}
Field Semantics¶
-
id- Stable fixture-time identity for this logical holon
- Used only internally by the harness
- Multiple TestReferences may map to the same
FixtureHolonId
-
state- Current lifecycle state of the holon at fixture time
- Authoritative summary derived from the latest head snapshot
- Updated by adders and by
commit - Examples:
Transient→Staged→SavedSaved→DeletedStaged→Abandoned
-
head_snapshot- The authoritative snapshot token for this holon
- Always refers to the most recent snapshot that represents the holon’s state
- Updated whenever:
- a step mutates the holon
- a commit advances the holon
- This is the mechanism that enables fixture-time head selection
FixtureHolons — Fixture-Time Registry¶
What FixtureHolons Is¶
FixtureHolons is the authoritative fixture-time registry for:
- all TestReferences ever minted
- all logical FixtureHolons
- the mapping between snapshot tokens and logical holons
It is the only component allowed to:
- mint TestReferences
- create FixtureHolons
- advance head snapshots
- interpret commit semantics
Rust Structure¶
pub struct FixtureHolons {
pub tokens: Vec<TestReference>,
pub holons: BTreeMap<FixtureHolonId, FixtureHolon>,
pub snapshot_to_holon: BTreeMap<TransientReference, FixtureHolonId>,
}
Field Semantics¶
-
tokens- Append-only history of all TestReferences minted during fixture construction
- Preserves complete fixture-time intent
- Never mutated or reordered
- Used for:
- debugging
- diagnostics
- executor coordination
-
holons- Map of logical holon identity → FixtureHolon
- One entry per logical holon in the test case
- Authoritative source of:
- lifecycle state
- current head snapshot
-
snapshot_to_holon- Maps any snapshot token to its owning FixtureHolon
- Enables:
- interpreting older TestReferences as logical-holon handles when deriving later source snapshots
- resolving target tokens to current expected heads when building expected relationship graphs
- reuse of prior steps (e.g. delete-after-delete)
- Critical for commit semantics
Head Selection — Where It Actually Lives¶
Head selection is not a TestReference concept.
It is a FixtureHolons responsibility.
What Head Selection Means¶
- A TestReference may embed a snapshot token that is no longer current
- The snapshot still identifies the logical holon
- FixtureHolons determines the current head snapshot for that holon
How It Works¶
When an adder derives the source for a later step:
- The SourceHolon snapshot token is extracted from the TestReference
snapshot_to_holonmaps it to aFixtureHolonId- The corresponding
FixtureHolon.head_snapshotis retrieved - That head snapshot is used to mint the new TestReference's source side
This is what allows:
- commit to mint new snapshots
- older TestReferences to remain valid
- test authors to ignore token churn
Relationship-Target Expected Resolution¶
Relationship adders use a different FixtureHolons interpretation path from
fixture-time source derivation.
When an adder needs to embed relationship targets into a new expected graph:
- The target token's expected snapshot id is extracted
snapshot_to_holonmaps it to the owningFixtureHolonId- The corresponding
FixtureHolon.head_snapshotis retrieved - That current expected head snapshot is embedded as the relationship target
This prevents stale target snapshots from being frozen into expected graphs when the fixture author passes an older token for a logical holon whose head has advanced.
So there are three distinct harness behaviors:
- fixture-time source derivation uses the source side of
TestReferenceas a handle to the logical holon's current head - fixture-time relationship-target expected resolution uses the expected side token as a handle to the logical holon's current expected head
- execution-time source resolution uses the source side of the step token
to look up recorded runtime handles through
ExecutionHolons
Those behaviors are related, but they are not the same operation.
Commit Semantics (Fixture-Time)¶
commit operates over FixtureHolons, not TestReferences.
Commit Responsibilities¶
For each FixtureHolon whose state == Staged:
- Clone the head snapshot
- Mint a new TestReference with:
- ExpectedHolon.state =
Saved - A new snapshot token
- ExpectedHolon.state =
- Update:
FixtureHolon.head_snapshot→ new snapshotFixtureHolon.state→Saved
- Append the new TestReference to
tokens
Important Constraints¶
- Commit must mint new TestReferences
- Commit must not mutate existing TestReferences
- Commit does not return TestReferences to test authors
- Head advancement is purely internal to FixtureHolons
Saved-Content Comparison Semantics¶
MatchSavedContent compares saved roots by:
- essential holon content
- exact definitional relationship presence/member agreement
Implications:
- non-definitional persisted edges, including commit-generated inverse SmartLinks, are intentionally ignored by saved-content equality
- definitional relationship members are matched by saved holon identity where the harness has recorded the committed realization
- each saved fixture holon is still compared independently as its own root, so nested member content is not recursively revalidated from every relationship occurrence
Saved-lookup stubs remain a harness-specific special case for holons created outside the fixture ledger.
What FixtureHolons Is Not¶
FixtureHolons is not:
- a runtime registry
- an execution cache
- visible to executors
- responsible for validation or assertions
It exists solely to make fixture-time intent coherent and executable.
One-Sentence Definitions¶
FixtureHolon
A mutable, fixture-time representation of a single logical holon that tracks its lifecycle state and current head snapshot across test steps.
FixtureHolons
The authoritative fixture-time registry that mints TestReferences, tracks logical holon identity, advances head snapshots (especially during commit), and enables adders to derive correct source snapshots and expected relationship targets.
These definitions should be treated as normative throughout the Dance Test Framework.