Skip to content

merge(teleport): stack OpenCode on Grok

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

Effect Service Conventions: 4 issues found

Reviewed the new teleport service and its contract errors against the Effect service conventions. Four violations were found and posted as inline comments.

  • apps/server/src/teleport/Services/TeleportService.ts: new service split across Services/ and Layers/ modules and retains a standalone TeleportServiceShape instead of an inline Context.Service interface in one canonical module.
  • apps/server/src/teleport/Layers/TeleportService.ts: exports only TeleportServiceLive; no make export and no canonical layer export.
  • apps/server/src/teleport/Layers/TeleportService.ts: Effect.catchIf with a _tag predicate (isIgnorableProviderStopError) recovers statically known tagged failures; should use Effect.catchTags. Also mapDispatchError is a constructor-only curried error helper.
  • packages/contracts/src/teleport.ts: TeleportInvalidInputError (and TeleportDiscoveryError, TeleportProjectResolutionError) store an unstructured message as their only data, and TeleportInvalidInputError serves as a catch-all for several semantically distinct, caller-visible failures.

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 examined: new files under apps/server/src/teleport/**, packages/contracts/src/teleport.ts, and the affected call sites in apps/server/src/server.ts, apps/server/src/ws.ts, and apps/server/src/server.test.ts.

Checks that passed:

  • Dependency acquisition: the layer resolves ServerSettingsService, OrchestrationEngineService, ProjectionSnapshotQuery, ProviderSessionDirectory, ProviderInstanceRegistry, ProviderService, and Crypto from the Effect environment rather than accepting service instances.
  • No ManagedRuntime.make, runPromise, or runPromiseExit introduced in domain/service code; Layer.mock usage is confined to tests.
  • Effect modules are imported as subpath namespaces (effect/Effect, effect/Layer, effect/Option, ...); no consolidated named imports from "effect".
  • Backend behavior changes are accompanied by focused tests (teleport formats, cwd matching, decider, projection snapshot, provider interrupt settling).

Calibration reference for the error convention: packages/contracts/src/vcs.ts (VcsProcessSpawnError, VcsProcessExitError, VcsProcessTimeoutError) uses structured attributes with a derived message getter and static factories, which is the pattern the new teleport errors should follow.


🔍 Agent activity — 1 tool call

💭 Looking at the diff for the TeleportService, I'm spotting convention violations with the Effect service pattern. The main issue is that TeleportServiceShape is defined as a standalone interface, but the convention requires it to be defined inline within the Context.Service declaration rather than kept separate. There's also a structural problem: the service is split across Services/TeleportService.ts and Layers/TeleportService.ts, but the convention says to keep a service's schemas, Context.Service tag, construction, and layer together in one canonical module. While the repo does have existing Services/ and Layers/ directories, creating a new service in this split layout violates the consolidation principle. Additionally, the exports don't follow convention — it's exporting TeleportServiceLive instead of the canonical layer constant, and there's no make export even though the module owns construction. The import path also needs adjustment to reference the correct location. On the error definitions side, TeleportInvalidInputError stores an unstructured message field, but the convention calls for using Schema.TaggedErrorClass with structured attributes and deriving the message from those rather than storing it separately. The mapDispatchError helper is also problematic — it's a curried function that just wraps error construction without performing any real normalization, and the rule says to keep mappers only when they do meaningful work beyond simple construction. I'm also noticing Effect.catchIf(isIgnorableProviderStopError, ...) in the TeleportService layers violates the convention about catching known tagged failures — the pattern should use Effect.catchTags for statically known _tag variants rather than a schema predicate that just switches on those tags. I'm noticing process.env used directly in homes.ts which doesn't align with the conventions, though it might be a runtime boundary concern. I should check the repo to see how other services are defined—specifically whether they use inline interfaces in Context.Service—to understand the pattern better. I'm noticing the codebase has an older Services/Layers architecture split across orchestration, persistence, and provider layers, but the newer convention consolidates services into a single canonical module. I should look at a recently refactored example like WorkspacePaths to understand the current canonical pattern—inline interface, make function, and layer structure. I'm identifying architectural violations in the TeleportService implementation. The main issues are that the service interface should be inlined rather than standalone, the module structure is split across Services and Layers directories when it should be consolidated, and the layer export is using the wrong pattern—it's exporting the service instance directly instead of a proper layer export with a make function, and the construction is inlined rather than extracted into a separate factory function. I'm also flagging that Effect.catchIf with isIgnorableProviderStopError should use Effect.catchTags instead. There's a mapDispatchError helper that's essentially just wrapping error construction with a message parameter, which violates the rule against adding helpers that only construct errors—though it does add some context, so it might be borderline. The core issue is that the error types themselves are poorly designed: TeleportInvalidInputError, TeleportDiscoveryError, and TeleportProjectResolutionError all store only an unstructured message field, which violates the principle of deriving messages from structured attributes rather than storing raw text. These are RPC-serialized contract errors that cross the wire, so the message field is necessary, but the convention still applies—they should have richer structure. More problematically, TeleportInvalidInputError is overloaded for many semantically distinct failures like busy sessions, cwd mismatches, duplicate refs, and thread-not-found errors, when the convention says to split these into separate error classes. I've identified that the teleport errors are storing message as a schema field, which violates the repo's pattern of using structured attributes with a derived message getter instead. I need to flag TeleportInvalidInputError and its related errors in the teleport contracts file, then document the issues I'm finding across the codebase—starting with the standalone TeleportServiceShape that should be inlined and the problematic service split. For the import style, I'm noting that the repo uses both patterns inconsistently, so I'll keep this brief in the comment for point A rather than making it a separate item — once the service modules are consolidated, consumers should import the namespace directly. I'm also checking whether the new layer pulls dependencies from the environment. Looking at the format registry in formats/registry.ts, I see it's a plugin system mutated by import side effects with adapters that are Effect-returning functions needing FileSystem and Path from the environment. The rule about hiding dependencies in module globals targets Effect service dependencies, but this registry pattern with cross-test global state from resetTeleportFormats() does seem to violate that principle. more careful here — the registry pattern is genuinely a hidden dependency introduced in this PR, and the test mutation risk is real, so I should flag it as a finding even if it requires design changes to fully resolve. Now I'm narrowing down to the strongest violations: the standalone shape interface split across modules, the naming inconsistency with TeleportServiceLive missing the make convention, and a few others. Let me prioritize the clearest four or five findings that are most actionable. I need to pull exact line numbers from the new files to reference in inline comments—for the Services file that's around lines 15-27 for the shape interface and 29-31 for the class definition, and for the Layers file I need to locate where the effect is declared, where mapDispatchError appears, and where the error handling logic sits. I found the isIgnorableProviderStopError definition around lines 118-129 where it switches on the _tag property. Since I need line numbers from the diff's right side for inline comments, I'm ready to add the first comment block spanning lines 15-29 in Services/TeleportService.ts at the interface start. I'm also noting several other issues to address: the Layers/TeleportService.ts export naming should use make and layer conventions, line 601 needs catchIf changed to catchTags, line 195 has a mapDispatchError constructor helper, and the contracts file around lines 131-137 stores messages as the only data field across multiple error classes. Let me verify the catchIf helper locations and check if Effect.catchTags is available in the current effect version by searching the repo. Now I'm going through the code review with inline comments. I need to flag the standalone shape and split module in TeleportService, address the naming issue with make on line 137, add a comment about the catchIf helper that spans lines 126–135 and 601, and note something about line 195. For the mapDispatchError helper on line 4, I'm realizing it violates the rule about not keeping helpers that are just constructor aliases—it's used six times with different messages but doesn't perform real normalization or add meaningful context. I should flag this and tie it to the broader point about constructing errors at the boundary once they have structural fields. For comment 3, I need to view the exact range around lines 595–615 to craft a proper unified diff or description of what the catchTags pattern should look like. I'm refactoring the error handling to use catchTags instead of catchIf, which will provide more specific error type matching for the provider validation error while maintaining the same logging behavior.

1. modify_pr — Effect service conventions review of the new TeleportService (plus its contract errors). Four convention violations found; details inline.


Agent Credits: 202 credits