Repository navigation
Effect Service Conventions: 4 issues found
Reviewed the Effect service modules introduced by this branch. Four convention violations found in new service code (inline comments could not be attached because of a GitHub error, so they are listed here; the review body was posted).
apps/server/src/mcp/PreviewMidsceneService.ts(L211-229): standalonePreviewMidsceneServiceShapeinterface retained instead of defining the service interface inline in theContext.Servicedeclaration and referring to it asPreviewMidsceneService["Service"].apps/server/src/mcp/PreviewMidsceneService.ts(L457-463): productionmakereadsprocess.envdirectly, hiding an ambient dependency frommake/layer; acquire it from the environment (HostProcessEnvironment) instead.apps/server/src/provider/pi/PiRpcClient.ts(L20-57):PiRpcClientErrorstores an unstructureddetailstring as its only data with a free-formoperationand nomessagegetter (raw RPC error text is copied intodetail), andclientErroris a helper whose only behavior isnew PiRpcClientError({ ... }). Modeloperationas a literal union with stable structural fields, derivemessagefrom them, keep the underlying value only ascause, and construct the error at the failure boundary.apps/server/src/bundledSkills.ts(L57-74):registerBundledSkillsExtraRootself-providesNodePath.layer, hiding thePathrequirement from callers and preventing test substitution; and it usesEffect.catchwith aSchema.ispredicate to recover a single known tag, whereEffect.catchTags({ CodexAppServerRequestError: ... })is the intended form.
No findings for apps/server/src/mcp/preview-midscene/PreviewMidsceneRuntime.ts or apps/server/src/provider/Drivers/OmpDriver.ts, which follow the imports, tag/make/layer, and dependency-acquisition conventions.
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 and methodology:
- The PR reports 13,822 changed files and 1.45M added lines against
pingdotgg/mainbecause the fork branch carries a squashed upstream sync commit (chore(upstream): squash sync pingdotgg/t3code main) plus a merge of it. Reviewing the merge-base diff wholesale is not meaningful, so the review targeted the modules the fork actually introduces on top of upstream (9e0ea47..3495ffaplus the Pi/Midscene/OMP feature commits). - Files examined:
apps/server/src/provider/Drivers/OmpDriver.ts,apps/server/src/provider/pi/PiRpcClient.ts,apps/server/src/mcp/PreviewMidsceneService.ts,apps/server/src/mcp/preview-midscene/PreviewMidsceneRuntime.ts,apps/server/src/bundledSkills.ts,apps/server/src/provider/Services/PiAdapter.ts, plus repository-wide greps forManagedRuntime.make,Layer.succeed,catchTag,runPromiseExit, anddetail: Schema.Stringto distinguish new violations from established upstream patterns. - Confirmed each flagged file is absent from both the merge base (
f61fa94) and currentmain(06de9e9), so every finding is introduced by this PR rather than inherited.
Deliberately not flagged:
Effect.runPromiseExitinPreviewMidsceneService.runBrokerPromise: a clearly named imperative bridge into Midscene's Promise-based agent/device API, not a dependency of another Effect service.makePiRpcClient(transport):PiRpcTransportis a genuine port abstraction with a real test seam, not fake service injection.ProviderDriverError({ detail: \Failed to build ... ${cause.message}` })inOmpDriver.ts: identical to all six sibling drivers onmain`; changing only the new driver would be inconsistent repository-wide cleanup.apps/server/src/provider/Services/PiAdapter.tsis a type-only alias overProviderAdapterShape, matching the existing adapter directory layout rather than a compatibility re-export shim.
🔍 Agent activity — 23 tool calls
1. git_tools — f61fa94..3495ffa
💭 This diff is massive—1.8 million lines between the merge base and head, which seems off for a PR titled "codex/bundle-midscene-preview." I should query the PR files directly through the GitHub API instead of pulling the full diff.
2. github_api_read_only — repos/{owner}/{repo}/pulls/{pull_number}
3. github_api_read_only — repos/{owner}/{repo}/pulls/{pull_number}/files?per_page=100
💭 This PR looks like a fork sync with a massive, unusable diff spanning thousands of files — it's already closed, and the merge base is clearly outdated. The real intent behind it seems to be adding compatibility for "oh my pi," so I should dig into the actual commits by this author instead of relying on the diff.
4. github_api_read_only — repos/{owner}/{repo}/pulls/{pull_number}/commits?per_page=100
💭 This PR is actually a fork-sync with a huge diff dominated by an upstream squash, so I should isolate just the fork's genuine new work—the OMP provider bundling feature and its fixes—by diffing against the commit where the fork's tree merged with upstream, rather than the raw base comparison.
5. git_tools — 9e0ea47..3495ffa
💭 Reviewing 13k files fully isn't realistic for this closed fork PR, so I'll focus on the most relevant recent work instead—specifically the new OMP provider files and the pi provider service files. Let me pull the file list from the OMP provider commit to see what changed.
6. git_tools — ce6aa4b
💭 There's a new file, OmpDriver.ts, along with changes to PiAdapter.ts and PiProvider.ts. Given the PR's narrowed scope, I want to focus on the new Effect service code, so let me look at OmpDriver.ts first.
7. git_tools — ce6aa4b:apps/server/src/provider/Drivers/OmpDriver.ts
💭 This follows the ProviderDriver pattern used by other drivers, but I notice a potential convention violation: the error detail field copies
cause.messagedirectly to build the wrapper message, which goes against the guideline that the wrapper's message should be derived from stable structural attributes rather than the raw cause message. I want to check whether existing drivers like PiDriver or CodexDriver do the same thing—if it's inherited from a legacy pattern, this might be pre-existing rather than something I introduced. I'll look at the ProviderDriverError definition and compare with other drivers.
8. git_tools — Failed to build .* snapshot
9. git_tools — class ProviderDriverError
💭 This detail-copying pattern shows up in every driver across the repo, so OmpDriver is just following the existing convention rather than introducing something new. Since instructions say not to demand unrelated repo-wide cleanup and to treat this as legacy precedent, I'm weighing whether it still counts as a violation since it's technically a new file—but it matches all sibling implementations exactly. I want to check the fork-added pi provider service files too, looking for clearer convention violations in how they structure runtime layers, service parameters, and error handling patterns.
10. git_tools — ManagedRuntime.make|runPromiseExit|.runPromise
11. browse_code — apps/server/src/provider/pi/**
12. browse_code — apps/server/src/provider/pi/PiRpcClient.ts
💭 I'm noticing that PiRpcClientError stores an unstructured detail string as its only data instead of structured attributes with a derived message, and that detail sometimes just copies raw error text like the failed command output. The
clientErrorhelper is also flagged since it's just a thin wrapper that constructs the error from spread args, which the conventions explicitly discourage. And theoperationfield being a free-form string rather than a literal union is another point worth noting. FormakePiRpcClient(transport), I consider whether the injected transport counts as an implementation dependency owned by the service, but since it's a genuine port abstraction with a real test seam using a fake transport, I decide not to flag it. Now I want to check PiAdapter.ts, PiProvider.ts, bundledSkills.ts, and PreviewMidsceneToolkit for similar Layer/service issues, and look at whether PiRpcClientError should have a message getter since it currently lacks one — that seems like a real gap ifdetailis meant to surface at a caller-visible boundary. I should look for other error classes in the repo to see if there's an established convention of TaggedErrorClass with operation and detail but no message, to judge whether this is consistent or an outlier.
13. git_tools — detail: Schema.String
💭 I notice PiRpcClientError has an empty class body with no message getter, unlike the repo's other error classes that derive messages from their attributes — that's a real deviation from convention. The clientError helper is also just a pure error factory, which the convention flags. Given the size of the fork, I'll narrow my review to a handful of new Effect-related files like PiAdapter.ts, PiProvider.ts, bundledSkills.ts, and PreviewMidsceneToolkit.
14. browse_code — apps/server/src/**/{bundledSkills,PreviewMidscene*,Omp*,Pi*}*.ts
💭 That PiAdapter.ts file is only 211 bytes, which suggests it might be a compatibility re-export shim left behind — exactly the kind of leftover the instructions say to delete rather than keep. I want to check its contents to confirm.
15. browse_code — apps/server/src/provider/Services/PiAdapter.ts
16. browse_code — apps/server/src/bundledSkills.ts
💭 I'm looking at bundledSkills.ts and noticing that
registerBundledSkillsExtraRootself-providesNodePath.layerinternally instead of requiringPathfrom the environment, which hides the dependency from callers—this conflicts with the convention that service dependencies should be acquired from the environment rather than hidden in module internals. I'm also examining the function'sclientparameter, typed as a pick fromCodexInitializationClient, effectively a service instance passed explicitly. Since this client is a per-session runtime object created by the caller rather than an environment-owned service, passing it directly may actually be legitimate rather than a violation. I want to check howCodexProviderorCodexSessionRuntimecall into this to see if similar patterns exist upstream. I'm also looking at an error-handling block that catches errors and uses a schema predicate to recover one specific known error code before re-failing — this looks like the exact anti-pattern the convention warns against, whereEffect.catchTagstargeting the specific tagged error would be the correct approach instead of a schema-basedEffect.catch. I want to verify whether the error channel is fully handled here (it's not, since it re-fails), and confirm that the privateisCodexAppServerRequestErrorschema predicate isn't wrapped redundantly, which would be fine per convention. Next I plan to scan PiAdapter.ts, PiProvider.ts, and the PreviewMidsceneService/Runtime files for similar smells around ManagedRuntime and Layer.succeed usage, then broaden the search across the fork-added files for these patterns.
17. git_tools — ManagedRuntime.make|catchTag(|Layer.succeed(|runPromiseExit
💭 That grep was too broad given the scale, so I need to decide on findings and post them. One notable case is PreviewMidsceneService.ts using Effect.runPromiseExit inside runBrokerPromise -- this looks like a legitimate boundary since it's bridging Effect into midscene's Promise-based agent API, which expects a Promise-returning device interface. A named imperative adapter like this can be acceptable as long as it doesn't become a dependency of another Effect service, so I want to check that file's structure more closely since it's a fork-added, 17KB Effect service worth inspecting in scope.
18. browse_code — apps/server/src/mcp/PreviewMidsceneService.ts
💭 I'm noticing that PreviewMidsceneService.ts keeps a standalone PreviewMidsceneServiceShape interface alongside the Context.Service declaration, which goes against the convention of defining the service interface inline rather than retaining a separate Shape type. Some legacy files in the repo do have similar Shape types, but since this service is newly added in this PR's scope, the inline convention should apply here rather than following the older pattern. I'm also checking the use of Effect.runPromiseExit inside runBrokerPromise — it's bridging the Effect service into Midscene's Promise-based device interface for a third-party callback, which seems like a legitimate adapter pattern as long as it isn't consumed as a dependency by another Effect service. Now I want to see how makeWithEnvironment handles ServerSettings versus a default settings effect, so I'm looking at the layer and make definitions toward the end of the file to confirm whether ServerSettings is actually pulled from the environment.
19. git_tools — ^export const (make|layer)
20. browse_code — apps/server/src/mcp/preview-midscene/PreviewMidsceneRuntime.ts
💭 PreviewMidsceneRuntime.ts looks good with its inline interface and layered service setup, unlike PreviewMidsceneService.ts which still keeps the separate shape type. I'm also noticing
makereaches intoprocess.envdirectly rather than pulling from an environment service, which violates the convention against hiding dependencies in module globals — the repo already has a HostProcessEnvironment service meant for this. So I'm compiling my findings: the standalone interface that should be inlined, the raw process.env read that should use HostProcessEnvironment, an error class in PiRpcClient.ts with unstructured detail and no derived message, and something in bundledSkills.ts worth flagging too. Before finalizing though, I need to verify these files actually exist in the PR's changed scope rather than pre-existing upstream code — checking whether PreviewMidsceneService.ts, PiRpcClient.ts, and bundledSkills.ts were present at the merge base commit f61fa94, since the fork branch added several of these via da2de7e and 870e5eb. I should grep the merge base tree for these exact paths to confirm before flagging anything.
21. browse_code — apps/server/src/{bundledSkills.ts,mcp/PreviewMidsceneService.ts,provider/pi/PiRpcClient.ts,provider/Drivers/OmpDriver.ts}
22. browse_code — apps/server/src/mcp/PreviewMidscene*
💭 Since all four files are newly introduced, every line falls within the diff, so inline comments should work fine. I'm mapping out exact line ranges to reference, starting with the interface definition around lines 211-229 in PreviewMidsceneService.ts. For the process.env usage around lines 457-462, I'll flag the relevant line specifically. In PiRpcClient.ts I want two comments: one on the error class structure (lines 20-27) and one on the clientError factory helper (lines 51-57). For bundledSkills.ts, I'm splitting into two comments as well—one on the Effect.provide layer usage and another on the Effect.catch/Schema.is pattern spanning lines 66-73. I'm also weighing whether to flag the OmpDriver pattern where the message is derived from cause—it's a repo-wide convention across sibling drivers, so raising it risks demanding an unrelated consistency change rather than addressing something introduced by this PR specifically. I decide to skip the OmpDriver note since it's a deliberate shared shape across drivers, and flagging just this one instance would push for inconsistent treatment. I'm trimming my inline comments down from six to five, and double-checking exact line numbers and code shapes in bundledSkills.ts to make sure my references are accurate—confirming the resolveBundledSkillsRoot() call with Effect.provide(NodePath.layer) sits at line 60, and the Effect.catch block spans 66-73, while the service instance parameter at line 58 doesn't need comment since it's per-session. I'm also considering whether the review should default to a failing state given the number of legitimate findings. Now I'll draft a concise diff-style suggestion for the PiRpcClientError message and confirm the inline comment line numbers align with the diff's RIGHT-side positions for the new file, then compose and post the final review body.
23. modify_pr — ## Effect service conventions This branch adds several new Effect service modules (apps/server/src/mcp/PreviewMidsceneService.ts, apps/server/src/mcp/preview-midscene/PreviewMidsceneRuntime.ts, apps/server/src/provider/pi/*, apps/server/src/bundledSkills.ts, apps/server/src/provider/Drivers/OmpDriver.ts). PreviewMidsceneRuntime.ts and OmpDriver.ts follow the conventions; four issues below are worth fixing in the new service code. Note: the PR is 13.8k files against main because the fork branch carries a squashed upstream sync, so only the fork-introduced service modules were reviewed.
💭 The inline comments didn't attach, probably because the PR is closed or the diff is too large, but the review body went through fine. I'll report the findings in the check summary instead and won't retry, given the clear convention violations found — this is a failure state.
Agent Credits: 517 credits