Skip to content

Fix initial choice state decoding - #201

Merged
SandroMaglione merged 1 commit into
mainfrom
codex/fix-initial-choice-from
Aug 30, 2026
Merged

Fix initial choice state decoding#201
SandroMaglione merged 1 commit into
mainfrom
codex/fix-initial-choice-from

Conversation

@SandroMaglione

Copy link
Copy Markdown
Member

Summary

  • Decode schema-backed state constructions before an initial choice resolver reads containingState or ancestors.
  • Preserve encoded target values for normal entry planning while giving choice selection the same decoded state view as ordinary active-state entry.
  • Add public nested-state coverage and forced generic-versus-compiled invoke/retry lifecycle coverage.

Changeset

  • Added or updated for a library or package-metadata change
  • Not required because this PR does not change a publishable package

Patch changeset for @typeonce/effect-machine.

Validation

  • pnpm check
  • Automated type-performance measurement passed or was not required
  • Automated runtime- and memory-performance measurement passed or was not required

Focused validation: 43 choice and strategy-differential tests passed.

Runtime performance: local pnpm perf:runtime smoke passed; the PR workflow base-versus-PR comparison remains authoritative. Type-performance validation is not required because this change does not alter the public TypeScript API or inference.

@github-actions

Copy link
Copy Markdown
Contributor

Type performance

Measured with TypeScript 6.0.3 and skipLibCheck=true.

ScenarioBasePRDifference
Effect only55550 (0.0%)
Import effect-machine55550 (0.0%)
Machine.states (3 states)3,0393,0390 (0.0%)
Machine.make (3 states, 2 events)10,78710,7870 (0.0%)
machine.handle (3 states, 2 transitions)28,55128,5510 (0.0%)
fluent transition (10 named branches)122,775122,7750 (0.0%)
fluent invocation (state-dependent Effect)108,429108,4290 (0.0%)
machine.handle (depth 24)207,970207,9700 (0.0%)
machine.handle (wide depth 16)236,332236,3320 (0.0%)
machine.handle (parallel/history/choice)144,812144,8120 (0.0%)
machine definition (3 independent implementations)143,617143,6170 (0.0%)
machine exact input/output/error/services129,873129,8730 (0.0%)
execution adapter readiness136,469136,4690 (0.0%)

Marginal instantiations are measured against the matching setup without that API call:

ScenarioBasePRDifference
Import effect-machine000
Machine.states (3 states)2,9842,9840 (0.0%)
Machine.make (3 states, 2 events)7,7407,7400 (0.0%)
machine.handle (3 states, 2 transitions)17,76417,7640 (0.0%)
fluent transition (10 named branches)112,498112,4980 (0.0%)
fluent invocation (state-dependent Effect)99,01899,0180 (0.0%)
machine.handle (depth 24)187,474187,4740 (0.0%)
machine.handle (wide depth 16)217,043217,0430 (0.0%)
machine.handle (parallel/history/choice)124,167124,1670 (0.0%)
machine definition (3 independent implementations)127,576127,5760 (0.0%)
machine exact input/output/error/services115,217115,2170 (0.0%)
execution adapter readiness106,299106,2990 (0.0%)
Check times (informational)
ScenarioBasePR
Effect only0.03s0.03s
Import effect-machine0.03s0.03s
Machine.states (3 states)0.10s0.10s
Machine.make (3 states, 2 events)0.16s0.15s
machine.handle (3 states, 2 transitions)0.25s0.24s
fluent transition (10 named branches)0.54s0.56s
fluent invocation (state-dependent Effect)0.56s0.54s
machine.handle (depth 24)0.78s0.77s
machine.handle (wide depth 16)0.79s0.80s
machine.handle (parallel/history/choice)0.65s0.63s
machine definition (3 independent implementations)0.65s0.64s
machine exact input/output/error/services0.60s0.64s
execution adapter readiness0.59s0.59s

Type instantiations are the comparison metric. Check time varies with runner load and is informational only.

@github-actions

Copy link
Copy Markdown
Contributor

Runtime performance

Median of 5 independent benchmark processes on Intel(R) Xeon(R) 6973P-C with Node v24.19.0.

Pull request baseline

