Repository navigation
Effect Service Conventions: 7 issues found
Reviewed the new teleport service and its call sites against the Effect service conventions. Seven violations were posted as inline comments.
apps/server/src/teleport/Services/TeleportService.ts— service is split intoServices/(tag) andLayers/(construction + layer) and retains a standaloneTeleportServiceShape; should be one canonical module with the interface declared inline inContext.Service.apps/server/src/teleport/Layers/TeleportService.ts— construction is inlined intoTeleportServiceLive; export a realmakeand the canonicallayer.apps/server/src/teleport/Layers/TeleportService.ts—mapDispatchErroris a curried error-factory alias used only withmapError; construct the error at each failure boundary with real context.apps/server/src/teleport/Layers/TeleportService.ts—Effect.catchTag("PlatformError", ...)at lines 513 and 746; useEffect.catchTags.apps/server/src/teleport/Layers/TeleportService.ts—Effect.catchIf(isIgnorableProviderStopError, ...)recovers known_tagvariants; useEffect.catchTagsand drop the predicate.packages/contracts/src/teleport.ts—TeleportInvalidInputError(andTeleportDiscoveryError,TeleportProjectResolutionError) store an unstructuredmessageas their only data and serve as catch-alls for distinct failures; model structural attributes and derivemessage.apps/server/src/ws.ts— service imported with a named import at a service boundary; use a module namespace import as every other service in the file does.
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.
Methodology: reviewed the full diff, then read the new teleport service modules at head (teleport/Services/TeleportService.ts, teleport/Layers/TeleportService.ts, teleport/fileLock.ts, teleport/formats/*, packages/contracts/src/teleport.ts) and compared them with existing canonical repository patterns (apps/server/src/workspace/WorkspacePaths.ts for tag/make/layer layout, packages/contracts/src/vcs.ts for structured errors with derived message, and the namespace-import convention used throughout apps/server/src/ws.ts).
Not flagged: the projection/reducer/migration changes (no service-definition impact), the Services/Layers split in pre-existing orchestration, provider, and persistence directories, and the new teleport tests, which cover real behavior changes rather than a mechanical refactor.
🔍 Agent activity — 1 tool call
💭 I'm spotting a violation in the new TeleportService file — the service interface is defined separately as
TeleportServiceShapeinstead of being declared inline within theContext.Servicecall, which breaks the convention. The file structure also looks off with the teleport services nested in their own directory. Looking at the existing codebase, I see there's already a pattern of splitting services and layers into separate directories, but the conventions say new code should consolidate these into a single canonical module. The instructions treat the conventions as authoritative even when older code diverges, so this new service should probably be restructured to follow that single-module approach rather than perpetuating the legacy split pattern. There are also issues with the layer export naming — it should beexport const layerfollowing convention, and the construction logic should be extracted into amakefunction rather than inlined in theLayer.effectcall. For imports, the service boundary needs to be cleaner: if the files were merged, the cross-module import wouldn't be needed at all, and consumers likews.tsshould import the service tag properly. Looking at how the errors are structured inteleport.ts, they're usingSchema.TaggedErrorClasswith unstructured message fields, but the convention is to define structured attributes and derive the message from those rather than storing it directly. The real issue is thatTeleportInvalidInputErroris being used as a catch-all for many different failure scenarios — "already in progress", "cwd mismatch", "duplicate session", etc. — which is exactly the anti-pattern of a generic error with free-form messages wrapping multi-step pipelines. There's also a helper function that creates these errors with just a message and cause, which reinforces this problematic pattern. Additionally, the code usesEffect.catchIfwith a predicate that checks for specific_tagvariants like "ProviderValidationError" or "ProviderSessionNotFoundError", but the convention says to useEffect.catchTagsinstead for statically known tagged failures — usingcatchIfwith a schema predicate just to recover known tags is another violation. In fileLock.ts, there's aTeleportFileLockedErrorbeing constructed in a catch handler but then immediately discarded withorElseSucceed, and the underlying error cause isn't being preserved — the convention requires keeping the immediate underlying error ascause, so this should be refactored to maintain that chain. Then in homes.ts, there's direct use ofprocess.env.XDG_DATA_HOMEandNodeOS.homedir()inside an Effect function, which hides runtime dependencies rather than acquiring them through services, though they've disabled the diagnostic for this so it's probably not a core concern here. Also in registry.ts, there's a module-globalMapstoring format adapters, which violates the pattern of not hiding mutable state in module globals or closures over singleton services. The registry Map is a module-level dependency that the service reads from, which feels like a legitimate violation of the convention, though I'm not entirely confident. The mutableinFlightSet inside the layer is fine since it's per-instance state. Let me dig into the repo structure to see how other services define their tags, name their layers, and handle imports. Looking at the codebase structure, I see there's a pattern where some services are consolidated into single canonical files likeworkspace/WorkspacePaths.ts, while others still use the legacy split betweenServices/andLayers/directories. The new teleport service is following that older split pattern, but according to the consolidation guidelines, I should merge the domain-specific files and schemas into one canonical module at the domain level, hoisting the combined result up from the split structure. Looking at the WorkspacePaths pattern, I need to verify the end of that file to confirm the canonical structure withmakeandlayerexports. For the new teleport service, I'm consolidating the split Services and Layers files into a singleTeleportService.ts, inlining theTeleportServiceShapeinterface, and renamingTeleportServiceLiveto justlayer. Now I need to check how ws.ts imports other services to match the pattern — whether it uses namespace imports likeimport * as TeleportService from ...or direct imports. I'm also noticing several violations: the error factory helpermapDispatchErroris curried when it shouldn't be,Effect.catchIfshould beEffect.catchTags, and the error classes store unstructuredmessagefields instead of deriving them from stable domain attributes. Let me search the codebase to see how existing contract errors handle this and verify the import conventions in ws.ts. I'm noticing that the new teleport.ts errors storemessageas a direct field, which breaks the pattern established in other error contracts wheremessageis derived from structural attributes instead. Let me verify this against examples like vcs.ts to confirm they follow the proper convention, and also check how services are imported across the codebase to see if there's consistency in the import style. I'm seeing that ws.ts violates the pattern by using a named import for the teleport service at a service boundary, while the codebase consistently uses namespace imports elsewhere. Server.ts has the same issue with its TeleportServiceLive import, though I'm noticing the legacy Layers directories throughout the repo export theseXxxLivenames as a convention, so I need to check how server.ts handles other layer imports to understand if this is a widespread pattern or a specific violation. Now I'm planning to gather the exact line numbers from the PR diff to post targeted review comments — I need to flag the standaloneTeleportServiceShapeinterface in Services/TeleportService.ts and suggest inlining it into the Context.Service definition while colocating the service and layer files according to the canonical structure. I also want to comment on the Layers file whereTeleportServiceLiveis exported, recommending thatmakeandlayerbe exported from the canonical module instead, and note that the layer is being constructed inline without a separatemakefunction. Beyond the structure issues, I'm tracking down themapDispatchErrorhelper location, theEffect.catchIfusage withisIgnorableProviderStopErrorthat should be migrated tocatchTags, and the error definitions in the contracts package wheremessageis being stored as a field — particularly inTeleportInvalidInputErrorand similar error types that should follow the established convention. There's also a minor import style issue in ws.ts where a named import should be converted to a namespace import, and potentially a note aboutfileLock.tswhere the error cause is being dropped in atryPromisecatch block and then swallowed byorElseSucceed, creating dead code that could be cleaned up. I need to locate the exact line whereEffect.catchIf(isIgnorableProviderStopErrorappears in the exportSession file. I'm noticing violations of the Effect convention at lines 513 and 746 wherecatchTagis used for single tags instead ofcatchTags. The convention explicitly states to usecatchTagseven when handling just one tag and to avoidcatchTagaltogether. I should flag both instances as violations of this stated rule. Now I'm mapping out the full set of comments I need to make: the standalone shape interface that should be inlined and colocated, theTeleportServiceLiveexport that needs refactoring, the trivial error factory that should be constructed at the failure boundary, thecatchIfwith tag switching that should usecatchTags, and the error message handling in the contracts module. I should also verify whether other services in the repository already store message fields in their contract errors to make sure I'm not making a false claim about this pattern, and I'll skip the fileLock.ts catch issue since it's lower value and would just add noise to the review. I see there's a conflict between the existing repo convention of usingmessage: TrimmedNonEmptyStringin error fields and the instructions to use Schema.TaggedErrorClass with structured attributes instead. The instructions take precedence, so I need to refactor the teleport error handling to follow the structured pattern rather than storing unstructured messages. TeleportInvalidInputError is the main issue—it's a catch-all that only stores a message and optional cause, which violates the structured error pattern. It's being used for about a dozen distinct failure scenarios (dispatch failures, thread load failures, session conflicts, in-flight conflicts) without capturing the contextual data like threadId or operation type. I'll flag this once with a focused comment on the TeleportInvalidInputError definition, noting the missing structural context. I also need to check the repo's usage ofEffect.catchTagsince the instructions explicitly say not to use it. Even though it's listed as something to flag, I should verify if it's worth calling out. I'll include a brief comment covering both instances and then examine the catchIf context around lines 595-615. I'm reviewing the TeleportService.ts file and noticing that the interface defined on lines 15-31 could be inlined directly into the Context.Service declaration rather than kept as a standalone shape, which would simplify the module structure. Looking at the remaining issues: line 137 has a layer name problem with a missingmakecall, lines 195-199 need attention for mapDispatchError, line 601 should usecatchTagsinstead ofcatchIf, and line 513 has acatchTagthat should becatchTagswith a note that line 746 has the same issue. I also need to review contracts/teleport.ts around lines 131-137 and check ws.ts line 126 for a namespace import issue. For the catchTags change, I'm considering whether to provide an inline suggestion that replaces the single-tag catchTag with a catchTags object pattern, but I need to keep the description textual since the full context spans multiple lines. Now I'm writing the review summary and title.
1. modify_pr — Effect service conventions review for the new teleport service. Findings below cover the service module layout, layer/make exports, error modeling, and tagged-error handling in the changed files.
Agent Credits: 150 credits