Skip to content

Harden state exploration with fail-fast validation and immutable graph diagnostics - #40

Open
Tomás Pérez Álvarez (Tomperez98) wants to merge 1 commit into
microsoft:mainfrom
Tomperez98:harden-state-exploration
Open

Harden state exploration with fail-fast validation and immutable graph diagnostics#40
Tomás Pérez Álvarez (Tomperez98) wants to merge 1 commit into
microsoft:mainfrom
Tomperez98:harden-state-exploration

Conversation

@Tomperez98

Copy link
Copy Markdown
Contributor

Summary

This change hardens Accordant's state exploration and system-checking boundaries so invalid models fail close to their source instead of producing delayed or ambiguous failures. It also makes graph construction deterministic and safer to test by snapshotting externally-owned collections, protecting graph objects from mutation, and preserving actionable exception context.

The implementation keeps the fast path inexpensive: already-frozen states avoid recomputation, and expensive canonical comparisons remain limited to hash/signature collision paths.

What changed

Fail-fast input and model validation

  • Validate StateGraph.ExploreStateGraph inputs at the public boundary:
    • null states and step collections
    • invalid depth values
    • null step functions
    • empty step-function IDs
    • duplicate step-function IDs
  • Validate all SystemChecker batches before executing any step function or hook.
  • Snapshot caller-owned step sequences before exploration to prevent mid-run collection mutation.
  • Validate combined active and concurrent step functions before advancing a profile.
  • Validate StateProfile entries when assigned, including state and step-function invariants.
  • Preserve the existing behavior that a null profile step-function list means no enabled step functions.

State immutability and mutation detection

  • Freeze the starting state before it is hashed or interned into a graph.
  • Freeze successor states returned by custom IStepFunction implementations.
  • Fail clearly when an IState implementation does not become frozen after Freeze().
  • Make freeze-validation configuration instance-scoped instead of global, preventing tests and parallel runs from leaking configuration through static state.
  • Preserve the per-state freeze-validation setting when cloning.
  • Run frozen-state mutation validation even when user step-function code throws.

Safer and more deterministic state graphs

  • Use node object identity for traversal bookkeeping instead of the display fingerprint.
  • Make node interning collision-safe:
    • use a compact hash/signature key for the normal path
    • compare canonical state representations only within matching buckets
  • Make graph node and edge state immutable after construction.
  • Snapshot node step functions and expanded edges.
  • Cache lazy-expansion failures and rethrow the original exception rather than exposing a partial graph.
  • Preserve traversal paths as read-only diagnostic snapshots.
  • Use stable invariant-culture fingerprint formatting.
  • Generate DOT node IDs from graph identity rather than truncated fingerprints, avoiding accidental ID collisions.
  • Deduplicate edges by step-function ID and interned target-node identity.

Step-function contract hardening

  • Add immediate validation for BaseStepFunction.Apply arguments.
  • Add an optional stable BaseStepFunction identifier while retaining GUID-backed default identity.
  • Validate step results before freezing or propagating them.
  • Snapshot and validate async-operation transition delegates.
  • Report clear state-type mismatches from AsyncOperation.
  • Normalize and validate contract predecessor IDs:
    • reject empty IDs
    • reject duplicate IDs
    • snapshot caller-owned collections
  • Reject predecessor configuration changes after a contract step has been applied.
  • Validate successful contract verification results before converting them into graph transitions.

Exception diagnostics

  • Make StepFunctionApplicationException diagnostic properties read-only.
  • Snapshot PathToNode so later mutations cannot corrupt failure diagnostics.
  • Fail immediately when exception, node, path, or step-function context is missing.

Test-generation safety

  • Snapshot edge lists before generating concurrent combinations so enumeration is not affected by external collection changes.

Tests

Added coverage for:

  • state-profile collection snapshots and read-only behavior
  • invalid state-graph arguments and step-function collections
  • state-hash collision handling
  • unfreezable state implementations
  • pre-validation of all SystemChecker batches
  • mutation detection when step application throws
  • async transition snapshots and invalid transitions
  • contract verification result validation
  • predecessor-ID validation and configuration lifecycle
  • lazy expansion failure caching
  • immutable graph and exception diagnostic properties
  • eager/lazy graph equivalence and path reconstruction
  • state freeze validation configuration and clone propagation

Validation

The following checks pass:

dotnet test Tests/Accordant.Tests/Accordant.Tests.csproj --no-restore
dotnet test Tests/Accordant.Operations.Tests/Accordant.Operations.Tests.csproj --no-restore
dotnet test Accordant.slnx --no-restore

The targeted core test suite passes 40 tests and the operations test suite passes 182 tests.

Compatibility notes

This hardens previously mutable public surfaces. Callers should no longer rely on mutating these objects after construction or graph creation:

  • StateProfile collections are snapshotted and read-only.
  • StateGraphNode and StateGraphEdge properties are read-only.
  • StepFunctionApplicationException diagnostics are read-only snapshots.
  • Frozen-state implementations must make Freeze() establish IsFrozen.
  • ContractStepFunction predecessor IDs must be configured before application.
  • Freeze-validation configuration is now set on an individual State instance rather than through a static global property.

@Tomperez98 Tomás Pérez Álvarez (Tomperez98) changed the title # Harden state exploration with fail-fast validation and immutable graph diagnostics Harden state exploration with fail-fast validation and immutable graph diagnostics Sep 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant