diff --git a/packages/opencode/test/account/repo.test.ts b/packages/opencode/test/account/repo.test.ts
index fb12ddf701..460c47443f 100644
--- a/packages/opencode/test/account/repo.test.ts
+++ b/packages/opencode/test/account/repo.test.ts
@@ -16,21 +16,21 @@ const truncate = Layer.effectDiscard(
const it = testEffect(Layer.merge(AccountRepo.layer, truncate))
-it.effect("list returns empty when no accounts exist", () =>
+it.live("list returns empty when no accounts exist", () =>
Effect.gen(function* () {
const accounts = yield* AccountRepo.use((r) => r.list())
expect(accounts).toEqual([])
}),
)
-it.effect("active returns none when no accounts exist", () =>
+it.live("active returns none when no accounts exist", () =>
Effect.gen(function* () {
const active = yield* AccountRepo.use((r) => r.active())
expect(Option.isNone(active)).toBe(true)
}),
)
-it.effect("persistAccount inserts and getRow retrieves", () =>
+it.live("persistAccount inserts and getRow retrieves", () =>
Effect.gen(function* () {
const id = AccountID.make("user-1")
yield* AccountRepo.use((r) =>
@@ -56,7 +56,7 @@ it.effect("persistAccount inserts and getRow retrieves", () =>
}),
)
-it.effect("persistAccount sets the active account and org", () =>
+it.live("persistAccount sets the active account and org", () =>
Effect.gen(function* () {
const id1 = AccountID.make("user-1")
const id2 = AccountID.make("user-2")
@@ -93,7 +93,7 @@ it.effect("persistAccount sets the active account and org", () =>
}),
)
-it.effect("list returns all accounts", () =>
+it.live("list returns all accounts", () =>
Effect.gen(function* () {
const id1 = AccountID.make("user-1")
const id2 = AccountID.make("user-2")
@@ -128,7 +128,7 @@ it.effect("list returns all accounts", () =>
}),
)
-it.effect("remove deletes an account", () =>
+it.live("remove deletes an account", () =>
Effect.gen(function* () {
const id = AccountID.make("user-1")
@@ -151,7 +151,7 @@ it.effect("remove deletes an account", () =>
}),
)
-it.effect("use stores the selected org and marks the account active", () =>
+it.live("use stores the selected org and marks the account active", () =>
Effect.gen(function* () {
const id1 = AccountID.make("user-1")
const id2 = AccountID.make("user-2")
@@ -191,7 +191,7 @@ it.effect("use stores the selected org and marks the account active", () =>
}),
)
-it.effect("persistToken updates token fields", () =>
+it.live("persistToken updates token fields", () =>
Effect.gen(function* () {
const id = AccountID.make("user-1")
@@ -225,7 +225,7 @@ it.effect("persistToken updates token fields", () =>
}),
)
-it.effect("persistToken with no expiry sets token_expiry to null", () =>
+it.live("persistToken with no expiry sets token_expiry to null", () =>
Effect.gen(function* () {
const id = AccountID.make("user-1")
@@ -255,7 +255,7 @@ it.effect("persistToken with no expiry sets token_expiry to null", () =>
}),
)
-it.effect("persistAccount upserts on conflict", () =>
+it.live("persistAccount upserts on conflict", () =>
Effect.gen(function* () {
const id = AccountID.make("user-1")
@@ -295,7 +295,7 @@ it.effect("persistAccount upserts on conflict", () =>
}),
)
-it.effect("remove clears active state when deleting the active account", () =>
+it.live("remove clears active state when deleting the active account", () =>
Effect.gen(function* () {
const id = AccountID.make("user-1")
@@ -318,7 +318,7 @@ it.effect("remove clears active state when deleting the active account", () =>
}),
)
-it.effect("getRow returns none for nonexistent account", () =>
+it.live("getRow returns none for nonexistent account", () =>
Effect.gen(function* () {
const row = yield* AccountRepo.use((r) => r.getRow(AccountID.make("nope")))
expect(Option.isNone(row)).toBe(true)
diff --git a/packages/opencode/test/account/service.test.ts b/packages/opencode/test/account/service.test.ts
index 9c67641d20..cfe55e23e4 100644
--- a/packages/opencode/test/account/service.test.ts
+++ b/packages/opencode/test/account/service.test.ts
@@ -54,7 +54,7 @@ const deviceTokenClient = (body: unknown, status = 400) =>
const poll = (body: unknown, status = 400) =>
Account.Service.use((s) => s.poll(login())).pipe(Effect.provide(live(deviceTokenClient(body, status))))
-it.effect("orgsByAccount groups orgs per account", () =>
+it.live("orgsByAccount groups orgs per account", () =>
Effect.gen(function* () {
yield* AccountRepo.use((r) =>
r.persistAccount({
@@ -107,7 +107,7 @@ it.effect("orgsByAccount groups orgs per account", () =>
}),
)
-it.effect("token refresh persists the new token", () =>
+it.live("token refresh persists the new token", () =>
Effect.gen(function* () {
const id = AccountID.make("user-1")
@@ -148,7 +148,7 @@ it.effect("token refresh persists the new token", () =>
}),
)
-it.effect("config sends the selected org header", () =>
+it.live("config sends the selected org header", () =>
Effect.gen(function* () {
const id = AccountID.make("user-1")
@@ -188,7 +188,7 @@ it.effect("config sends the selected org header", () =>
}),
)
-it.effect("poll stores the account and first org on success", () =>
+it.live("poll stores the account and first org on success", () =>
Effect.gen(function* () {
const client = HttpClient.make((req) =>
Effect.succeed(
@@ -259,7 +259,7 @@ for (const [name, body, expectedTag] of [
"PollExpired",
],
] as const) {
- it.effect(`poll returns ${name} for ${body.error}`, () =>
+ it.live(`poll returns ${name} for ${body.error}`, () =>
Effect.gen(function* () {
const result = yield* poll(body)
expect(result._tag).toBe(expectedTag)
@@ -267,7 +267,7 @@ for (const [name, body, expectedTag] of [
)
}
-it.effect("poll returns poll error for other OAuth errors", () =>
+it.live("poll returns poll error for other OAuth errors", () =>
Effect.gen(function* () {
const result = yield* poll({
error: "server_error",
diff --git a/packages/opencode/test/bus/bus-effect.test.ts b/packages/opencode/test/bus/bus-effect.test.ts
index 642763e90f..6f3bcbcfab 100644
--- a/packages/opencode/test/bus/bus-effect.test.ts
+++ b/packages/opencode/test/bus/bus-effect.test.ts
@@ -22,7 +22,7 @@ const live = Layer.mergeAll(Bus.layer, node)
const it = testEffect(live)
describe("Bus (Effect-native)", () => {
- it.effect("publish + subscribe stream delivers events", () =>
+ it.live("publish + subscribe stream delivers events", () =>
provideTmpdirInstance(() =>
Effect.gen(function* () {
const bus = yield* Bus.Service
@@ -46,7 +46,7 @@ describe("Bus (Effect-native)", () => {
),
)
- it.effect("subscribe filters by event type", () =>
+ it.live("subscribe filters by event type", () =>
provideTmpdirInstance(() =>
Effect.gen(function* () {
const bus = yield* Bus.Service
@@ -70,7 +70,7 @@ describe("Bus (Effect-native)", () => {
),
)
- it.effect("subscribeAll receives all types", () =>
+ it.live("subscribeAll receives all types", () =>
provideTmpdirInstance(() =>
Effect.gen(function* () {
const bus = yield* Bus.Service
@@ -95,7 +95,7 @@ describe("Bus (Effect-native)", () => {
),
)
- it.effect("multiple subscribers each receive the event", () =>
+ it.live("multiple subscribers each receive the event", () =>
provideTmpdirInstance(() =>
Effect.gen(function* () {
const bus = yield* Bus.Service
@@ -129,7 +129,7 @@ describe("Bus (Effect-native)", () => {
),
)
- it.effect("subscribeAll stream sees InstanceDisposed on disposal", () =>
+ it.live("subscribeAll stream sees InstanceDisposed on disposal", () =>
Effect.gen(function* () {
const dir = yield* tmpdirScoped()
const types: string[] = []
diff --git a/packages/opencode/test/effect/runner.test.ts b/packages/opencode/test/effect/runner.test.ts
index 5d3488849c..9dc395876e 100644
--- a/packages/opencode/test/effect/runner.test.ts
+++ b/packages/opencode/test/effect/runner.test.ts
@@ -6,7 +6,7 @@ import { it } from "../lib/effect"
describe("Runner", () => {
// --- ensureRunning semantics ---
- it.effect(
+ it.live(
"ensureRunning starts work and returns result",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -18,7 +18,7 @@ describe("Runner", () => {
}),
)
- it.effect(
+ it.live(
"ensureRunning propagates work failures",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -29,7 +29,7 @@ describe("Runner", () => {
}),
)
- it.effect(
+ it.live(
"concurrent callers share the same run",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -51,7 +51,7 @@ describe("Runner", () => {
}),
)
- it.effect(
+ it.live(
"concurrent callers all receive same error",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -71,7 +71,7 @@ describe("Runner", () => {
}),
)
- it.effect(
+ it.live(
"ensureRunning can be called again after previous run completes",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -81,7 +81,7 @@ describe("Runner", () => {
}),
)
- it.effect(
+ it.live(
"second ensureRunning ignores new work if already running",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -110,7 +110,7 @@ describe("Runner", () => {
// --- cancel semantics ---
- it.effect(
+ it.live(
"cancel interrupts running work",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -128,7 +128,7 @@ describe("Runner", () => {
}),
)
- it.effect(
+ it.live(
"cancel on idle is a no-op",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -138,7 +138,7 @@ describe("Runner", () => {
}),
)
- it.effect(
+ it.live(
"cancel with onInterrupt resolves callers gracefully",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -154,7 +154,7 @@ describe("Runner", () => {
}),
)
- it.effect(
+ it.live(
"cancel with queued callers resolves all",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -175,7 +175,7 @@ describe("Runner", () => {
}),
)
- it.effect(
+ it.live(
"work can be started after cancel",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -245,7 +245,7 @@ describe("Runner", () => {
// --- shell semantics ---
- it.effect(
+ it.live(
"shell runs exclusively",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -256,7 +256,7 @@ describe("Runner", () => {
}),
)
- it.effect(
+ it.live(
"shell rejects when run is active",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -272,7 +272,7 @@ describe("Runner", () => {
}),
)
- it.effect(
+ it.live(
"shell rejects when another shell is running",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -292,7 +292,7 @@ describe("Runner", () => {
}),
)
- it.effect(
+ it.live(
"shell rejects via busy callback and cancel still stops the first shell",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -323,7 +323,7 @@ describe("Runner", () => {
}),
)
- it.effect(
+ it.live(
"cancel interrupts shell that ignores abort signal",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -349,7 +349,7 @@ describe("Runner", () => {
// --- shell→run handoff ---
- it.effect(
+ it.live(
"ensureRunning queues behind shell then runs after",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -376,7 +376,7 @@ describe("Runner", () => {
}),
)
- it.effect(
+ it.live(
"multiple ensureRunning callers share the queued run behind shell",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -407,7 +407,7 @@ describe("Runner", () => {
}),
)
- it.effect(
+ it.live(
"cancel during shell_then_run cancels both",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -441,7 +441,7 @@ describe("Runner", () => {
// --- lifecycle callbacks ---
- it.effect(
+ it.live(
"onIdle fires when returning to idle from running",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -454,7 +454,7 @@ describe("Runner", () => {
}),
)
- it.effect(
+ it.live(
"onIdle fires on cancel",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -470,7 +470,7 @@ describe("Runner", () => {
}),
)
- it.effect(
+ it.live(
"onBusy fires when shell starts",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -485,7 +485,7 @@ describe("Runner", () => {
// --- busy flag ---
- it.effect(
+ it.live(
"busy is true during run",
Effect.gen(function* () {
const s = yield* Scope.Scope
@@ -502,7 +502,7 @@ describe("Runner", () => {
}),
)
- it.effect(
+ it.live(
"busy is true during shell",
Effect.gen(function* () {
const s = yield* Scope.Scope
diff --git a/packages/opencode/test/format/format.test.ts b/packages/opencode/test/format/format.test.ts
index 74336e02a3..95fe763d41 100644
--- a/packages/opencode/test/format/format.test.ts
+++ b/packages/opencode/test/format/format.test.ts
@@ -10,7 +10,7 @@ import * as Formatter from "../../src/format/formatter"
const it = testEffect(Layer.mergeAll(Format.defaultLayer, CrossSpawnSpawner.defaultLayer, NodeFileSystem.layer))
describe("Format", () => {
- it.effect("status() returns built-in formatters when no config overrides", () =>
+ it.live("status() returns built-in formatters when no config overrides", () =>
provideTmpdirInstance(() =>
Format.Service.use((fmt) =>
Effect.gen(function* () {
@@ -32,7 +32,7 @@ describe("Format", () => {
),
)
- it.effect("status() returns empty list when formatter is disabled", () =>
+ it.live("status() returns empty list when formatter is disabled", () =>
provideTmpdirInstance(
() =>
Format.Service.use((fmt) =>
@@ -44,7 +44,7 @@ describe("Format", () => {
),
)
- it.effect("status() excludes formatters marked as disabled in config", () =>
+ it.live("status() excludes formatters marked as disabled in config", () =>
provideTmpdirInstance(
() =>
Format.Service.use((fmt) =>
@@ -64,11 +64,11 @@ describe("Format", () => {
),
)
- it.effect("service initializes without error", () =>
+ it.live("service initializes without error", () =>
provideTmpdirInstance(() => Format.Service.use(() => Effect.void)),
)
- it.effect("status() initializes formatter state per directory", () =>
+ it.live("status() initializes formatter state per directory", () =>
Effect.gen(function* () {
const a = yield* provideTmpdirInstance(() => Format.Service.use((fmt) => fmt.status()), {
config: { formatter: false },
@@ -80,7 +80,7 @@ describe("Format", () => {
}),
)
- it.effect("runs enabled checks for matching formatters in parallel", () =>
+ it.live("runs enabled checks for matching formatters in parallel", () =>
provideTmpdirInstance((path) =>
Effect.gen(function* () {
const file = `${path}/test.parallel`
@@ -144,7 +144,7 @@ describe("Format", () => {
),
)
- it.effect("runs matching formatters sequentially for the same file", () =>
+ it.live("runs matching formatters sequentially for the same file", () =>
provideTmpdirInstance(
(path) =>
Effect.gen(function* () {
diff --git a/packages/opencode/test/lib/effect.ts b/packages/opencode/test/lib/effect.ts
index 4162ba0924..36e2b71f61 100644
--- a/packages/opencode/test/lib/effect.ts
+++ b/packages/opencode/test/lib/effect.ts
@@ -1,10 +1,10 @@
import { test, type TestOptions } from "bun:test"
import { Cause, Effect, Exit, Layer } from "effect"
import type * as Scope from "effect/Scope"
+import * as TestClock from "effect/testing/TestClock"
import * as TestConsole from "effect/testing/TestConsole"
type Body = Effect.Effect | (() => Effect.Effect)
-const env = TestConsole.layer
const body = (value: Body) => Effect.suspend(() => (typeof value === "function" ? value() : value))
@@ -19,19 +19,35 @@ const run = (value: Body, layer: Layer.Layer
return yield* exit
}).pipe(Effect.runPromise)
-const make = (layer: Layer.Layer) => {
+const make = (testLayer: Layer.Layer, liveLayer: Layer.Layer) => {
const effect = (name: string, value: Body, opts?: number | TestOptions) =>
- test(name, () => run(value, layer), opts)
+ test(name, () => run(value, testLayer), opts)
effect.only = (name: string, value: Body, opts?: number | TestOptions) =>
- test.only(name, () => run(value, layer), opts)
+ test.only(name, () => run(value, testLayer), opts)
effect.skip = (name: string, value: Body, opts?: number | TestOptions) =>
- test.skip(name, () => run(value, layer), opts)
+ test.skip(name, () => run(value, testLayer), opts)
- return { effect }
+ const live = (name: string, value: Body, opts?: number | TestOptions) =>
+ test(name, () => run(value, liveLayer), opts)
+
+ live.only = (name: string, value: Body, opts?: number | TestOptions) =>
+ test.only(name, () => run(value, liveLayer), opts)
+
+ live.skip = (name: string, value: Body, opts?: number | TestOptions) =>
+ test.skip(name, () => run(value, liveLayer), opts)
+
+ return { effect, live }
}
-export const it = make(env)
+// Test environment with TestClock and TestConsole
+const testEnv = Layer.mergeAll(TestConsole.layer, TestClock.layer())
-export const testEffect = (layer: Layer.Layer) => make(Layer.provideMerge(layer, env))
+// Live environment - uses real clock, but keeps TestConsole for output capture
+const liveEnv = TestConsole.layer
+
+export const it = make(testEnv, liveEnv)
+
+export const testEffect = (layer: Layer.Layer) =>
+ make(Layer.provideMerge(layer, testEnv), Layer.provideMerge(layer, liveEnv))
diff --git a/packages/opencode/test/session/processor-effect.test.ts b/packages/opencode/test/session/processor-effect.test.ts
index 0dfdef26f6..23c6911a2c 100644
--- a/packages/opencode/test/session/processor-effect.test.ts
+++ b/packages/opencode/test/session/processor-effect.test.ts
@@ -264,7 +264,7 @@ const env = SessionProcessor.layer.pipe(Layer.provideMerge(deps))
const it = testEffect(env)
-it.effect("session.processor effect tests capture llm input cleanly", () => {
+it.live("session.processor effect tests capture llm input cleanly", () => {
return provideTmpdirInstance(
(dir) =>
Effect.gen(function* () {
@@ -316,7 +316,7 @@ it.effect("session.processor effect tests capture llm input cleanly", () => {
)
})
-it.effect("session.processor effect tests stop after token overflow requests compaction", () => {
+it.live("session.processor effect tests stop after token overflow requests compaction", () => {
return provideTmpdirInstance(
(dir) =>
Effect.gen(function* () {
@@ -376,7 +376,7 @@ it.effect("session.processor effect tests stop after token overflow requests com
)
})
-it.effect("session.processor effect tests reset reasoning state across retries", () => {
+it.live("session.processor effect tests reset reasoning state across retries", () => {
return provideTmpdirInstance(
(dir) =>
Effect.gen(function* () {
@@ -449,7 +449,7 @@ it.effect("session.processor effect tests reset reasoning state across retries",
)
})
-it.effect("session.processor effect tests do not retry unknown json errors", () => {
+it.live("session.processor effect tests do not retry unknown json errors", () => {
return provideTmpdirInstance(
(dir) =>
Effect.gen(function* () {
@@ -495,7 +495,7 @@ it.effect("session.processor effect tests do not retry unknown json errors", ()
)
})
-it.effect("session.processor effect tests retry recognized structured json errors", () => {
+it.live("session.processor effect tests retry recognized structured json errors", () => {
return provideTmpdirInstance(
(dir) =>
Effect.gen(function* () {
@@ -544,7 +544,7 @@ it.effect("session.processor effect tests retry recognized structured json error
)
})
-it.effect("session.processor effect tests publish retry status updates", () => {
+it.live("session.processor effect tests publish retry status updates", () => {
return provideTmpdirInstance(
(dir) =>
Effect.gen(function* () {
@@ -611,7 +611,7 @@ it.effect("session.processor effect tests publish retry status updates", () => {
)
})
-it.effect("session.processor effect tests compact on structured context overflow", () => {
+it.live("session.processor effect tests compact on structured context overflow", () => {
return provideTmpdirInstance(
(dir) =>
Effect.gen(function* () {
@@ -656,7 +656,7 @@ it.effect("session.processor effect tests compact on structured context overflow
)
})
-it.effect("session.processor effect tests mark pending tools as aborted on cleanup", () => {
+it.live("session.processor effect tests mark pending tools as aborted on cleanup", () => {
return provideTmpdirInstance(
(dir) =>
Effect.gen(function* () {
@@ -725,7 +725,7 @@ it.effect("session.processor effect tests mark pending tools as aborted on clean
)
})
-it.effect("session.processor effect tests record aborted errors and idle state", () => {
+it.live("session.processor effect tests record aborted errors and idle state", () => {
return provideTmpdirInstance(
(dir) =>
Effect.gen(function* () {
@@ -807,7 +807,7 @@ it.effect("session.processor effect tests record aborted errors and idle state",
)
})
-it.effect("session.processor effect tests mark interruptions aborted without manual abort", () => {
+it.live("session.processor effect tests mark interruptions aborted without manual abort", () => {
return provideTmpdirInstance(
(dir) =>
Effect.gen(function* () {
diff --git a/packages/opencode/test/session/prompt-effect.test.ts b/packages/opencode/test/session/prompt-effect.test.ts
index ef664113f3..bdcbc278b3 100644
--- a/packages/opencode/test/session/prompt-effect.test.ts
+++ b/packages/opencode/test/session/prompt-effect.test.ts
@@ -416,7 +416,7 @@ const boot = Effect.fn("test.boot")(function* (input?: { title?: string }) {
// Loop semantics
-it.effect("loop exits immediately when last assistant has stop finish", () =>
+it.live("loop exits immediately when last assistant has stop finish", () =>
provideTmpdirInstance(
(dir) =>
Effect.gen(function* () {
@@ -432,7 +432,7 @@ it.effect("loop exits immediately when last assistant has stop finish", () =>
),
)
-it.effect("loop calls LLM and returns assistant message", () =>
+it.live("loop calls LLM and returns assistant message", () =>
provideTmpdirInstance(
(dir) =>
Effect.gen(function* () {
@@ -450,7 +450,7 @@ it.effect("loop calls LLM and returns assistant message", () =>
),
)
-it.effect("loop continues when finish is tool-calls", () =>
+it.live("loop continues when finish is tool-calls", () =>
provideTmpdirInstance(
(dir) =>
Effect.gen(function* () {
@@ -471,7 +471,7 @@ it.effect("loop continues when finish is tool-calls", () =>
),
)
-it.effect("failed subtask preserves metadata on error tool state", () =>
+it.live("failed subtask preserves metadata on error tool state", () =>
provideTmpdirInstance(
(dir) =>
Effect.gen(function* () {
@@ -532,7 +532,7 @@ it.effect("failed subtask preserves metadata on error tool state", () =>
),
)
-it.effect("loop sets status to busy then idle", () =>
+it.live("loop sets status to busy then idle", () =>
provideTmpdirInstance(
(dir) =>
Effect.gen(function* () {
@@ -567,7 +567,7 @@ it.effect("loop sets status to busy then idle", () =>
// Cancel semantics
-it.effect(
+it.live(
"cancel interrupts loop and resolves with an assistant message",
() =>
provideTmpdirInstance(
@@ -598,7 +598,7 @@ it.effect(
30_000,
)
-it.effect(
+it.live(
"cancel records MessageAbortedError on interrupted process",
() =>
provideTmpdirInstance(
@@ -632,7 +632,7 @@ it.effect(
30_000,
)
-it.effect(
+it.live(
"cancel finalizes subtask tool state",
() =>
provideTmpdirInstance(
@@ -695,7 +695,7 @@ it.effect(
30_000,
)
-it.effect(
+it.live(
"cancel with queued callers resolves all cleanly",
() =>
provideTmpdirInstance(
@@ -733,7 +733,7 @@ it.effect(
// Queue semantics
-it.effect("concurrent loop callers get same result", () =>
+it.live("concurrent loop callers get same result", () =>
provideTmpdirInstance(
(dir) =>
Effect.gen(function* () {
@@ -752,7 +752,7 @@ it.effect("concurrent loop callers get same result", () =>
),
)
-it.effect("concurrent loop callers all receive same error result", () =>
+it.live("concurrent loop callers all receive same error result", () =>
provideTmpdirInstance(
(dir) =>
Effect.gen(function* () {
@@ -780,7 +780,7 @@ it.effect("concurrent loop callers all receive same error result", () =>
),
)
-it.effect(
+it.live(
"prompt submitted during an active run is included in the next LLM input",
() =>
provideTmpdirInstance(
@@ -860,7 +860,7 @@ it.effect(
30_000,
)
-it.effect(
+it.live(
"assertNotBusy throws BusyError when loop running",
() =>
provideTmpdirInstance(
@@ -897,7 +897,7 @@ it.effect(
30_000,
)
-it.effect("assertNotBusy succeeds when idle", () =>
+it.live("assertNotBusy succeeds when idle", () =>
provideTmpdirInstance(
(dir) =>
Effect.gen(function* () {
@@ -914,7 +914,7 @@ it.effect("assertNotBusy succeeds when idle", () =>
// Shell semantics
-it.effect(
+it.live(
"shell rejects with BusyError when loop running",
() =>
provideTmpdirInstance(
diff --git a/packages/opencode/test/session/prompt-provider.test.ts b/packages/opencode/test/session/prompt-provider.test.ts
index d2190e151d..0cf90f2bd5 100644
--- a/packages/opencode/test/session/prompt-provider.test.ts
+++ b/packages/opencode/test/session/prompt-provider.test.ts
@@ -52,7 +52,7 @@ function makeConfig(url: string) {
}
describe("session.prompt provider integration", () => {
- it.effect("loop returns assistant text through local provider", () =>
+ it.live("loop returns assistant text through local provider", () =>
Effect.gen(function* () {
const llm = yield* TestLLMServer
return yield* provideTmpdirInstance(
@@ -87,7 +87,7 @@ describe("session.prompt provider integration", () => {
}),
)
- it.effect("loop consumes queued replies across turns", () =>
+ it.live("loop consumes queued replies across turns", () =>
Effect.gen(function* () {
const llm = yield* TestLLMServer
return yield* provideTmpdirInstance(
diff --git a/packages/opencode/test/tool/truncation.test.ts b/packages/opencode/test/tool/truncation.test.ts
index dba083c512..9ec5b78400 100644
--- a/packages/opencode/test/tool/truncation.test.ts
+++ b/packages/opencode/test/tool/truncation.test.ts
@@ -140,7 +140,7 @@ describe("Truncate", () => {
const DAY_MS = 24 * 60 * 60 * 1000
const it = testEffect(Layer.mergeAll(TruncateSvc.defaultLayer, NodeFileSystem.layer))
- it.effect("deletes files older than 7 days and preserves recent files", () =>
+ it.live("deletes files older than 7 days and preserves recent files", () =>
Effect.gen(function* () {
const fs = yield* FileSystem.FileSystem