Repository navigation
Effect Service Conventions: 1 issue found
1 finding
apps/server/src/orchestration-v2/Orchestrator.ts(line 179): the newgetCommandReceiptmember onOrchestratorV2Shapeis typed via the standaloneCommandReceiptStoreV2Shape["getByCommandId"](and adds atype CommandReceiptStoreV2Shapeimport) instead of the inferred service interfaceCommandReceiptStoreV2["Service"]["getByCommandId"], which is the form used by the adjacent members and by the mirrored member added inThreadManagementService.ts.
No other convention violations were found in the changed Effect service code.
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.
Reviewed
apps/server/src/scheduledTasks/ScheduledTaskService.ts— new manual-run errors are now distinctSchema.TaggedErrorClassdeclarations with structured attributes and messages derived from those attributes (prior findings onmessage: Schema.Stringpayloads andreasondiscriminators are resolved). Module order (imports, errors, tag, layer) is unchanged from the existing canonical layout;makeKeyedSerialExecutoris a pure helper, so the named import is appropriate.Effect.catchCausein the poll loop intentionally handles the whole channel while re-failing interrupts, which is allowed.apps/server/src/scheduledTasks/ScheduledTaskService.test.ts— usesimport * as ScheduledTasks from "./ScheduledTaskService.ts"andFoo["Service"][...]types; service instances are passed only through test harness seams (mapThreadManagement,getProject), which is a legitimate test seam rather than production injection. Backend behavior changed, so the added coverage is expected.apps/server/src/mcp/OrchestratorMcpService.ts—scheduledTaskManualRunFailuremirrors the existingthreadManagementFailuretranslation boundary and performs real classification across many tags, so it is not a redundant one-line error factory.apps/server/src/orchestration-v2/ThreadManagementService.ts,ThreadLaunchService.ts,apps/server/src/mcp/toolkits/orchestrator/*,packages/contracts/src/*,packages/shared/src/t3McpToolPresentation.ts— no service-definition, dependency-acquisition, or runtime-boundary violations (no newManagedRuntime.make,runPromise, or fakeLayer.succeedimplementations).
Not flagged
- Pre-existing standalone shapes (
OrchestratorMcpServiceShape,ThreadManagementServiceShape,CommandReceiptStoreV2Shapeitself) — legacy, outside this PR's scope apart from the new reference noted above. - New manual-run errors without a
causefield: the translated upstream error (ThreadManagementThreadNotFoundError) carries no context beyond thethreadId/projectIdalready captured on the new errors.
🔍 Agent activity — 10 tool calls
💭 I'm reviewing the diff for Effect service convention violations, checking ScheduledTaskService, Orchestrator, ThreadManagementService, the MCP toolkit, and contracts. The previously flagged issues with generic error messages and reason discriminators appear fixed now with distinct tagged error classes, so I'm moving on to check the new error classes in ScheduledTaskService.ts for remaining problems. Those new error classes lack a
causefield, but since they're mostly validation/domain errors that's acceptable per convention. I'm also examining the named import style in OrchestratorMcpService.ts, the test file's namespace import (which already got addressed), and whether the standaloneOrchestratorMcpServiceShapeinterface is pre-existing or newly introduced by this diff. Now I'm checkingCommandReceiptStoreV2Shape["getByCommandId"]in Orchestrator.ts against the preferredService["getCommandReceipt"]pattern used elsewhere, and verifying whether CommandReceiptStoreV2 is defined as a Context.Service to see if this usage should be flagged. I'm also confirming the test harness setup and the static error message forScheduledTaskManualRunTaskScopeErrorlook fine as-is. Moving on,taskErrorremains a pre-existing helper so it's not new debt, and theEffect.catchCauseinterrupt-preservation logic in ScheduledTaskService is intentional and consistent with convention. Now I'm looking atscheduledTaskManualRunFailurein OrchestratorMcpService, a switch-based error-to-error mapper, and weighing whether this translation logic should instead live as a static factory on the target error class per convention. I conclude it's one-off usage, so an inline switch is acceptable rather than forcing a static method, though I want to check if similar mapper patterns already exist elsewhere in that file. The domain errors lacking acausefield, likeScheduledTaskManualRunNotFoundError, look fine since they're pure domain errors. I want to actually inspect the files directly now, starting with CommandReceiptStoreV2.
1. git_tools — CommandReceiptStoreV2Shape
2. git_tools — OrchestratorMcpFailure|function failure
💭 The scheduled task manual run failure pattern matches the existing thread management failure convention, which is consistent. I'm checking that the pre-existing CommandReceiptStoreV2Shape interface is being referenced correctly, following the convention of using the inferred service interface's typed method signature rather than a separate type. Comparing against ThreadManagementService.ts, which correctly uses the canonical
Foo["Service"]form, I notice the new Orchestrator.ts line is inconsistent — it introduces a fresh import of the deprecated standalone Shape type instead. This looks like a legitimate, if minor, style violation introduced by the PR, since the convention explicitly calls for the canonical form even in mechanically updated code. I want to look more closely at ScheduledTaskService.ts's imports and structure next.
3. browse_code — apps/server/src/scheduledTasks/ScheduledTaskService.ts
4. browse_code — apps/server/src/scheduledTasks/ScheduledTaskService.ts
💭 I'm checking whether KeyedSerialExecutor is a pure helper module, which would justify keeping it as a named import rather than following the service-module convention. I also want to look at errors missing a
causefield, particularly around ScheduledTaskManager, to see if they're wrapping an underlying failure that should be preserved.
5. browse_code — apps/server/src/orchestration-v2/KeyedSerialExecutor.ts
6. browse_code — apps/server/src/scheduledTasks/ScheduledTaskService.ts
💭 KeyedSerialExecutor being a pure helper makes the named import fine. But I'm noticing loadScopedThread's mapError does a structural check on
cause._tagrather than using Effect.catchTags — and since conventions specifically discourage using catchIf-style predicates just to recover known tag variants, this pattern might need reconsidering, though it's technically mapError rather than catch. Actually this is a common translation pattern using a ternary on _tag, so it's arguably fine rather than a clear violation. What stands out more is that CallerScopeError and TargetScopeError don't appear to define a cause field, yet they're being used to translate a real underlying failure (ThreadManagementThreadNotFoundError) — which conflicts with the convention that translated errors should preserve the immediate underlying cause alongside their structural fields. I'm leaning toward flagging this lightly, though it risks being seen as a minor style nit rather than a hard violation. Let me move on to check the rest of the diff for stronger findings, including the test file — imports look properly consolidated from "effect" submodules and from "@effect/vitest", and the test harness setup appears reasonable so far. Looking at ThreadManagementService.ts, the shape interface change is pre-existing and fine, as are the MCP toolkit handlers. In orchestratorMcp.ts I notice a manual unicode well-formedness loop that duplicates functionality now available via a native string method, and there's apparent schema duplication between two client-request-id schemas where only one applies the well-formed check — a design inconsistency, but not something covered by the Effect service conventions I'm checking against, so I'll set it aside as out of scope. Error conventions in contracts look fine with the pre-existing OrchestratorMcpFailure. Now I want to check how OrchestratorV2Shape members reference other services' types in Orchestrator.ts, particularly around the CommandReceiptStoreV2Shape getByCommandId finding, so I'm searching for similar["Service"]references to establish whether there's a consistent pattern in this file.
7. git_tools — ["Service"][
💭 I'm noticing most of the codebase references services as
Foo["Service"]["member"], but the new Orchestrator.ts line imports a standaloneCommandReceiptStoreV2Shapetype and indexes into it directly instead. It's a mild inconsistency worth flagging, though I'm weighing whether it truly counts as a convention violation since the shape type is explicitly exported for this purpose. I keep the bar in mind: only clear convention violations should fail, not optional style preferences. I check other candidates — the test harness's Layer usage is fine since it's test code, ScheduledTaskService's inline construction without amakefunction is pre-existing rather than newly introduced, and the manual run result structure looks fine too. I'm now considering whether a small inline error-construction helper counts as a disallowed trivial wrapper. I'm also looking atscheduledTaskManualRunFailure, which classifies error tags into MCP failure codes, mirroring an existing pattern elsewhere in the codebase, so I don't think it's worth flagging given the precedent. I'm checking whether any new errors duplicate a distinction between a specific tag and a separate reason field, but I don't see that here. The strongest remaining candidate is that several new manual-run errors skip acausefield even though some wrap an underlying not-found error from thread management — I want to trace throughloadScopedThreadto see exactly how that mapping happens before deciding whether to flag it. Losing that cause chain does seem like a real, if minor, violation of the stated convention, but fixing it would mean touching two error classes and their construction sites, which isn't a small inline diff. I'm second-guessing whether flagging a third error-shape nit is too pedantic given prior rounds already caught similar issues, so I want to check if there are more substantive problems first, like the effect on cause handling elsewhere. I'm scanning for other convention violations — checking tagged failure handling, catchIf usage, and result/exit patterns, all of which look fine. One thing that stands out is an import line in OrchestratorMcpService.ts that pulls in a type and service directly rather than importing the local service module as a namespace, which the convention explicitly calls for at service boundaries. Looking closer, I see other imports in the same file also use named rather than namespace imports, so this pattern is mixed across the repo — probably not worth flagging on its own. Now I'm weighing whether to raise both this import issue and the cause-preservation finding, or stay quiet, since the check defaults to reporting "all clear" if nothing's flagged and two prior review rounds have already driven meaningful fixes. Verifying thatCommandReceiptStoreV2["Service"]["getByCommandId"]is a valid pattern here, since it mirrors howProjectionStoreV2is used in the same file — it checks out. But acting on it would leave an unused import, requiring edits across two separate hunks, and since cross-hunk changes in one file mean I can't produce a single clean diff, I'll just describe the two edits in prose instead of trying to force a unified diff. I'm also weighing whether losing the underlying error'scausein the loadScopedThread error-mapping counts as a real violation — since it's translating a genuine failure into a "not found" error, I think it does, and I'll raise it as a suggestion to preserve the cause. Still, I want to avoid piling on too many minor comments at once, so I'm considering consolidating into a single focused comment. Given the borderline nature, I'm leaning toward not failing the check unless I find something clearly wrong — so I want to do one more pass over the diff, especially checking the test file's use of the non-null assertion on the options object and whether the added tests are proportionate to the refactor or feel excessive. Reasoning through the tests confirms they're warranted since backend behavior actually changed. I'm noticing a minor import ordering inconsistency in the scheduled task test file, along with a named import that deviates slightly from the usual namespace convention, but neither seems worth flagging. In the contracts file I'm also spotting a helper function that duplicates existing built-in string functionality. Deciding I should just settle on posting two comments: one about theCommandReceiptStoreV2Shapesince it clearly violates the explicit convention of defining the service interface inline rather than keeping a standalone shape type, and one about cause-preservation, since that guideline is also unambiguous and applies to newly introduced code. I'm torn on the severity to assign — treating a type-alias nit as an automatic CI failure feels heavy-handed, but the guidance leans toward defaulting to failure unless everything is clear. Since the check explicitly defaults to failure rather than success, I'll go with failure. I'll keep both findings since they're distinct and actionable rather than trimming to just one, and now I want to double-check whether the error class in this codebase actually supports a cause field by looking at how ScheduledTaskError is defined in contracts.
8. git_tools — class ThreadManagementThreadNotFoundError
9. git_tools — class ScheduledTaskError
💭 I'm deciding to skip the not-found error finding since it carries no extra context beyond what's already replicated. Now I'm turning to evaluate whether the
CommandReceiptStoreV2Shapetype reference is a genuine deviation worth flagging. Reconsidering, the convention clearly intends for standalone shape types to be replaced by the inferred service interface, so referencing this shape type in new code does violate that rule's letter, even if minor. I'll go ahead and post the comment on it, treating it as a real, concrete finding rather than a stylistic quibble. Since fixing line 179 also requires removing the now-unused import on line 44, that's two hunks in one file, so per the rules I should skip the inline diff suggestion and just describe the change instead. I've confirmed the correct line number in the PR diff (line 179 of Orchestrator.ts) via the diff hunk and a grep check, so I'm ready to post the review.
10. modify_pr — One convention finding in the Effect service changes: new code in Orchestrator.ts references the standalone CommandReceiptStoreV2Shape type instead of the inferred Foo["Service"] interface. Everything else (tagged manual-run errors with derived messages, namespace imports, keyed serial executor as a pure helper, test-only service seams) looks consistent with the conventions.
Agent Credits: 182 credits
Token usage: 14 uncached input · 646,900 cache-read input · 175,271 cache-write input · 12,194 output
Agent Credits may also include non-token charges from external tools such as web research.