W-030: ecs-schedule OnStart, errors and re-entrancy (SCH-F03, part 2)¶
Type: feature · Size: M · Epic: E-schedule-v0 · Target: packages/ecs-schedule · Breaking: no Depends: W-029 Refs: spec SCH-036, SCH-037, SCH-043, SCH-044, SCH-045, SCH-112, SCH-113, SCH-114, SCH-115, SCH-116, SCH-117
Goal¶
Add once-only OnStart, error propagation, synchronous-system checks, and per-world re-entrancy guards. This item creates the per-world state trait with name, disabled, and onStartDone (SCH-063 shape). Isolation, reset, and state exposure are completed in W-033. The allocation benchmark (SCH-117) is manual.
Steps¶
- S1 (SCH-036, SCH-114):
OnStartruns once per world on the firstrun,runPhase, orrunPhasesthat includes it; calls that exclude it do not run or mark it done; files: packages/ecs-schedule/src/state.ts, packages/ecs-schedule/src/on-start.ts, packages/ecs-schedule/tests/on-start.test.ts - S2 (SCH-112, SCH-113 partial): onStartDone is set only after the whole OnStart phase completes without throwing; after a throw the phase runs again in full; empty OnStart runs without error (fully-skipped and observable-flag cases deferred to W-031, W-032, W-033); files: packages/ecs-schedule/tests/on-start-done.test.ts
- S3 (SCH-037, SCH-116): system errors propagate unchanged and skip later systems in that call; a thenable return throws naming the schedule and system and clears the executing marker; files: packages/ecs-schedule/src/run-errors.ts, packages/ecs-schedule/tests/run-errors.test.ts
- S4 (SCH-043, SCH-044, SCH-045, SCH-115): nested run of the same schedule on the same world throws; the marker is cleared on return or throw; other schedules and worlds may nest; error precedence is phase, then
dt, then re-entrancy; files: packages/ecs-schedule/src/reentrancy.ts, packages/ecs-schedule/tests/reentrancy.test.ts - S5 (SCH-117 [manual]): benchmark many steady-state
runcalls with no hooks and check for per-call allocation; files: packages/ecs-schedule/bench/run-alloc.bench.ts - S6 (changeset): add
.changeset/w-030-ecs-schedule-onstart.md(patch,@workspace/ecs-schedule)
Log¶
- 2026-11-01 created from the approved spec split of W-004 (Triage)
- 2026-11-02 moved from Next to Now, state active (Triage)
- 2026-11-02 S1 done, Reviewer APPROVED; files add src/state.ts, src/on-start.ts; SCH-061 tests included in on-start.test.ts
- 2026-11-02 S2 note: onStartDone is set after the last OnStart system runs, must also count when the last system is skipped/disabled (SCH-113)
- 2026-11-02 S2 narrowed to verifiable scope; fully-skipped and observable-flag cases of SCH-113 deferred to W-031, W-032, W-033 (Triage)
- 2026-11-02 S2 done, Reviewer APPROVED after 1 fix round; it.todo cases 3 and 4 moved to W-031 S5a and W-032 S3a (Triage)
- 2026-11-02 S3 done, Reviewer APPROVED after 1 fix round; adds src/run-errors.ts (runSystem); S4 must clear the executing marker on thenable throw
- 2026-11-02 S4 done, Reviewer APPROVED; adds src/reentrancy.ts (per-schedule WeakSet
marker, outside the state trait) - 2026-11-02 S6 note: stray .changeset/cool-news-smoke.md exists; rename to w-030-ecs-schedule-onstart.md with W-030 prefix
- 2026-11-02 S5 benchmark added (bench/run-alloc.bench.ts,
benchscript); measured ~25 B/call from beginOnStart world.get; user decided to defer the fix to W-033 - 2026-11-02 S5 done, Reviewer APPROVED (manual SCH-117 check: ~25 B/call, fix deferred to W-033 S5a)
- 2026-11-02 S6 done, changeset .changeset/w-030-ecs-schedule-onstart.md added, stray cool-news-smoke.md removed
- 2026-11-02 final Reviewer pass: ref coverage confirmed, changeset verified on disk; moved to review (Triage)
- 2026-11-02 final Reviewer APPROVED, done (Triage)