Repository navigation
Effect Service Conventions: 2 issues found
Two convention violations found in the new Cua driver code.
apps/desktop/src/cua/CuaDriverServerEnvironment.ts(lines 100-110):CuaDriverConfigurationErroris constructed withbinaryPath: driverPath.valuewhile the failure being wrapped ispath.toFileUrlon the embedded module path, so the structural attribute and derived message name a resource that did not fail. Capture the converted module path instead.apps/desktop/src/app/DesktopApp.ts(lines 265-274): recovery usesEffect.catchwith an inlineerror._tag === "CuaDriverConfigurationError"branch. Both tags are statically known, soEffect.catchTags({ ... })with a shared handler is the conventional form.
Previous findings (fabricated "<not configured>" binary path, optional cause) are resolved: the missing-configuration case now has its own CuaDriverNotConfiguredError tag and cause is required on the wrapping errors.
Details
Note
Your check run agent prompt is: .macroscope/check-run-agents/effect-service-conventions.md
More information about how Check Run Agents work can be found in our Help Center.
Scope reviewed: apps/desktop/src/cua/CuaDriverServerEnvironment.ts, apps/desktop/src/app/DesktopApp.ts, apps/server/src/cua/CuaDriverEmbedded.ts, apps/server/src/serverRuntimeStartup.ts, apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.ts, apps/server/src/provider/Layers/codexLaunchArgs.ts, apps/web/src/components/settings/SettingsPanels.tsx, packages/contracts/src/settings.ts and the accompanying tests. scripts/build-desktop-artifact.ts, pnpm-lock.yaml and pnpm-workspace.yaml are outside this check's include patterns and were used only as context.
Checked and found conforming:
- Namespace subpath imports (
effect/Effect,effect/Option,effect/Path,effect/Schema) in all new modules; no consolidated named imports from"effect". - No new
Context.Servicetags,Layer.succeedimplementations,ManagedRuntime.make, orrunPromise/runPromiseExitusage;Path.Pathis acquired from the environment viayield* Path.Path. monitorEmbeddedCuaDriverExittakeswaitForExit/onUnexpectedExitcallbacks rather than injected service instances, which is a legitimate strategy parameter and a test seam.- Failures are declared with
Schema.TaggedErrorClass, messages derive from structural attributes rather thancause, andcauseis required where every construction wraps a real failure. - A single
CuaDriverStartErrorfor the import/construct/start stages is acceptable: the sole caller (serverRuntimeStartup) treats all three identically, so no stage discriminator is required. - No compatibility re-export shims, no
FooShapeinterfaces, and no service files left behind.
🔍 Agent activity — 1 tool call
💭 I'm reviewing the code changes to check for any remaining violations from previous runs. The main files I need to examine are in the CUA driver implementations and adapters, though the scripts directory is outside the scope of this review. Looking at the error handling patterns, I notice
Effect.catchis being used in DesktopApp.ts with an internal_tagdiscriminator to handle bothCuaDriverConfigurationErrorandCuaDriverNotConfiguredError. While this technically handles the entire error channel, the internal branching based on the tag is a bit of a code smell—usingEffect.catchTagswould be more idiomatic, though the current approach isn't strictly wrong. I'm also checkingCuaDriverStartErrorin CuaDriverEmbedded.ts, which usesbinaryPathandcause: Schema.Defect(), and I need to verify how it's being used across the three call sites. oderate finding. The environment configuration functions useEffect.addFinalizerwith scopes to restore state on cleanup, which is fine. There's a potential issue wherereplaceCuaDriverServerEnvironmentadds a finalizer that restores the previous environment when the scope closes—behaviorally odd in tests but not a convention violation. The exit monitoring function takes callbacks for waiting and handling unexpected exits, which is an allowed pattern. However,installCodexLaunchArgsmutatesprocess.envdirectly as module-global state, which violates the principle of not hiding dependencies in module globals. I'm also noticing thatstartEmbeddedCuaDriverreadsprocess.envdirectly rather than using Effect's Config service, andresolveEmbeddedDriverPathhas a default parameter pointing toprocess.env—both are hidden globals. The imports look correct with propereffect/Effectsubpaths. I need to verify whetherOption.fromNullishOris a real API in the version being used, then examine the actual files to complete the review. The stringified cause in the log is acceptable, though it's worth noting. For theEffect.catchusage here, since the entire error channel is a single known tag that's fully handled, usingEffect.catchis appropriate rather thanEffect.catchTags. Let me check the current state of the files and review the repo conventions for Schema.TaggedErrorClass and Effect patterns to make sure everything aligns. Looking at the DesktopApp handler, I see it's using Effect.catch to handle errors, but the convention calls for Effect.catchTags when dealing with statically known tagged failures—even when there's just one tag to handle. The code is checking for "CuaDriverConfigurationError" and extracting context, but it should follow the more specific catchTags pattern instead. There's also a concern with how the error cause is being stringified directly into the log context. The convention warns against copying raw error text into log payloads, so convertingerror.causeto a string and including it in the context violates that principle. I need to identify which findings are solid enough to report. One clear candidate isstartEmbeddedCuaDriverpulling dependencies directly fromprocess.envinstead of using Effect's Config system — the repo already has ServerConfig with Config schemas, so I should verify whether the convention is to use Config throughout. ForCuaDriverStartError, I'm less convinced it's a violation. They do map failures at each site, and while the error doesn't distinguish between import, construction, and startup stages, callers treat all three identically, so a single error tag seems reasonable given the shared semantics. Looking atinstallCodexLaunchArgs, that's straightforward — it returns a thunk wrapping an Effect, which is fine. AndmonitorEmbeddedCuaDriverExitusesEffect.catchon the whole channel to log warnings, which is also acceptable. ButCodexAdapterV2'swithLiveCodexIntegrationEnvironmentis readingprocess.envdirectly at spawn time instead of using the passed environment — that's a hidden global dependency that violates the convention against module globals. Let me check the DesktopApp code to see what's happening there. I'm noticing that usingEffect.catchwith manual_tagdiscrimination here is a pattern violation—the convention recommendsEffect.catchTagswhen the error tags are statically known, even for single tags. WhileEffect.catchis technically allowed when handling the entire error channel, the implementation is essentially reimplementing tag dispatch, which suggests this should be flagged as a clear convention violation. The refactored version usingcatchTagswith per-tag handlers would be cleaner, though I'm weighing whether the shared behavior (disable + dialog) makes this worth failing the check or just recommending as a minor improvement. I'm also noticing theString(error.cause)being logged—the convention says to preserve the exact underlying value only as cause, not to stringify arbitrary defect text into the log payload, which could be another issue worth examining. Now I'm checking the rest of the codebase: Settings usage looks fine, SettingsPanels.tsx is straightforward React, and the schema in packages/contracts is good. ForstartEmbeddedCuaDriverin serverRuntimeStartup, it's usingEffect.catchto handle a single known error tag (CuaDriverStartError), which is actually appropriate here since the entire error channel is intentionally handled—the tryPromise with catch mapping ensures only that one error type flows through. The handler correctly accesseserror.binaryPath, but I need to verify this pattern holds in the desktop case as well. No new Effect services are being created here—these are just plain Effect function modules, so the service conventions don't apply. Import patterns look good across the board. One thing I'm noticing:resolveEmbeddedDriverPathhas a hidden global default for the environment parameter, though the configure function does passprocess.envexplicitly, so it's minor. There's also some duplication of environment variable name constants between the desktopconfigureCuaDriverServerEnvironmentand the serverCuaDriverEmbedded.tsfile that I should check. The error message referencesbinaryPathbut the actual failure is converting the module path to a file URL, so the captured context doesn't match what actually failed. I should capture the module path being converted instead, since that's the resource whose conversion actually failed — that's a concrete finding worth noting. On thecatchTagsissue, the code is manually checking_taginsideEffect.catchwhen it should be usingEffect.catchTagswith explicit tag handlers, which is a clear violation of the convention. Let me verify thelogStartupErrorfunction signature so I can suggest the right fix. I'm identifying a bug in CuaDriverServerEnvironment.ts where the error handling captures the wrong path—it logsbinaryPathbut should be recording the actual module path that failed during thetoFileUrlconversion. The fix is to either add a dedicatedmodulePathfield to the error or renamebinaryPathto better reflect what's actually being reported. Since CuaDriverConfigurationError is only constructed in this one place and DesktopApp references thebinaryPathfield elsewhere, I need to note that renaming requires updates across both files. I'll suggest capturing the module path explicitly in the error construction and mention the cross-file impact rather than providing a full diff. For the second finding around line 265-274, I'm noticing the code manually branches on_taginside an Effect.catch handler. The convention here is to use Effect.catchTags for statically known tagged errors instead of reimplementing that logic inline. I'll flag this as a suggestion since the entire error channel is being handled and the manual tag inspection essentially duplicates what catchTags does. Now I need to verify the line numbers for the diff context—the new block in DesktopApp.ts spans lines 255-291, and the_tagcheck at line 269 is part of those added lines, so I'll reference it with the proper diff range starting at 265.
1. modify_pr — Effect service conventions review: two findings on error context and tagged-failure recovery in the new Cua driver modules.
Agent Credits: 79 credits