Added
ManualTestClockgained deterministic wait primitives:
waitForSleepers(atLeast:),waitForSleepRegistrations(toReach:), and the
gatedadvance(by:onceSleepersReach:). They suspend on the sleep
registration event itself, replacing the yield-count and wall-clock
polling that time-sensitive tests previously needed before advancing the
clock.sleepRegistrationCountis now public to support the
registration-count wait.PhaseMap.derivedGraphnow carries a suggested root when exactly one
declared source phase never appears as a transition target, so the
root-inferringvalidate/validationReportoverloads work directly on
acyclic topologies instead of always reporting.missingRoot. Cyclic
topologies can pass the entry phase explicitly through the new
PhaseMap.derivedGraph(root:).
CI
actions/checkoutis now pinned to one SHA (v6.0.3) across every
workflow; ci.yml and docs.yml had silently stayed on v6.0.2 while cd.yml
moved ahead. The pin gate now also requires a human-readable release-tag
comment next to each SHA and rejects the same action pinned to different
SHAs in different workflows. Documentation builds now also run for pull
requests targetingdevelop, so DocC regressions surface before the
release branch.
Tests
- The composition primitives gained dedicated behavioral coverage
(ReducerCompositionTests): declaration-order cumulative mutation,
builder branch/optional semantics, effect merging and lifting through
Scope, theIfLet/IfCaseLetmissing-child.ignorepolicy, and
id-routing throughForEachReducer/ForEachIdentifiedReducer. These
semantics were previously pinned only indirectly through feature
fixtures and env-gated perf benchmarks.
Documentation
- The consumer guides, canonical sample tests, and
ARCHITECTURE_CONTRACT.mdnow teach the deterministicManualTestClock
waits instead ofsleeperCountpolling with yield counts or wall-clock
sleeps; the sample's hand-rolled polling helper is removed. RELEASING.mdreflects the published 5.0.0 state, binding documentation
namesbinding(_:to:)as the canonical spelling across all READMEs, and
deliberate runtime/diagnostic boundaries (SelectionCache retention,
composite task priority, phase-totality scope) are recorded next to the
code they describe.
Deprecated
PhaseMapExpectedTrigger.predicate(_:sampleAction:)is deprecated in
favor of the identicalinit(_:sampleAction:). The factory never took a
predicate closure; coverage has always been decided by running the sample
action through the declared transitions.
Fixed
@InnoFlownow accepts the Self-qualified body signature
var body: some Reducer<Self.State, Self.Action>and the
module-qualified constraint spellingsInnoFlow.Reducer/
InnoFlowCore.Reducer. All of these resolve to the same declarations, so
the qualified forms were being rejected incorrectly. Qualification
through any other base type is still refused, and the diagnostics name
the accepted spellings.
Changed
-
EffectTask.potentialCancellationIDsis now computed once at effect
construction (children carry their own cached sets, so composition costs
O(children)) instead of re-walking the whole effect tree with freshSet
allocations on every execution. Subtrees containing a.lazyMapnode
keep the access-time walk so laziness is preserved. -
IdentifiedArray.remove(ids:)now removes the batch in a single filter
pass with one index rebuild (O(n + k)) instead of paying an O(n) element
shift plus an O(n) index rebuild per removed id (O(n·k)). Semantics are
unchanged: missing ids are skipped, duplicates are tolerated, and
insertion order is preserved. -
The per-action dispatch entry points of the composition primitives
(Reduce,Scope,IfLet,IfCaseLet,ForEachReducer,
ForEachIdentifiedReducer) and the O(1)IdentifiedArrayaccessors are
now@inlinable, so feature modules that importInnoFlowCoreget
cross-module specialization on the reducer hot path instead of paying an
unspecialized generic call per composition node per action.
EffectTask.isNoneis nowpublic(previouslypackage) because the
inlinedReduce.reducebody needs it to skip.nonechildren. -
swift-syntaxis now constrained to the single toolchain line
"603.0.0"..<"604.0.0"instead of an exact pin, so consumer graphs that
carry other macro packages can resolve a shared 603.x patch. Maintainer
reproducibility stays onPackage.resolved, which keeps recording the
verified 603.0.1; resolved-patch upgrades follow the release-hardening
checklist inRELEASING.mdbecause macro expansion snapshots track the
SwiftSyntax test-support rendering.