Repository navigation
Effect Service Conventions: 1 issue found
Found 1 convention violation in the changed scope.
apps/server/src/textGeneration/PiTextGeneration.ts(line 142): recovers the knownSchemaErrortagged failure withEffect.catchTag. The conventions requireEffect.catchTags({ ... })for statically known tagged failures, including single-tag recovery. Every sibling text-generation implementation (CursorTextGeneration.ts,ClaudeTextGeneration.ts,GrokTextGeneration.ts,CodexTextGeneration.ts, etc.) already usescatchTagsfor this sameSchemaErrormapping, so this is both a convention violation and an inconsistency. An inline suggestion with the fix was posted.
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 reviewed: new/changed TypeScript for the Pi provider (drivers, adapters, RPC client, provider snapshot, text generation, contracts settings/runtime).
Items checked and found compliant:
- Effect module imports use subpath namespaces (
import * as Effect from "effect/Effect", etc.);@t3tools/contractscorrectly kept as named imports. Services/PiAdapter.tsfollows the established adapter-shape anchor pattern used byCursorAdapter.ts/OpenCodeAdapter.ts(not aContext.Service), so theFooShapeguidance does not apply.makePiAdapter/makePiTextGenerationacquire dependencies from the environment (yield* ServerConfig,yield* ChildProcessSpawner.ChildProcessSpawner,yield* FileSystem.FileSystem,yield* Crypto.Crypto); themakeTransportoverride is a legitimate test seam. NoManagedRuntime.make,.runPromise,Layer.succeed, or hidden runtimes introduced.- Errors use existing
Schema.TaggedErrorClasstypes with structured attributes and preserve realcause;PiTextGenerationcorrectly passes through existingTextGenerationErrorat the translation boundary and usesSchema.is(TextGenerationError). - The
detail: "Failed to build Pi snapshot: ...cause.message..."construction inPiDriver.tsmirrors the identical idiom in all eight other drivers (Codex, Claude, Cursor, Grok, OpenCode, Copilot, Kiro, OpenRouter); not flagged to avoid demanding a repository-wide change that would leave Pi inconsistent with its family.
Only concrete violation: Effect.catchTag in PiTextGeneration.ts.
🔍 Agent activity — 1 tool call
💭 Looking at the PR structure for the Pi provider implementation, I need to examine how it follows the Effect service conventions across the adapter interface, layer implementations, RPC client, and driver files. Checking the
PiAdapterShapeinterface—it extendsProviderAdapterShapewhich is an existing pattern used by other adapters like Cursor. The convention warns against standaloneFooShapeinterfaces, but this follows the established codebase pattern where all adapters use a Shape convention, so I need to determine if this is a violation specific to this PR or just consistent with existing code. Looking at the imports in the driver files, they're using namespaced imports from effect modules likeDeferred,Effect,Crypto, andDuration, which aligns with the convention. For error handling, the PR constructs errors likeTextGenerationErrorwith anoperationdiscriminator and adetailfield that contains descriptive strings rather than copying the cause message directly, which follows the established pattern. Looking at dependency acquisition, bothmakePiAdapterandmakePiTextGenerationproperly yield from the environment to get their required services likeServerConfig,Crypto,ChildProcessSpawner, andFileSystem. Theoptions?.makeTransportparameter is being examined next. I'm seeing a violation of the error handling convention here — thedetailfield is copyingcause.messagedirectly into the string, which violates the rule against embedding the cause's message into structural fields. The wrapper's message should derive only from stable structural attributes, not from the cause itself. Now I need to check if this pattern is consistent with how other drivers in the codebase constructProviderDriverError, since the convention only flags violations introduced or retained in the PR's changed scope. Let me look at existing drivers like OpenCodeDriver to see if this is an established pattern or something new. I need to correct the function call. I need to adjust the URL parameter formatting to use proper JSON structure instead of the nested format I tried before. Looking at how the PiDriver handles errors, it's wrapping the cause message into the detail field when building snapshots fail, following the established pattern for error construction. But the convention explicitly warns against this—detail shouldn't just copy cause.message, and the wrapper's message should derive only from stable structural attributes, not from the underlying cause. The cause itself should be preserved separately. This looks like it might be an anti-pattern that's already in place, so I should check how other drivers like OpenCodeDriver or ClaudeDriver handle this to see if it's a widespread issue or a newly introduced violation. The PiDriver follows the same pattern as all the other drivers in the codebase, so flagging this would be asking for repository-wide cleanup rather than addressing a concrete issue in the pull request's scope. Now I'm examining the actual service definitions in PiAdapter.ts and comparing the Layers pattern against how other adapters like Cursor handle their shapes to see if there are any genuine convention violations.PiAdapter.tsfollows theCursorAdapterShapepattern correctly as a Services adapter, not a Context.Service, which aligns with the codebase conventions and theFooShapenaming pattern for driver bundle anchors. Now I'm looking at the Effect service conventions in the new code, particularly around driver and adapter patterns. Since this PR mirrors the existing Cursor/OpenCode driver, adapter, and provider structure, most conventions are already consistent. I'm checking the error handling inPiRpcClientwhich usesEffect.Effect<void>withEffect.ignore— that's appropriate. ThemakePiRpcTransportdoesn't declare errors, which is fine.PiProvider.tsusesEffect.fnandEffect.catchCausecorrectly. Looking atPiTextGeneration, the error handling translates boundaries properly by passing through existingTextGenerationErrorinstances while wrapping unknown errors into the domain error type — this follows the right pattern for structured error handling. But I'm spotting a genuine convention violation: the code usesEffect.catchTag("SchemaError", ...)instead of the preferredEffect.catchTags({ SchemaError: ... })pattern. The convention explicitly states to usecatchTagswith an object for statically known tagged failures, even when handling just one tag, and to avoidcatchTagentirely. I need to check whether other TextGeneration implementations in the codebase follow the same pattern withcatchTagto determine if this is actually a violation or just consistent with the existing convention. I'm noticing the new implementation uses a different error handling pattern than all the other TextGeneration variants—it's callingEffect.catchTagfor individual errors instead ofEffect.catchTagswith a grouped object, which breaks the established convention. I should check how the sibling implementations handle this to provide the right fix. I'm spotting an inconsistency in error handling patterns between the two files—CursorTextGeneration.tsusesEffect.catchTagswith multiple error handlers whilePiTextGeneration.tsswitches toEffect.catchTagfor a single error, which breaks the established convention in the codebase. Looking at where this happens in the new file with the schema decoding logic. Line 142 is usingEffect.catchTag, which violates the established convention. Looking at theTextGenerationShapepattern, it's actually consistent with how the sibling implementations handle it—they all reference it the same way throughTextGenerationShape["generateCommitMessage"], so that's not an issue. Let me scan through the new provider files to see if there are any othercatchTagorcatchIfviolations I should flag. The only concrete violation I've found is theEffect.catchTagin PiTextGeneration.ts line 142 — it's a genuine convention breach that was introduced in the changed code and stands out as inconsistent with the rest of the codebase. I'm preparing an inline suggestion to replace it withEffect.catchTagsusing the proper object syntax, which will align it with the established pattern across all sibling implementations. Writing the catchTags replacement...
1. modify_pr — Effect Service Conventions: one issue found. PiTextGeneration.ts recovers a known tagged failure with Effect.catchTag, which the conventions disallow (and which diverges from every sibling text-generation implementation that uses Effect.catchTags).
💭 I need to generate the final JSON result for the check-run, marking it as a failure and including the appropriate title and summary.
Agent Credits: 208 credits