Repository navigation
Effect Service Conventions: 1 issue found
1 finding
apps/server/src/orchestration-v2/testkit/ProviderReplayHarness.ts— the newly addedtransformEventSinkoption (lines 185, 226, 246) types the event sink with the standaloneEventSinkV2Shapeinterface instead of the inferred service interfaceEventSinkV2["Service"]; the harness already usesServerConfig["Service"]at line 70. Switching also removes the need for the newtype EventSinkV2Shapeimport.
Previously flagged items are resolved at this head commit: AttachmentMcpService.make is exported alongside layer, OrchestratorV2Shape.getCommandReceipt now uses CommandReceiptStoreV2["Service"]["getByCommandId"] (and the CommandReceiptStoreV2Shape import was dropped), and OrchestratorMcpAttachments.test.ts imports the service module as a namespace.
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
apps/server/src/mcp/AttachmentMcpService.ts— canonical layout (imports,Context.Servicetag with inline interface, exportedmake, exportedlayer), Effect subpath namespace imports, and all dependencies (ServerConfig,ServerSecretStore,FileSystem) acquired viayield*and reflected in the layer requirements. No violations.apps/server/src/mcp/toolkits/attachment/{tools.ts,handlers.ts}— mirror the existing worktree/orchestrator toolkit modules exactly (namespace import forMcpInvocationContext, tag import for the service,satisfies Parameters<typeof Toolkit.toLayer>[0]). No violations.apps/server/src/mcp/McpHttpServer.ts— new registration layer usesAttachmentMcpService.layerthrough a namespace import.apps/server/src/mcp/OrchestratorMcpService.ts— newFileSystem/ServerConfigdependencies are acquired from the environment and added to the exportedlayerrequirement type; helper wrappers only re-provide already-acquired services, so nothing is hidden in module globals or a private runtime. NoManagedRuntime.make,runPromise, orrunPromiseExitintroduced.apps/server/src/orchestration-v2/ThreadManagementService.ts—ThreadManagementPostDispatchProjectionErroris aSchema.TaggedErrorClasswith structured attributes (projectId,threadId,messageId,dispatchReplayed), preserves the realcause, derivesmessagesolely from its attributes, and is added to theSchema.Unionerror type.getCommandReceiptis typed asOrchestratorV2["Service"]["getCommandReceipt"].apps/server/src/orchestration-v2/Orchestrator.ts,AttachmentClaims.ts,ThreadLaunchService.ts— behavior changes are accompanied by focused tests;Layer.mock/service-instance passing occurs only in test harnesses.packages/contracts/src/attachmentMcp.ts— schema/error module;AttachmentMcpFailurefollows the same shape as the existingOrchestratorMcpFailure/WorktreeMcpFailureMCP tool failure contracts.
Pre-existing standalone FooShape interfaces (OrchestratorV2Shape, ThreadManagementServiceShape, EventSinkV2Shape definitions themselves) were not flagged: they are untouched legacy declarations outside this PR's changed scope.
🔍 Agent activity — 13 tool calls
💭 I'm reviewing whether the previously flagged Effect service convention issues were fixed at the head commit. The AttachmentMcpService export looks corrected, and I'm now checking the Orchestrator.ts type reference for the command receipt store to confirm it matches what's expected. Now I'm scanning imports in AttachmentMcpService.ts and confirming they follow the namespace-import convention correctly. I'm also flagging a
failure()helper function whose only job is constructing anAttachmentMcpFailureerror object — this mirrors an existing pattern in OrchestratorMcpService.ts, but since AttachmentMcpService.ts is a new file, it may be introducing a convention violation by adding this same anti-pattern helper. I'm also considering whether error mapping calls likeEffect.mapErrorthat discard the underlying cause violate the convention of preserving root causes, but since the AttachmentMcpFailure contract type only has code and message fields (mirroring OrchestratorMcpFailure), this may be an intentional design choice tied to the new contract schema rather than a genuine bug. I decide not to flag the free-form message pattern since it exactly mirrors the existing OrchestratorMcpFailure approach and prior review passes let it slide, so raising it now would be inconsistent. I want to pull up the actual current file contents to check for real issues like misuse of Layer.succeed or standalone shape types, and I recall EventSinkV2Shape being a pre-existing pattern already used elsewhere in the testkit. The testkit's newtransformEventSinkoption uses EventSinkV2Shape directly rather than the preferredEventSinkV2["Service"]convention — this parallels a case in Orchestrator.ts where the author already fixed an analogous CommandReceiptStoreV2Shape issue after review, so this looks like a legitimate, consistent finding worth flagging again. I also want to check ThreadManagementService.ts and OrchestratorMcpService.ts, but those look fine on inspection — they use the correct["Service"]access pattern and standardprovideServicere-provisioning.
1. browse_code — apps/server/src/orchestration-v2/EventSink.ts
2. browse_code — apps/server/src/mcp/AttachmentMcpService.ts
💭 I'm confirming EventSinkV2Shape is a pre-existing interface not touched by this PR, and checking whether EventSinkV2 is set up as a Context.Service. I'm also looking at how AttachmentMcpService's
makefunction acquires FileSystem, ServerConfig, and ServerSecretStore, then re-provides them into helper functions.
3. git_tools — EventSinkV2Shape|class EventSinkV2|Context.Service<\s*EventSinkV2
💭 EventSinkV2Shape is pre-existing and already used broadly, so this is legacy convention, not something introduced by this PR—the harness just consumes it. Since this falls under optional style preferences on unrelated legacy code, and I recall similar precedent with CommandReceiptStoreV2Shape being flagged only when it appeared in new declarations, I shouldn't flag this here. I'm moving on to scan the rest of the changed files for stronger, more substantive findings—starting with import ordering and structure in OrchestratorMcpService.ts. Then I turn to toolkits/attachment/handlers.ts, where the service tags are imported by name rather than as a namespace at what looks like a service boundary. I'm weighing whether this matches the convention violation pattern seen elsewhere, comparing it against sibling files like tools.ts to see if there's an inconsistency worth flagging.
4. browse_code — apps/server/src/mcp/toolkits/orchestrator/handlers.ts
5. browse_code — apps/server/src/mcp/toolkits/worktree/handlers.ts
💭 The new handlers file matches the existing pattern fine, and the McpHttpServer import for AttachmentMcpService looks correct as a namespace import. I'm checking the providersCache variable in OrchestratorMcpService and it seems fine since it's a local, per-invocation cache rather than a shared module global. The new error class uses the structured tagged-error pattern correctly with message derived from attributes and a Defect cause. I'm verifying that OrchestratorCommandIdConflictError already exists pre-diff since it's referenced by canReplayCommandReceipt, and checking the layerUnavailable pattern where getCommandReceipt dies via Effect—this matches an existing convention. I'm also confirming the CommandReceiptStoreV2 import and the optional replayed field on OrchestratorV2DispatchResult look fine, along with the attachmentMcp contracts file being schema-only with no service concerns, and the mime-types import being used correctly as a type cast. Now I'm checking whether the mock layer usage in tests is an acceptable test seam, and confirming NodeFS.writeFileSync in the attachment test is fine too. I'm flagging a potential convention violation: the
failure(code, message)helper is exactly the pattern the guidelines discourage—a trivial wrapper that just constructs an error—but since OrchestratorMcpService.ts and WorktreeMcpService.ts already have this identical helper, I want to check WorktreeMcpService to confirm it's an established pattern rather than a new violation.
6. git_tools — function failure(
7. browse_code — apps/server/src/orchestration-v2/Orchestrator.ts
💭 Good, that prior finding is fixed now. I'm weighing whether to flag the
failurehelper — it matches a pattern used in two sibling MCP services, so flagging it feels like an inconsistent nitpick, even though the guideline explicitly discourages a helper that only wraps args into an error. Since the instructions say to treat these guidelines as authoritative over older code conventions, I lean toward following the guideline here. Looking closer, the helper does add narrowing/typing forcodeand is used four times, so it's not just a curried mapError alias used once — I'll let it pass since it mirrors sibling services and the attributes stay visible at call sites. Now I'm checking whether the harness's use ofEventSinkV2Shapeshould be flagged against the convention of referring to the inferred service interface asFoo["Service"], but sinceEventSinkV2Shapeappears to be the canonical exported interface used elsewhere, I need to verify that before deciding.
8. git_tools — ["Service"]
9. browse_code — apps/server/src/orchestration-v2/testkit/ProviderReplayHarness.ts
💭 Since the harness already uses
ServerConfig["Service"], suggestingEventSinkV2["Service"]for the new transformEventSink signatures fits the existing convention and would let them remove the unnecessary type import. This looks like a legitimate convention violation worth flagging, since the rule explicitly calls for referencing the inferred interface including harnesses. I'll comment on the import line since it covers all three usages of the pattern, rather than posting separately on each occurrence. Checking the rest of the OrchestratorMcpService.ts diff, the dependency handling looks fine—services are passed explicitly through helper wrappers while still being properly declared in the layer's requirements. Import ordering in OrchestratorMcpService follows the pre-existing canonical pattern. Now I'm checking whether the import style in attachment/tools.ts is consistent with how other tool files like worktree/tools.ts structure their imports.
10. browse_code — apps/server/src/mcp/toolkits/worktree/tools.ts
11. browse_code — apps/server/src/mcp/McpHttpServer.ts
💭 The new attachment toolkit files match existing patterns fine, so the only remaining concern is whether
EventSinkV2Shapein the testkit harness counts as a violation. Since it's a pre-existing, already-exported shape rather than something newly defined in this PR, the rule against standalone shape types likely doesn't apply here—just referencing it shouldn't trigger the same concern as creating one. Since I flagged the same pattern before withCommandReceiptStoreV2Shapeand it was accepted, I'll flag this one too for consistency, treating it as a low-severity but real convention deviation. I want to scan the other touched files for similar standalone shape references or riskyLayer.succeedusage—checkingThreadManagementService.ts, I see it correctly references the service interface for one member, but there's also a pre-existing standaloneThreadManagementServiceShapeinterface that the PR extends rather than replaces, which is a retained legacy pattern worth noting. This is marginal enough that I'm weighing whether it truly deserves failing status versus a low-severity note, especially given the check defaults to failure absent real findings. I'm scanning the rest of the diff for genuine violations—OrchestratorMcpService's error dispatch helper and ThreadManagementService's projection error type both look fine, nothing else jumping out yet. I want to double check the exact type signature used for getCommandReceipt against the actual source before flagging anything.
12. browse_code — apps/server/src/orchestration-v2/Orchestrator.ts
💭 With that settled, I'm now confirming that referencing EventSinkV2["Service"] matches the convention used elsewhere in the repo, like Orchestrator.ts and the harness's ServerConfig pattern, so I'll draft one comment with an inline suggestion reflecting that. Since the changes span multiple lines (185, 226, 246) plus an import removal, an inline suggestion won't cleanly apply — I'll just describe the fix in prose rather than provide a diff. Given the guidance that this check defaults to failure when findings exist, I'm leaning toward marking the result as a failure rather than neutral, since this is a real convention deviation rather than just a style preference. I'm also weighing whether the EventSinkV2Shape usage in the integration harness counts as a genuine violation of the interface-naming rule — it does, since it's new code in the changed scope referring to the service type directly rather than through the required convention. That settles it: I'll report a single flagged comment and set the overall state to failure, since the rule explicitly ties findings to a failing check rather than "All clear." Let me scan a few more changed files for stronger violations: the orchestrator service imports, the registration test's mock layer usage, the attachment integration test's helper imports, and the attachment upload functions running inside an Effect environment with secret store layers — all look like legitimate patterns, not convention breaks. I've settled on one file to flag:
ProviderReplayHarness.ts, where the added import line forEventSinkV2Shapeon the diff's right side is the spot to comment, noting the state issue and its fix.
13. modify_pr — Effect service conventions review: one finding on the new transformEventSink type signatures in the replay harness.
Agent Credits: 131 credits
Token usage: 18 uncached input · 670,681 cache-read input · 95,932 cache-write input · 12,261 output
Agent Credits may also include non-token charges from external tools such as web research.