Repository navigation
Effect Service Conventions: 1 issue found
1 finding
apps/desktop/src/computerHistory/manager.ts(line 301):mergePatchSettingsconstructsComputerHistoryOperationErrorwithoperation: "ensureDaemon", so the operation discriminator and themessagederived from it name an operation that never ran. Add"mergePatchSettings"to theoperationliteral set and use it at this failure boundary.
An inline review comment was posted for this finding.
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
Changed TypeScript/TSX under apps/**, packages/** matching the check's include patterns, focusing on Effect service creation and consumption:
apps/desktop/src/computerHistory/manager.ts(newComputerHistoryManagerservice)apps/desktop/src/computerHistory/resolveBinary.tsapps/desktop/src/computerUse/permissions.tsapps/desktop/src/ipc/methods/computerHistory.ts,computerUse.ts,DesktopIpcHandlers.tsapps/desktop/src/app/DesktopApp.ts,apps/desktop/src/main.tsapps/server/src/computerHistory/service.tsapps/server/src/desktopControl/desktopMcpBinary.ts,desktopMcpLaunch.tsapps/server/src/provider/Layers/{CodexAdapter,CodexSessionRuntime,ClaudeAdapter,CursorAdapter,GrokAdapter}.tspackages/contracts/src/*,packages/effect-codex-app-server/src/client.ts,packages/shared/src/computerHistory/*
Checks performed and passing
- Effect modules are imported as namespaces from subpaths (
effect/Effect,effect/Layer,effect/Schema, ...); no consolidatedfrom "effect"imports were introduced. - Service boundaries use module namespace imports (
ComputerHistoryManager.ComputerHistoryManager,ComputerHistoryManager.layer,ServerSettings.ServerSettingsService); nolayer as fooLayeraliases. ComputerHistoryManagerdefines its interface inline inContext.Service, exports a realmake, and exports the canonicallayer; no standaloneFooShapetype.- No
ManagedRuntime.make,runPromise, orrunPromiseExitintroduced in domain services or constructors; imperative Promise work stays insideEffect.tryPromise/Effect.promiseat the service or IPC boundary. - No service-instance parameters used as production dependency injection;
makeResolveEnabledDesktopMcpcaptures services from the environment at construction and re-provides them, keeping session methods atR = never. - Errors use
Schema.TaggedErrorClasswith structural attributes, retain the underlying failure ascause, and derivemessagefrom attributes rather than the cause. Recovery inDesktopApp.tsusesEffect.catchTags; nocatchTag/catchIfon known tags was introduced. - Newly added tests accompany behavioral changes (approval mapping, desktop MCP resolution, Computer History store) rather than proving mechanical refactors.
🔍 Agent activity — 1 tool call
💭 The diff is quite large, and the previous review caught an issue in manager.ts that the author fixed by adding root and path fields. Now I'm checking the current state for any new or remaining violations. The stat_only parameter seems to have been ignored since the output shows the full diff instead of just file statistics, so I'll switch to using the GitHub API to get a proper file list. Looking at what changed between those commits to understand which violations are new versus retained, particularly focusing on how the error handling in manager.ts is structured with the Schema.Defect approach. The multi-value operation with a generic derived message seems aligned with the rules, and the tryPromise wrapper in runDaemonOp is acceptable. The mutable state inside the service constructor closure is fine, but I'm checking whether Layer.effect with an addFinalizer-scoped effect creates a type mismatch in Effect v4 when the Layer is explicitly typed without requiring a Scope. Looking at the other files: the computerHistory service exports a background loop layer via Layer.effectDiscard without a service tag, which follows convention. The desktopMcp helper legitimately captures and provides services back to maintain R=never. The permissions module is just plain sync functions used through Effect.promise in the IPC handler, so it's not a service itself. Now I need to check what's changed since the last commit to see if there are any new issues to flag. The prior commit was force-pushed, so I'm reviewing the current state from scratch. I need to check for other Effect-service-related files that might have been missed in the truncated diff—like the tsx files in apps/web, desktop settings UI components using ManagedRuntime or runPromise, and components for computer history. The TypeScript-only diff appears complete through the scripts directory, but the tsx files weren't shown in that filter. Let me pull the diff stats for the tsx files. Looking at the server-side code in the computerHistory service, the imports are properly namespaced from effect subpaths and the named imports from the shared package are fine since they're pure helpers. I notice the
Effect.tryPromisecall for loading recent context markdown doesn't have a catch handler, which means it'll throw an UnknownException if something goes wrong. The error handling approach here swallows failures withorElseSucceedrather than modeling them with TaggedErrorClass, which technically violates the convention but isn't a strong violation since the errors are fully absorbed. The layer setup viaLayer.effectDiscardlooks canonical. For the desktopControl file, themakeResolveEnabledDesktopMcpfunction captures and re-provides services in an adapter pattern that seems to follow existing repo conventions, so that's acceptable. Now looking at manager.ts, the module-level namespace import from the computerHistory manager is good, and the file structure mostly follows the conventions with imports, errors, tags, and make functions in order. TherunDaemonOphelper wraps tryPromise and constructs errors, which I need to evaluate against the conventions. The error'scausefield usesSchema.Defect()correctly, and whilestopDaemonhas a minor issue with an empty-string fallback for the root path, the real problem is inmergePatchSettings— it labels its failures withoperation: "ensureDaemon"when the actual operation is mergePatchSettings. That's a concrete violation of the convention to capture stable, serializable domain context; mislabeling the operation discriminator is incorrect and worth flagging as a new finding. There's also a question about whether the manager service methods should be acquiringDesktopEnvironmentfrom the environment rather than takingstateDiras a pure configuration parameter, sinceDesktopEnvironmentalready provides that value. The manager's use of raw Promises and spawn inside a Context.Service is an imperative adapter for a native resource, which is acceptable here since it's usingLayer.effectwith closure state rather than smuggling other Effect services. Similarly, the IPC boundary incomputerUse.tsbridges to imperative code withEffect.promise, which is fine. I should also check whetherManagedRuntime.makeor.runPromiseappear anywhere new in the diff. Web tests use window bridge promises without issue. I'm verifying thatcatchTagsis used correctly throughout, anddesktopMcpLaunch.tsproperly usesEffect.orElseSucceedfor fail-closed behavior. Looking at themergePatchSettingsoperation, I notice the error label says "ensureDaemon" when it should probably reflect the actual operation being performed. I need to get the exact line numbers from the file so I can place the comment correctly, then I'll present a unified diff showing both the literal addition and the usage change. Let me also review the service file more carefully to see if there are any other issues worth flagging beyond what I've already found. Looking at the module structure, it exports alayerfor background processing usingLayer.effectDiscardandEffect.forkScoped, but there's nomakeexport — which is fine since the module doesn't own service construction. I'm also noticing thatEffect.tryPromisein the service doesn't have explicit error handling and just swallows exceptions viaorElseSucceed, but since those errors never surface to callers, that's not worth flagging. However, inDesktopApp.tsthere's a logging pattern where the error object including defect causes gets logged directly, which could expose sensitive information — I should check if that violates the safety guidelines for error logging. Now I need to locate the line numbers for the mergePatchSettings block. Looking for the mergePatchSettings error construction line. Line 301 is part of the new file in the diff, so I can post an inline comment there using the RIGHT side with the file path. The error message approach seems fine since it's using a multi-value operation with a generic message rather than encoding the same distinction twice. I should also check whetherrevealMemoryreturning a plainfalsefor out-of-root paths instead of a typed error is worth flagging — it's not a convention violation. And I'm scanning through the newly added code to see if there are any instances ofcatchTagorcatchIfthat need attention. I found an issue on line 301 of the computer history manager file where mergePatchSettings errors are incorrectly tagged withoperation: "ensureDaemon", causing the error message to reference the wrong operation. I should add "mergePatchSettings" to the operation literal set and use it at that location, then provide a two-hunk diff to show the fix. Since the operation literal doesn't currently exist in the codebase, I'll skip the diff and just describe the precise change needed. The finding is valid — this is a clear convention violation where the operation context doesn't match the actual operation being performed, so the check should fail.
1. modify_pr — Effect service review of the Computer History / Computer Use changes. One finding on the new desktop service's error context; the rest of the touched Effect code (namespace subpath imports, inline Context.Service interface, make + layer exports, Effect.catchTags recovery in DesktopApp.ts, dependency acquisition via the Effect environment in desktopMcpLaunch.ts) follows the conventions.
Agent Credits: 190 credits