Skip to content

fix(acp): scope pending prompt cancellation

MacroscopeApp / Macroscope - Effect Service Conventions failed Aug 26, 2026 in 4m 5s

Effect Service Conventions: 1 issue found

1 finding

  • apps/server/src/provider/Layers/OmpAdapter.ts β€” the new local mapOmpAcpToAdapterError is a pure error constructor typed on cause: unknown; it bypasses the shared mapAcpToAdapterError translator (../acp/AcpAdapterSupport.ts) and therefore loses the AcpProcessExitedError β†’ ProviderAdapterSessionClosedError classification that the sibling ACP adapters rely on and that this PR's ProviderCommandReactor now surfaces with a dedicated message.

Previously flagged items are resolved on this head: the client-visible errorMessage/reason no longer embed Cause.pretty output, ProviderDriverError/ProviderAdapterRequestError detail values are structural rather than copies of cause.message, AcpTextGeneration uses Effect.catchTags, and the makeCursorTextGeneration JSDoc was restored.

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: apps/server/src/provider/Layers/OmpAdapter.ts, OmpProvider.ts, Drivers/OmpDriver.ts, Services/OmpAdapter.ts, acp/OmpAcpSupport.ts, acp/AcpSessionRuntime.ts, acp/AcpRuntimeModel.ts, orchestration/Layers/ProviderCommandReactor.ts, textGeneration/AcpTextGeneration.ts, OmpTextGeneration.ts, CursorTextGeneration.ts, GrokTextGeneration.ts, providerMaintenance.ts, serverSettings.ts, plus the touched web/mobile/client-runtime/contracts modules.

