Green threads are most useful when a running task can start new ones - a server accepting a connection, a worker forking a helper. Today a task spawns another mid-run, and the newcomer joins the back of the rotation exactly like any other ready task.
Let a running task call Spawn, and confirm the new task joins at the back of the queue.
Dynamic spawning is what turns a scheduler into a runtime: work discovers more work.
Because Spawn just enqueues at the back, a task created mid-run gets no special
treatment - it waits its turn behind everything already ready, which keeps the whole
system fair and predictable.
Watch the ids and the queue together. Task 1 runs first, spawns the new task (which
becomes id 2 at the back) and yields, so the queue goes from [] (task 1 is out
being stepped) to [2, 1]. Task 2 runs next and finishes; task 1 resumes and
finishes. The trace [1, 2, 1] shows the newcomer slotting in after the task that
created it yielded - never cutting ahead. That ordering guarantee is what makes
concurrent green threads reason-about-able.
// Spawn is already a scheduler method; a task closes over s to call itstep := func() Status {if first {first = falses.Spawn(func() Status { return Done }) // enqueued at the backreturn Ready // task 1 yields}return Done}