Skip to content

test(teleport): use generic fixture paths

MacroscopeApp / Macroscope - Effect Service Conventions failed Aug 15, 2026 in 3m 4s

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 into Services/ (tag) and Layers/ (construction + layer) and retains a standalone TeleportServiceShape; should be one canonical module with the interface declared inline in Context.Service.
  • apps/server/src/teleport/Layers/TeleportService.ts — construction is inlined into TeleportServiceLive; export a real make and the canonical layer.
  • apps/server/src/teleport/Layers/TeleportService.ts — mapDispatchError is a curried error-factory alias used only with mapError; 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; use Effect.catchTags.
  • apps/server/src/teleport/Layers/TeleportService.ts — Effect.catchIf(isIgnorableProviderStopError, ...) recovers known _tag variants; use Effect.catchTags and drop the predicate.
  • packages/contracts/src/teleport.ts — TeleportInvalidInputError (and TeleportDiscoveryError, TeleportProjectResolutionError) store an unstructured message as their only data and serve as catch-alls for distinct failures; model structural attributes and derive message.
  • 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 TeleportServiceShape instead of being declared inline within the Context.Service call, 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 be export const layer following convention, and the construction logic should be extracted into a make function rather than inlined in the Layer.effect call. 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 like ws.ts should import the service tag properly. Looking at how the errors are structured in teleport.ts, they're using Schema.TaggedErrorClass with 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 that TeleportInvalidInputError is 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 uses Effect.catchIf with a predicate that checks for specific _tag variants like "ProviderValidationError" or "ProviderSessionNotFoundError", but the convention says to use Effect.catchTags instead for statically known tagged failures — using catchIf with a schema predicate just to recover known tags is another violation. In fileLock.ts, there's a TeleportFileLockedError being constructed in a catch handler but then immediately discarded with orElseSucceed, and the underlying error cause isn't being preserved — the convention requires keeping the immediate underlying error as cause, so this should be refactored to maintain that chain. Then in homes.ts, there's direct use of process.env.XDG_DATA_HOME and NodeOS.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-global Map storing 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 mutable inFlight Set 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 like workspace/WorkspacePaths.ts, while others still use the legacy split between Services/ and Layers/ 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 with make and layer exports. For the new teleport service, I'm consolidating the split Services and Layers files into a single TeleportService.ts, inlining the TeleportServiceShape interface, and renaming TeleportServiceLive to just layer. Now I need to check how ws.ts imports other services to match the pattern — whether it uses namespace imports like import * as TeleportService from ... or direct imports. I'm also noticing several violations: the error factory helper mapDispatchError is curried when it shouldn't be, Effect.catchIf should be Effect.catchTags, and the error classes store unstructured message fields 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 store message as a direct field, which breaks the pattern established in other error contracts where message is 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 these XxxLive names 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 standalone TeleportServiceShape interface 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 where TeleportServiceLive is exported, recommending that make and layer be exported from the canonical module instead, and note that the layer is being constructed inline without a separate make function. Beyond the structure issues, I'm tracking down the mapDispatchError helper location, the Effect.catchIf usage with isIgnorableProviderStopError that should be migrated to catchTags, and the error definitions in the contracts package where message is being stored as a field — particularly in TeleportInvalidInputError and 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 about fileLock.ts where the error cause is being dropped in a tryPromise catch block and then swallowed by orElseSucceed, creating dead code that could be cleaned up. I need to locate the exact line where Effect.catchIf(isIgnorableProviderStopError appears in the exportSession file. I'm noticing violations of the Effect convention at lines 513 and 746 where catchTag is used for single tags instead of catchTags. The convention explicitly states to use catchTags even when handling just one tag and to avoid catchTag altogether. 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, the TeleportServiceLive export that needs refactoring, the trivial error factory that should be constructed at the failure boundary, the catchIf with tag switching that should use catchTags, 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 using message: TrimmedNonEmptyString in 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 of Effect.catchTag since 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 missing make call, lines 195-199 need attention for mapDispatchError, line 601 should use catchTags instead of catchIf, and line 513 has a catchTag that should be catchTags with 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