51ad4801e8
12 tests using testEffect + TestLLM pattern (no HTTP server): - loop exits on stop finish, calls LLM for new messages, continues on tool-calls - loop sets status busy→idle - cancel interrupts cleanly, returns last assistant, records MessageAbortedError - cancel with queued callers resolves all cleanly - concurrent callers get same result via Deferred queue - concurrent callers receive same error on failure - assertNotBusy throws BusyError when running, succeeds when idle - shell rejects with BusyError when loop running