ScenarioEffect Machine
Plan counter transitions168,096 transitions/s
Drain burst with terminal fence553,840 increments/s
Drain burst with a change observer509,978 increments/s
Lookup and send to one child468,014 increments/s
Start and stop a machine209,336 machines/s
Start and stop a parent with one child58,197 families/s
Plan transitions through a compound state148,912 transitions/s
Plan transitions through parallel regions119,960 transitions/s
Drain burst through a compound state436,118 events/s
Drain burst through two parallel regions412,838 events/s
Drain a compound-state burst with a change observer405,940 events/s

Process runtime reference points

ScenarioEffect Machine
Start and stop a raw generic process38,971 processes/s
Start and stop a raw compiled process90,835 processes/s
Memory profileEffect Machine
Idle machine1.7 KiB
Raw generic managed process13.9 KiB
Raw compiled process3.2 KiB
Two independent idle machines3.3 KiB
Idle parent with one child5.7 KiB
Parent with observed child registry9.8 KiB
Parent with observed invoked child snapshots6.3 KiB

Effect Machine change from base

MetricBaseBase variabilityPRPR variabilityDifference
Plan counter transitions170,741 transitions/s2.8% MAD168,096 transitions/s1.5% MAD-1.5%
Drain burst with terminal fence596,474 increments/s9.0% MAD553,840 increments/s4.9% MAD-7.1%
Drain burst with a change observer545,473 increments/s7.4% MAD509,978 increments/s4.4% MAD-6.5%
Lookup and send to one child497,357 increments/s5.9% MAD468,014 increments/s3.6% MAD-5.9%
Start and stop a machine207,943 machines/s1.8% MAD209,336 machines/s1.6% MAD+0.7%
Start and stop a parent with one child57,740 families/s5.4% MAD58,197 families/s2.2% MAD+0.8%
Plan transitions through a compound state155,595 transitions/s0.8% MAD148,912 transitions/s2.0% MAD-4.3%
Plan transitions through parallel regions124,769 transitions/s0.9% MAD119,960 transitions/s2.3% MAD-3.9%
Drain burst through a compound state450,933 events/s2.9% MAD436,118 events/s2.8% MAD-3.3%
Drain burst through two parallel regions435,682 events/s2.5% MAD412,838 events/s2.5% MAD-5.2%
Drain a compound-state burst with a change observer421,284 events/s2.8% MAD405,940 events/s1.1% MAD-3.6%
Idle machine heap per unit1.7 KiB0.2% MAD1.7 KiB0.3% MAD+0.1%
Raw generic managed process heap per unit13.9 KiB0.0% MAD13.9 KiB0.0% MAD+0.0%
Raw compiled process heap per unit3.2 KiB0.3% MAD3.2 KiB0.2% MAD-0.1%
Two independent idle machines heap per unit3.3 KiB0.0% MAD3.3 KiB0.0% MAD-0.0%
Idle parent with one child heap per unit5.7 KiB0.0% MAD5.7 KiB0.0% MAD0.0%
Parent with observed child registry heap per unit9.8 KiB0.0% MAD9.8 KiB0.0% MAD-0.0%
Parent with observed invoked child snapshots heap per unit6.3 KiB0.1% MAD6.3 KiB0.1% MAD+0.1%

Process runtime reference change from base

MetricBaseBase variabilityPRPR variabilityDifference
Start and stop a raw generic process38,609 processes/s1.5% MAD38,971 processes/s2.0% MAD+0.9%
Start and stop a raw compiled process92,064 processes/s2.1% MAD90,835 processes/s2.6% MAD-1.3%

Regression guard

No large, noise-adjusted throughput or heap regressions detected.

Versions and interpretation
  • Effect Machine: 0.31.1

Higher throughput is better; lower heap is better. Variability is the median absolute deviation across independent processes, relative to their median. Small differences on shared GitHub-hosted hardware remain informational; the required guard rejects only large changes beyond the measured noise allowance.

@SandroMaglione
SandroMaglione merged commit 65e4722 into mainAug 30, 2026
8 checks passed
@SandroMaglione
SandroMaglione deleted the codex/fix-initial-choice-from branch August 30, 2026 10:27
Sign up for freeto 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

@SandroMaglione