Repository navigation
Effect Service Conventions: 1 issue found
apps/server/src/desktopControl/resolveEnabledDesktopMcp.ts — ServerSettingsService is acquired with Effect.serviceOption, so this production construction path does not expose the dependency in its requirements type, and the onNone branch defaults to Computer Use enabled, meaning a missing layer silently enables desktop control instead of failing. Suggested fix posted inline: yield* ServerSettings.ServerSettingsService (keeping only the getSettings failure fallback), or an explicit optional-service layer if the dependency must stay optional.
No other convention violations found in the changed TypeScript scope.
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.
Files examined (in-scope changed TypeScript):
apps/server/src/desktopControl/desktopMcpBinary.tsand its test —Effect.fn, subpath namespace imports,FileSystem/Path/HostProcessPlatform/HostProcessEnvironmentacquired from the environment. No findings.apps/server/src/desktopControl/resolveEnabledDesktopMcp.tsand its test — finding above.apps/server/src/provider/Layers/{ClaudeAdapter,CursorAdapter,GrokAdapter}.ts— call sites acquire the launch descriptor inside the existing constructors viayield*; settings continue to arrive as plain configuration values, which is not service injection.apps/server/src/provider/Layers/CodexSessionRuntime.ts— newSchema.isconstants are private but the exportedisComputerUseMcpApproval/isMcpToolApprovalwrappers add a realmode !== "url"check and take a different argument, so they are not redundant predicate wrappers. Error creation goes through the reused static factoryCodexErrors.CodexAppServerRequestError.methodNotFound.apps/server/src/provider/Layers/{CodexAdapter,CodexProvider,ProviderRuntimeIngestion}.ts— mechanical canonical request-type/kind mapping; no service, layer, or error-model changes.apps/desktop/src/computerUse/permissions.ts,apps/desktop/src/ipc/methods/computerUse.ts,apps/desktop/src/ipc/{channels,DesktopIpcHandlers}.ts,apps/desktop/src/preload.ts— imperative Electron/TCC reads bridged at the IPC boundary withEffect.promise; matches the existingnodeBuiltinImport:offprecedent inapps/desktop/srcand does not become a dependency of another Effect service.apps/web/**— React components, route, and puresession-logicmapping updates; no Effect runtime creation.packages/contracts/src/{ipc,orchestration,providerRuntime,settings}.ts,packages/effect-codex-app-server/src/errors.ts— schema/literal additions only.
Checks performed for hidden runtimes and fake injection: searched the diff and touched call sites for ManagedRuntime.make, .runPromise, .runPromiseExit, Layer.succeed, and service-instance parameters — none newly introduced outside tests/boundaries.
Out of scope for this check's include patterns and therefore not targeted: native/**, scripts/build-desktop-artifact.ts, apps/desktop/scripts/electron-launcher.mjs, vite.config.ts, package.json.
🔍 Agent activity — 1 tool call
💭 Looking at this large PR, I need to focus on how Effect services are being used in the TypeScript files. The permissions module in the desktop app is an imperative adapter rather than an Effect service itself — it uses Electron's synchronous APIs and returns a Promise, but it's wrapped by an IPC method that converts it into an Effect using Effect.promise, which is an acceptable boundary adapter pattern. The desktopMcpBinary file uses Effect.fn with FileSystem and Path from the environment, which is fine. But resolveEnabledDesktopMcp is using Effect.serviceOption to acquire ServerSettings with fallback defaults, and I'm questioning whether that violates the rule about modeling unavailability explicitly rather than bypassing the layer — the rule suggests using an optional-service layer to keep recovery visible and testable. I should check if Effect.serviceOption is used elsewhere in the repo to understand the conventions, and also inspect the ServerSettings module to verify the service naming and whether layerTest is exported. I'm also noticing the imports from "@t3tools/shared/hostProcess" — need to check whether that subpath itself is a service module and if it follows the namespace convention.
Effect.serviceOptionis already an established pattern in the codebase for handling optional services, and the guidance about modeling unavailability with explicit optional-service layers supports using it here. There's precedent for this approach, so it's not a hard flag, though I'm wondering if theEffect.orElseSucceedfallback pattern might be worth reconsidering. Looking at the other candidates now — the permissions module uses imperative FS reads with Electron, called directly from an IPC handler wrapped inEffect.fn. That's actually reasonable since the IPC handler is an application boundary, and it bridges to Effect viaEffect.promise. The file also has a lint suppression for Node builtins, which is allowed in the repo, so that's not a convention violation on our end. For the adapter files in the server provider layers, they're callingresolveEnabledDesktopMcp()inside constructors to acquire from environment. The tricky part is thatEffect.serviceOptionhides the ServerSettings dependency from the type signature — the requirement doesn't get exposed. The rule says production service construction must expose those requirements, but this pattern is documented and has precedent in the codebase. The instructions also say not to flag optional style preferences or unrelated legacy code, so this feels more like a gray area than a concrete violation. TheDesktopMcpLaunchtype export is fine. The new errorDesktopMcpBuildOutputMissingErroris in scripts/, which isn't in the include patterns, so that's out of scope. In CodexSessionRuntime.ts, the private schema validation constants are wrapped by exported functions that check computer use approval metadata. These wrapper functions aren't redundant —isComputerUseMcpApprovaladds real logic by checking the mode field and accessing_meta, giving it a different signature than just the raw schema predicate. Same withisMcpToolApproval, which also validates the mode. The pre-existingCodexSessionRuntimeShapeinterface is there, and the rule about not retaining standalone... Now checking the rest of the codebase:CodexErrors.CodexAppServerRequestError.methodNotFoundis a static factory which is fine. New error tags inCodexAppServerIdentifierPurposeare acceptable. IndesktopMcpBinary.ts, there's no error channel but the comment explains why, and usingEffect.orElseSucceedto swallow errors aroundfs.existsis reasonable. The React component inComputerUseSettings.tsxuseswindow.desktopBridgeand promises at the React boundary, which is fine since there's noManagedRuntimethere. Still checking for any newLayer.succeed,ManagedRuntime.make, or.runPromisecalls... Verifying the imports across new files:desktopMcpBinary.tsuses proper subpath imports for Effect, FileSystem, and Path. The resolver and IPC methods files also use correct subpath imports for Effect and Schema. Test files import from@effect/platform-node/NodeServicescorrectly. Now looking atpermissions.tsand its Electron imports... IncomputerUse.ts, I'm checking the aliased import from permissions.ts — it's importingopenComputerUsePrivacySettingsasopenPrivacySettings. Since permissions.ts isn't a service module (no Context.Service or layer), this aliased import doesn't violate the namespace rule that applies to service boundaries. The alias is actually necessary here to avoid a name collision with the exported IPC method. I should verify whether other IPC method files follow a similar pattern for importing helpers, and also check if there are any other potential issues like theresolveEnabledDesreference that might need attention. Looking at thedesktopMcpsetup, it seems to duplicate the default control object in multiple places and silently defaults to enabled, which doesn't match any established convention. TheresolveDesktopMcpPathandresolveEnabledDesktopMcpfunctions are both Effect generators with no arguments, which is fine. Now I'm wondering whether there's a pattern in the codebase where server settings should be accessed through a required service in adapters — if other adapters likeClaudeAdapteralready useServerSettingsService, then usingserviceOptionhere might be inconsistent. The drivers are already injectingServerSettingsServiceand passing settings directly to the adapter factories as plain configuration values. I'm noticing thatresolveEnabledDesktopMcpgets invoked inside those adapter factories and tries to accessServerSettingsServicethrough the Effect system usingserviceOption. The issue is thatServerSettingsServiceis already available in the environment sinceClaudeDriverprovides it—so usingserviceOptionmasks a dependency that's actually satisfied and required in practice. It silently defaults to "enabled" if the layer is missing, which violates the principle that production service construction should explicitly acquire dependencies from the environment. The existing codebase usesserviceOptionfor genuinely optional services like the DPoP signer, butServerSettingsis a core service in the server context; the optionality here is just for dev and test convenience. The guidance says to keep failures typed in the Effect system rather than bypassing the layer through imperative runtime logic, and to model unavailability through service operations.serviceOptiondoes keep things in Effect rather than bypassing it, so that's not the issue—the stronger problem is that the dependency isn't exposed in the type signature. SinceServerSettingsServiceis already in every driver environment and tests already provide it vialayerTest, requiring it directly wouldn't break anything. The real concern is that the missing settings service silently enables desktop control in tests, which masks a dependency that should be explicit. I'll suggest makingServerSettings.ServerSettingsServicea direct requirement rather than an optional fallback, and mention the duplicated fallback defaults while I'm at it. TheorElseSucceedalso swallows potentialgetSettingsfailures, which violates the error handling conventions, though it's clearly intentional as a fallback. Now checking the other TypeScript changes in scope—the schema additions and optional methods inDesktopBridgelook fine, the error literals are fine, React changes are fine. For the aliased import in the desktop IPC methods file, I should compare how sibling files handle their imports... I'm deciding whether to flag this hidden dependency as a convention violation. Since it's a listed requirement that must be exposed, and the check defaults to failure unless there are no findings, I should post an inline comment on the relevant lines and mark this as a failure state. Let me look more closely at the permissions module — it's callingreadComputerUsePermissions()synchronously inside an Effect handler, which violates the convention against hiding asynchronous dependencies in imperative code. The IPC method isn't properly representing its service dependencies in the Effect environment. However, this is an imperative adapter at the boundary, and the file documents why sync APIs are necessary here for Electron. I should check whether other IPC methods follow the same pattern before flagging this as a violation. There's precedent for this pattern in the codebase, so I'll post it as an inline comment suggestion rather than failing the check. The hidden ServerSettings dependency is borderline—it follows the repo's own conventions with Effect.serviceOption and stays within the Effect ecosystem, so it doesn't quite meet the threshold for a clear violation. But actually, thinking through this more carefully: the convention is explicit that production service construction must expose service dependencies, and resolveEnabledDesktopMcp deliberately hides ServerSettingsService while making the disabled setting unenforceable if the layer isn't wired. That's a real behavioral risk, especially since the fallback defaults to enabled, which silently enables desktop control if the dependency is missing. This crosses from style preference into a genuine convention violation, so I should fail the check. I'm drafting an inline comment on the resolveEnabledDesktopMcp function pointing out that while every driver already provides ServerSettingsService, using Effect.serviceOption keeps it out of the requirements type and silently defaults to enabled when missing. The fix is to acquire it explicitly so the requirement is visible and a missing layer fails loudly rather than turning Computer Use on by default. I'll provide a code suggestion that replaces the current lines to acquire the service directly, then pipe through getSettings with a map to extract desktopControl and an orElseSucceed fallback for read errors.
1. modify_pr — One finding: the new desktop-control resolver hides its ServerSettingsService dependency behind Effect.serviceOption, so the requirement is absent from the type of every adapter that calls it and a missing layer silently resolves to "Computer Use enabled". Everything else in the changed TypeScript (subpath namespace imports for effect/*, Effect.fn helpers acquiring FileSystem/Path/HostProcess* from the environment, new Schema.is predicates that add real logic, static CodexAppServerRequestError.methodNotFound factory, no new ManagedRuntime/runPromise/fake Layer.succeed) matches the conventions.
Agent Credits: 286 credits