Skip to content

fix(native): harden shared Computer Use bridge, capture, and app listing

MacroscopeApp / Macroscope - Effect Service Conventions failed Aug 15, 2026 in 2m 31s

Effect Service Conventions: 1 issue found

1 finding

  • apps/desktop/src/computerHistory/manager.ts (line 301): mergePatchSettings constructs ComputerHistoryOperationError with operation: "ensureDaemon", so the operation discriminator and the message derived from it name an operation that never ran. Add "mergePatchSettings" to the operation literal 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 (new ComputerHistoryManager service)
  • apps/desktop/src/computerHistory/resolveBinary.ts
  • apps/desktop/src/computerUse/permissions.ts
  • apps/desktop/src/ipc/methods/computerHistory.ts, computerUse.ts, DesktopIpcHandlers.ts
  • apps/desktop/src/app/DesktopApp.ts, apps/desktop/src/main.ts
  • apps/server/src/computerHistory/service.ts
  • apps/server/src/desktopControl/desktopMcpBinary.ts, desktopMcpLaunch.ts
  • apps/server/src/provider/Layers/{CodexAdapter,CodexSessionRuntime,ClaudeAdapter,CursorAdapter,GrokAdapter}.ts
  • packages/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 consolidated from "effect" imports were introduced.
  • Service boundaries use module namespace imports (ComputerHistoryManager.ComputerHistoryManager, ComputerHistoryManager.layer, ServerSettings.ServerSettingsService); no layer as fooLayer aliases.
  • ComputerHistoryManager defines its interface inline in Context.Service, exports a real make, and exports the canonical layer; no standalone FooShape type.
  • No ManagedRuntime.make, runPromise, or runPromiseExit introduced in domain services or constructors; imperative Promise work stays inside Effect.tryPromise/Effect.promise at the service or IPC boundary.
  • No service-instance parameters used as production dependency injection; makeResolveEnabledDesktopMcp captures services from the environment at construction and re-provides them, keeping session methods at R = never.
  • Errors use Schema.TaggedErrorClass with structural attributes, retain the underlying failure as cause, and derive message from attributes rather than the cause. Recovery in DesktopApp.ts uses Effect.catchTags; no catchTag/catchIf on 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.tryPromise call 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 with orElseSucceed rather 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 via Layer.effectDiscard looks canonical. For the desktopControl file, the makeResolveEnabledDesktopMcp function 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. The runDaemonOp helper wraps tryPromise and constructs errors, which I need to evaluate against the conventions. The error's cause field uses Schema.Defect() correctly, and while stopDaemon has a minor issue with an empty-string fallback for the root path, the real problem is in mergePatchSettings — it labels its failures with operation: "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 acquiring DesktopEnvironment from the environment rather than taking stateDir as a pure configuration parameter, since DesktopEnvironment already 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 using Layer.effect with closure state rather than smuggling other Effect services. Similarly, the IPC boundary in computerUse.ts bridges to imperative code with Effect.promise, which is fine. I should also check whether ManagedRuntime.make or .runPromise appear anywhere new in the diff. Web tests use window bridge promises without issue. I'm verifying that catchTags is used correctly throughout, and desktopMcpLaunch.ts properly uses Effect.orElseSucceed for fail-closed behavior. Looking at the mergePatchSettings operation, 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 a layer for background processing using Layer.effectDiscard and Effect.forkScoped, but there's no make export — which is fine since the module doesn't own service construction. I'm also noticing that Effect.tryPromise in the service doesn't have explicit error handling and just swallows exceptions via orElseSucceed, but since those errors never surface to callers, that's not worth flagging. However, in DesktopApp.ts there'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 whether revealMemory returning a plain false for 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 of catchTag or catchIf that need attention. I found an issue on line 301 of the computer history manager file where mergePatchSettings errors are incorrectly tagged with operation: "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