fix(test): share one top-level scope for httpapi-exercise effect mode - #206
Merged
Merged
Conversation
The AppLayer is memoized across every httpapi-exercise scenario for speed, but withContext was building it against a fresh per-scenario Scope each time. Because the memo map only builds the layer once, any service that captures `yield* Scope.Scope` at layer-build time to fork background work (SessionPrompt's title/summarize forks, the promptAsync httpapi handler's fire-and-forget fork) got permanently tied to whichever scenario happened to trigger the first build. Once that scenario's own scope closed, every later forkIn(scope) anywhere in the app silently died, so session.prompt_async and session.command never reached the fake LLM server (30s timeouts), and session.prompt could intermittently read a leaked background fiber's fake-LLM text. Give the whole exerciser run one top-level scope in main() and thread it through runScenario/runActive/withContext for the Layer.buildWithMemoMap call instead, matching how the app is scoped in production (built once against the server's own lifetime scope). Closes #205 Co-Authored-By: Claude Sonnet 5 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue for this PR
Closes #205
Type of change
What does this PR do?
Fixes the 3 effect-mode
bun run test:httpapiscenarios (session.prompt,session.prompt_async,session.command) that have never been reliably green since they were added in #203.Root cause (test harness, not app regression):
test/server/httpapi-exercise/runner.ts'swithContextbuilds the sharedAppLayerviaLayer.buildWithMemoMap(modules.AppLayer, modules.memoMap, scope).modules.memoMapis a singleLayer.MemoMapcreated once for the whole exerciser process (intentional, for speed — the app is built once and reused across all 245+ scenarios). But thescopepassed alongside it was obtained fresh per scenario (inside each scenario's ownEffect.scoped). Since the memo map only builds the layer once, whichever scenario happens to trigger that first build permanently ties every layer-build-timeyield* Scope.Scopecapture (used bySessionPrompt's title-generation/auto-summarize forks and thepromptAsynchttpapi handler's fire-and-forget fork) to that scenario's scope. The instant that scenario's own scope closes, every laterEffect.forkIn(scope, ...)anywhere in the app forks into an already-closed scope and is immediately interrupted — sosession.prompt_async/session.commandnever reached the fake LLM server at all (30s timeouts), andsession.promptcould intermittently read a leaked background fiber's fake-LLM text instead of its own.Fix: obtain one top-level
Scopeonce inmain()(test/server/httpapi-exercise/index.ts) and thread it throughrunScenario→runActive→withContextfor theLayer.buildWithMemoMapcall, instead of a fresh per-scenario scope. This matches how the app is actually scoped in production (built once against the server's own lifetime scope).Both changed files are test-only (
test/server/httpapi-exercise/index.ts,test/server/httpapi-exercise/runner.ts). No production code was touched.How did you verify your code works?
session.prompt,session.prompt_async,session.commandpass reliably — verified 3x each in isolation and as part of the batch that previously reproduced the failure (--include session.prompt, which selects all three).bun run script/httpapi-exercise.ts --mode effect --fail-on-missing --fail-on-skip: 242 pass / 3 fail. The 3 remaining failures (pty.create,worktree.reset,v2.pty.create) are pre-existing and unrelated — confirmed present before and after this change, untouched here.bun run script/httpapi-exercise.ts --mode coverage --fail-on-missing --fail-on-skip: 245/245 pass (no regression).bun run script/httpapi-exercise.ts --mode auth --fail-on-missing --fail-on-skip: 245/245 pass (no regression).bun turbo typecheck: passes (30/30 packages).Screenshots / recordings
N/A (test infrastructure change, no UI).
Checklist
🤖 Generated with Claude Code