Repository navigation
Effect Service Conventions: 1 issue found
apps/server/src/environment/ServerEnvironment.ts(lines 150-154): the post-write invariant failure manufacturesnew Error(...)solely to populate the requiredcause: Schema.Defect()field, even though no underlying failure exists; suggested makingcauseoptional and encoding the distinction structurally (e.g. an"initialize"operation literal).
No other convention violations found in the changed scope: the new ServerEnvironmentIdentity tag, makeIdentity/identityLayer, and consumers (SessionStore, EnvironmentAuthPolicy, EnvironmentAuth, server.ts, cli/connect.ts) acquire dependencies from the Effect environment, and the Layer.succeed/Layer.mock occurrences are test seams only. The doc-block placement flagged in the prior run is now attached to layer.
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 reviewed: apps/server/src/environment/ServerEnvironment.ts, apps/server/src/auth/{utils.ts,SessionStore.ts,EnvironmentAuth.ts,EnvironmentAuthPolicy.ts,http.ts}, apps/server/src/server.ts, apps/server/src/cli/connect.ts, plus the touched test files.
Checks performed:
- Namespace vs named imports in touched service modules (all Effect modules imported from subpaths as namespaces; local service modules imported as namespaces).
- Service definition order, inline interface in
Context.Service, exportedmake/layer(second service in the module usesmakeIdentity/identityLayer, which is a reasonable disambiguation and not a convention violation). - Dependency acquisition: no
ManagedRuntime.make,runPromise, orrunPromiseExitintroduced; no service instances passed as constructor parameters in production code.Layer.succeed/Layer.mockoccurrences are confined to tests. - Layer composition in
server.ts:ServerEnvironmentLayerLiveis a single shared layer value referenced by bothAuthLayerLiveand the runtime core, so memoization yields one identity instance rather than duplicated resources. - Error modeling:
ServerEnvironmentIdPersistenceErrorkeeps a multi-valueoperationdiscriminator with a message derived from structural attributes; the only issue is the syntheticcausenoted above. - Behavior changes (cookie naming, legacy-cookie migration, concurrent environment-id initialization) are covered by focused tests in
utils.test.ts,SessionStore.test.ts,server.test.ts, andServerEnvironment.test.ts. - No new lint/type-checker suppression directives were introduced.
🔍 Agent activity — 11 tool calls
💭 I want to check the changed files for naming conventions—specifically how ServerEnvironment.ts structures its two services, ServerEnvironment and ServerEnvironmentIdentity, since the naming pattern with makeIdentity/identityLayer might be acceptable given there are two services sharing one module. I recall a prior review flagged the doc block placement, so let me look at the actual files now.
1. browse_code — apps/server/src/environment/ServerEnvironment.ts
2. browse_code — apps/server/src/auth/utils.ts
💭 I'm checking whether the previously flagged doc block placement issue was fixed—it looks like it was, since the doc comment now sits correctly above the layer declaration. I'm also verifying that EnvironmentAuth's runtimeLayer properly merges the identity layer, and moving on to check how tests set up the server environment. Looking further, I confirm the test seams and mock layers used across SessionStore.test.ts and server.test.ts look fine, and EnvironmentAuthPolicy correctly acquires the identity service from the environment. I'm also checking whether the named import of HostProcessEnvironment in bin.test.ts should instead be a namespace import per convention—it's allowed either way since the rule uses "may," and existing code already follows the named-import pattern, so this seems acceptable. Now I'm looking at whether the identity module properly exports a
makefunction since it owns construction of two services, butmakeIdentityisn't currently exported. I'm weighing whether the privatemakeIdentityalongside an exportedidentityLayerviolates the convention of keeping a service's tag, construction, and layer together—it's borderline since the module handles two closely related services, and the guideline's intent is against forcing unnecessary exports rather than requiring every internal function be public, so I'll treat this as ambiguous rather than a clear violation. Now I'm checking how errors are caught in makeIdentity, specifically whether the tagged failure matching follows the convention for handling statically known error variants. Since this construction can legitimately arise without an underlying failure, cause should be optional here rather than requiring a manufactured Error — that's a real violation worth flagging. There's also a minor naming quibble: reusing "read failed" phrasing for a case that's really "missing after init," though that's a smaller nitpick. Continuing through the remaining files, I'm checking exported helpers, cookie handling, session store setup, and layering in server.ts — all look consistent with existing patterns. I'm now scanning the diff for any suppressions like ts-expect-error or eslint-disable, and spot anas nevercast in the auth test file. I want to see if that cast style matches other usages in the same test file, whether the mapError pattern with Effect.fn holds up, and whether the persistEnvironmentId error type still needs the manufactured Error or can be simplified — plus double-checking the failure-path tests and the test layer setup in bin.test.ts.
3. git_tools — as never
4. git_tools — Schema.optional(Schema.Defect
💭 Making
causeoptional seems idiomatic here, so manufacturing anew Error(...)just to satisfy a required cause field is a real violation of the guidance against fabricating errors. I also notice the missing-after-init case reuses "read" as the operation even though the message says "read failed" — not a huge issue, but worth flagging alongside the suggestion to make cause optional. Since the fix spans two places — the schema field and the construction site — I'm weighing whether to give a diff or just describe it in prose, since guidance discourages multi-hunk diffs in a single comment. I'll settle on providing a diff for the construction site and describing the schema change separately in prose, since combining both into one diff could be misleading. Now I want to double check other files for similar violations — SessionStore.ts, http.ts, EnvironmentAuth.ts's selectRequestCredential — plus a few smaller details like test layer usage and error channel typing, which all look fine on inspection. I'll take one more pass through the http.ts diff and the EnvironmentAuth.ts section near line 630 to be thorough.
5. browse_code — apps/server/src/auth/EnvironmentAuth.ts
6. browse_code — apps/server/src/auth/http.ts
💭 These catchIf patterns look pre-existing and consistent with conventions, so that's not a new issue. Confirming the only real finding is the manufactured Error's doc block, and checking whether the winner === null branch existed before this commit or was newly introduced. Reconsidering whether this flag is fair: the instructions say not to manufacture an Error solely to populate a cause field, and this code does exactly that — synthesizing an Error just to satisfy the required cause while the actual explanatory message gets discarded since it's never surfaced through the wrapper's own message getter. It also misuses
operation: "read"for a failure that isn't actually a read, which compounds the mismatch. I'll keep the comment focused on the synthetic cause and suggest making cause optional. Now I want to verify the connect.ts changes — checking whether removing theServerEnvironment.layercomposed withServerSecretStore.layerfrom the provided layers still satisfies the identity layer's requirements elsewhere, since this is something that would only surface as a compile error if unsatisfied.
7. browse_code — apps/server/src/cli/connect.ts
💭 I'm now checking whether the environment identity resource gets composed twice across different runtime layers — since EnvironmentAuth.runtimeLayer already merges in the identity layer, I want to verify server.ts isn't redundantly providing ServerEnvironmentLayerLive as a separate dependency to AuthLayerLive. Layer memoization by reference within a single build should dedupe this as long as it's the same layer instance in one composition graph, so this likely isn't a convention violation. I need to look at server.ts directly to confirm there isn't accidental double-instantiation.
8. browse_code — apps/server/src/server.ts
💭 I'm checking whether AuthLayerLive's layer provisioning creates duplicate instances since the same layer is referenced twice — but Effect memoizes by reference within a single build, so that's fine. My main finding remains the manufactured Error used as cause, though I want to double-check one more detail. I should look at SessionStore.ts's make function, and also check whether EnvironmentAuthPolicy.ts pulls environmentId from serverEnvironment inside a function scope where that context is actually available.
9. browse_code — apps/server/src/auth/EnvironmentAuthPolicy.ts
10. browse_code — apps/server/src/auth/SessionStore.ts
💭 I found one issue, a modest convention violation. Since the check defaults to failure and there's explicit guidance to fail on clear convention violations, I'll post the finding as an inline comment and mark the check as failed rather than defaulting to success. Given this is introduced in the diff and matches the listed rule directly, I'll flag it. I'll target lines 150-154 in ServerEnvironment.ts and draft a comment noting the synthetic Error only exists to satisfy the required cause field, suggesting making cause optional and dropping the manufactured error while preserving the explanatory context elsewhere.
11. modify_pr — </antml new_field="">
Agent Credits: 15 credits
Token usage: 4 uncached input · 130,006 cache-read input · 1,415 cache-write input · 2,381 output
Agent Credits may also include non-token charges from external tools such as web research.