Checks performed and passing:

  • Imports: Effect modules imported as subpath namespaces; named imports limited to @t3tools/contracts, pure helpers, schemas, and type-only service shapes.
  • Service shape: OmpAdapterShape mirrors the existing Services/*Adapter.ts pattern; `AcpSessionRuntime[

πŸ” Agent activity β€” 17 tool calls

πŸ’­ I'm checking the current PR head at e9ce63c to see if prior flagged issues from earlier commits were fixed, looking through the new adapter and provider files like OmpAdapter.ts, OmpDriver.ts, and AcpTextGeneration.ts. I notice OmpAdapterShape extends ProviderAdapterShape as a standalone interface, which seems to conflict with the convention of defining service interfaces inline in Context.Service declarations rather than keeping separate Shape types -- but this might just follow an existing pattern used by CursorAdapter or GrokAdapter, so I want to verify against those before flagging it.

1. browse_code β€” apps/server/src/provider/Services/*.ts

2. browse_code β€” apps/server/src/provider/Services/OmpAdapter.ts

πŸ’­ This aligns with existing repo conventions. Checking the current state of the previously flagged issues, I'm confirming the AcpTextGeneration catchTags fix, the OmpDriver error detail fix, and now looking at the OmpAdapter attachment detail to verify it's been addressed too. Now I want to check whether the Cursor JSDoc that was flagged as missing on makeCursorTextGeneration has since been restored, so I need to pull up the current file. Since the diff I'm looking at reflects the final merged state at head e9ce63c, the prior findings seem to already be addressed there, so now I'm reviewing this diff fresh for any new violations. Starting with AcpTextGeneration.ts, a new module that's a factory rather than a service, I'm scrutinizing its type-only imports from AcpSessionRuntime against the convention about how named imports should be scoped for pure helpers versus service modules. I'm also checking makeAcpTextGeneration's config.makeRuntime, which returns an effect producing a runtime instance passed into a callback rather than injected directly, so that pattern looks acceptable β€” and the Runtime type alias uses the recommended Foo["Service"] form. Now I'm looking at OmpAcpSupport.ts, where OmpAcpRuntimeInput includes a childProcessSpawner typed as ChildProcessSpawner["Service"], which raises the question of whether passing a service instance as a parameter counts as improper service injection β€” I want to compare this against how CursorAcpSupport and GrokAcpSupport handle the same pattern to see if it's an established convention.

3. git_tools β€” childProcessSpawner

4. browse_code β€” apps/server/src/textGeneration/CursorTextGeneration.ts

πŸ’­ I'm weighing whether flagging OmpAcpSupport's childProcessSpawner param is fair, since it mirrors the same pattern already used in CursorAcpSupport, GrokAcpSupport, and DevinAcpSupport β€” even though this is production code rather than tests, singling out the new module for consistency with established siblings feels like it might be an unnecessary nitpick. Now I want to check the remaining new code for real issues, particularly OmpAdapter.ts β€” looking at how errors are constructed, whether Cause.pretty leaks into client-facing reason strings, and how imports are structured. I'm confirming that both OmpAdapter.ts and OmpProvider.ts import ChildProcessSpawner in ways consistent with existing files like CursorTextGeneration, so that pattern checks out. Let me pull up the relevant sections of OmpAdapter.ts to verify.

5. git_tools β€” Cause.pretty|catchTag(|catchIf|Schema.is(|ManagedRuntime|runPromise

6. browse_code β€” apps/server/src/provider/Errors.ts

πŸ’­ I'm now checking whether logging Cause.pretty(cause) inside an error annotation counts as reintroducing a serialized cause field alongside a sanitized error, since the guideline warns against pairing sanitized errors with a parallel log payload containing raw defect text. I want to see if this same pattern of logging with Cause.pretty appears elsewhere in the repo as an established convention, and I also recall a prior run flagged errorMessage at an earlier commit which has since been fixed.

7. git_tools β€” cause: Cause.pretty

πŸ’­ Now I'm checking OmpAdapter.ts for error construction patterns around attachment reading, looking at lines flagged for invalid attachment id and failed read errors that carry the cause message along with the error detail. I'm also examining mapOmpAcpToAdapterError, a small wrapper that builds a ProviderAdapterRequestError with a fixed provider and detail string. Since it's reused across five or more call sites (session start, prompt, cancel, configuration mapping), it likely qualifies as adding legitimate reusable context rather than being a trivial pass-through constructor. I want to check whether sibling adapters like CursorAdapter or GrokAdapter follow the same pattern before deciding whether to keep it as-is.

8. git_tools β€” function map.*AcpToAdapterError|mapAcp|ToAdapterError

πŸ’­ I notice OmpAdapter defines its own local mapOmpAcpToAdapterError instead of reusing the shared mapAcpToAdapterError helper from AcpAdapterSupport that CursorAdapter and GrokAdapter use. I want to check whether that shared helper does real normalization, like classifying session-closed errors, to see if OmpAdapter should be using it too.

9. browse_code β€” apps/server/src/provider/acp/AcpAdapterSupport.ts

πŸ’­ I'm weighing whether the new Omp helper actually violates convention: it avoids putting raw error messages into the detail field, which is good, but it loses the classification logic that turns an ACP process-exit failure into a proper SessionClosedError instead of a generic request error. While it's not purely a trivial passthrough helper (since it's reused across five sites), it still effectively duplicates the shared mapper without preserving the finer-grained error classification, which seems like a legitimate finding worth flagging. I'll flag this as a moderate finding, phrased as a suggestion, since OmpAdapter reuses the shared mapper appropriately. Moving on, I want to check OmpProvider.ts β€” it's pure functions plus Effect, no service class, with checkOmpProviderStatus using Effect.fn and result/failure predicates. One thing catching my eye: enrichOmpSnapshot provides an HttpClient service instance directly through an input object field, which seems unusual, so I want to compare it against how sibling providers like OpenCode or Cursor structure their enrich functions to see if this pattern is consistent.

10. git_tools β€” export const enrich

πŸ’­ I'm checking the import style in AcpTextGeneration.ts against sibling adapters β€” they use a namespace import for AcpSessionRuntime while this new file imports specific types, so I need to reconcile that with the established convention of importing local service modules as namespaces at service boundaries. Since it's actually a type-only import used to derive Runtime = AcpSessionRuntime["Service"], that fits the exempt case for standalone types, so I'll skip flagging it. Now I want to verify JSDoc was preserved in GrokTextGeneration.ts the way it was restored for Cursor's version.

11. browse_code β€” apps/server/src/textGeneration/GrokTextGeneration.ts

12. browse_code β€” apps/server/src/textGeneration/AcpTextGeneration.ts

πŸ’­ These changes seem fineβ€”the refactor dropped tracing wrappers on generator functions in favor of plain arrow functions in a shared helper, which is a minor behavioral shift but not tied to any listed convention, so I'll skip flagging it. Now I'm moving on to review the changes in ProviderCommandReactor.ts. Five new module-level Schema.is predicate constants were added for error classes; they're private but used directly rather than wrapped in redundant functions, matching the existing pattern in the file, so that's fine. Looking at the error-classification logic in resolveProviderErrorDetail, it uses if-chains with schema predicates to inspect a Cause's fail reason rather than catching errors, so it doesn't clearly violate the guidance against using catchIf for known tagged variantsβ€”though a switch on _tag might be cleaner, it's not a listed violation. That function is deriving client-visible messages from structured errors, like mapping SessionClosed to "Provider session is closed," which looks reasonable. I'm now scanning normalizeThreadInteractionMode and OmpAcpSupport.ts for convention issues, checking that runtime construction and imports mirror the existing CursorAcpSupport pattern, then moving to check import ordering and error-class usage in OmpAdapter.ts. The error imports there don't include a session-closed variant, confirming the missing classification I noticed earlier, though the process/transport error constructions otherwise look consistent with similar adapters. The rest of the client-side and hook-based changes across web and mobile appear to be pure functions and standard React hooks, so I'm now checking whether any new module misuses Layer.succeed or the managed runtime. I want to verify OmpDriver's pattern of acquiring services and providing the child process spawner matches how CursorDriver does it, so I don't flag something that's actually an established convention.

13. browse_code β€” apps/server/src/provider/Drivers/CursorDriver.ts

πŸ’­ OmpDriver missing a module-level JSDoc that siblings have isn't a real issue since this is moved code, so I'll skip it. I'm now checking OmpAdapter's stopSessionInternal and event flow for similar convention concerns.

14. git_tools β€” ManagedRuntime|runPromiseExit|.runPromise|Layer.succeed

πŸ’­ I'm double-checking whether OmpAcpSupport actually uses the same Layer.succeed pattern for ChildProcessSpawner, since my earlier grep may have missed it despite the diff showing it there. Turning to AcpSessionRuntime.ts, I see it added awaitExit, cancelPendingPrompt, and clearPendingCancel, moved configOptionCurrentValueMatches into AcpRuntimeModel.ts, and swapped out sessionConfigOptionsFromSetup for direct Ref.set on configOptions. I want to verify whether sessionConfigOptionsFromSetup is now dead code left over from that refactor.

15. git_tools β€” sessionConfigOptionsFromSetup

πŸ’­ I'm checking that resolveProviderErrorDetail exposing error.issue matches the existing pattern for client-visible errors, and confirming normalizeThreadInteractionMode correctly builds its command ID from the source event ID. I'm now scanning OmpProvider.ts and OmpTextGeneration.ts for error-modeling issues, but both look consistent β€” snapshots don't leak errors and the invalid attachment error uses proper detail formatting. I'm also checking that mapOmpAcpToAdapterError properly classifies ProviderAdapterSessionClosedError so a session closing mid-request gets reported with the right user-facing message rather than falling through to a generic error. The real issue is that a process-exit failure during an OMP ACP request would surface as a generic request error instead of the specific session-closed message, even though the OMP adapter handles process exit separately elsewhere. Per the established convention, a reused mapper should keep this classification centralized rather than duplicated in a local helper that drops it β€” so I'll flag this as a finding recommending reuse of mapAcpToAdapterError, though I note that mapper still has the previously-flagged issue of copying error.message directly into detail. Since this is a genuine convention violation around error classification, I'm weighing whether it's substantial enough to fail the check rather than report "All clear," and I'm leaning toward treating it as a real finding that warrants a failure state. Let me also double-check OmpAdapter more broadly for similar issues with error detail and structural fields before finalizing, particularly around lines 60-260 and 400-520.

16. browse_code β€” apps/server/src/provider/Layers/OmpAdapter.ts

πŸ’­ I'm noting that mapOmpAcpToAdapterError types its cause as unknown instead of the typed AcpError that sibling functions use β€” that's a real classification issue worth flagging. I'll post an inline comment pointing out that this local mapper duplicates and weakens the shared error-mapping logic elsewhere. Checking the file scope confirms it matches, so I'm working out exactly which lines in the diff to attach the comment to β€” probably the range covering the function body. Before finalizing, I want to double-check whether this is a false positive, since OmpAdapter might deliberately handle exits differently through its own exit-awaiting logic rather than the shared error path. Weighing the conventions more carefully, wrapping a lower-level AcpProcessExitedError is explicitly permitted since it's not a domain error in the target channel, and the classification into a more specific session-closed error is described as optional rather than required. This looks more like a style/consistency suggestion than a hard violation, and the guidance is clear that I should only flag concrete rule violations, not optional preferences β€” so I'm leaning toward not reporting this. But looking further, there's a firmer rule against helpers that only construct an error without any normalization or pass-through, and mapOmpAcpToAdapterError matches that description exactly since a shared normalizing mapper already exists in the codebase doing the same job. Used at five sites, it does add the provider constant and detail string, similar to what the shared mapper already does β€” so a fair comment would be to either reuse the existing shared mapper or extend the local one to perform equivalent classification. Since findings default to failure per the customer's rule, I lean toward posting this comment and marking the check as failure, given the finding is genuinely grounded in the error-handling conventions. Let me scan for other potential violations I might have missed β€” checking the provider capabilities module, the ProviderRegistry import changes, and the OmpProvider status check logic β€” but these all look consistent with the established patterns. I'll settle on the single comment and phrase it concisely with a suggested fix. I considered proposing a signature change to consolidate the error-mapping function, but since that would require updating five call sites and imports, it's not feasible as an inline diff suggestion. I'll post the review comment without a diff.

17. modify_pr β€” One finding on the new OMP adapter's ACP error translation. Everything else in the changed Effect service code looks consistent with the conventions (namespaced effect/* imports, Foo["Service"] usage, dependencies acquired from the environment, Schema.TaggedErrorClass failures with structural detail plus preserved cause, and Effect.catchTags for known tags).


Agent Credits: 299 credits