v0.9.5 — Seamster Extraction and Graph.Validate Race Fix
Released 2026-07-07. GitHub release.
This release fixes a concurrency bug in graph validation and moves the engine’s test-only instrumentation into a
standalone module. Both live in one commit (0c113c3).
Fixed
- Data race in
workflow.Graph.Validate.Validate()built the fan-out to fan-in convergence map as a side effect stored on the graph. Because a graph is loaded once and shared across concurrentCreatecalls, two validations (or a validation racing aMarshalJSON) wrote and read that field at the same time, which the race detector flagged and which could corrupt the map.Validate()is now pure over the graph’s immutable definition and stores nothing on the graph.
Changed
Fan-in routing is now derived at dispatch, not persisted. The fan-out to fan-in map is a pure function of the graph structure, so the engine computes it per flow from the frozen graph definition (new internal package
internal/faninmap) and caches it beside the parsed graph. It is no longer written into the stored graph JSON, so a workflow graph carries only its author-defined shape over the wire.Test seams extracted to the
seamstermodule. The fault-injection and checkpoint instrumentation the engine uses in white-box tests now lives ingithub.com/microbus-io/seamsterv0.1.0 (a new, standard-library-only dependency). The engine embeds oneseamster.Seamsterase.seamsand consults it directly (IsFault,Checkpoint,Inject,Wait,Break,Resume). The seam is inert in production by construction.engine/debug.gois renamedengine/seams.goand reduced to the engine’s fault and checkpoint names plusdeliverFailureLost, the one consult that needs a database read.
API Changes
Removed
workflow.Graph.FanInForand thefanOutToFanInJSON field.Graphnow exposes only its definition and validation. The fan-in lookup thatFanInForprovided is an engine concern, served byinternal/faninmap. A pre-existing graph JSON that still carries afanOutToFanInfield decodes cleanly (the field is ignored), and the routing is recomputed from the structure, so persisted flows keep working.This removes an exported method, so downstream code calling
graph.FanInFor(...)will not compile. If that matters for the version line, consider taggingv0.10.0instead ofv0.9.5.
Docs
- Updated
engine/CLAUDE.mdanddocs/graphs.mdto describe pure validation and the dispatch-time fan-in map.
Upgrade Notes
- No schema migration. No behavior change for existing flows.
go get github.com/microbus-io/[email protected]pulls inseamsterv0.1.0 automatically.