Problem: app.scheduleTask(code, delay, true) queued the task and then
skipped it (eval_with_tasks: `if repeat { continue; }`), so repeating
tasks - what ScriptUI panels use for polling and refreshing - never ran.
One-shot tasks scheduled by handlers or in the Script Console never ran
either.
Fix: tasks live per script context (crates/script/src/tasks.rs) with a
due time. Frontends run the due ones every frame through the new
ScriptUi::run_tasks hook (the egui app does; agents and headless hosts
use the `script.runTasks` command). Script-host threads get a Tick
message, inline hosts (Script Console, web) run in their kept context.
A repeating task runs every `delay` ms until app.cancelTask, until it
throws (reported once, then cancelled), or until its owner goes: the
script's last window closing, or - for scripts without windows and the
console - the project being closed or replaced (ScriptUi::project_epoch).
Bounds: at least 50 ms between runs, at most 64 pending tasks per
script, one run per pass (no catch-up bursts), task code nested too
deeply is refused, the engine's loop and recursion limits apply. Ticks
only reach the hosts of the session that scheduled them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>