Repository navigation
Effect Service Conventions: 5 issues found
Five convention violations were found in the changed provider probe code; inline comments were posted.
apps/server/src/provider/providerProbeTimeouts.ts(L15-33): platform is read from a module-levelprocess.platformglobal at import time, hiding a runtime dependency the repo already models in the Effect environment (HostProcessPlatform/isHostWindowsinpackages/shared/src/hostProcess.ts). This also forces platform branching in the new test and theTestClock.adjust("46 seconds")workaround inProviderRegistry.test.ts.apps/server/src/provider/providerProbeTimeouts.ts(L42-71):resolveProviderProbeCwddefaults toprocess.env, falls back toprocess.cwd(), and uses blockingNodeFs.statSync, bypassingHostProcessEnvironment/HostProcessWorkingDirectoryand theFileSystem.FileSystemservice already required by the calling probes.apps/server/src/provider/providerSnapshot.ts(L26-29):DEFAULT_TIMEOUT_MS(marked@deprecated) andAUTH_PROBE_TIMEOUT_MSare left as compatibility re-export shims; each has a single consumer (ClaudeProvider.ts,CodexProvider.ts) that could be updated so the aliases can be deleted.apps/server/src/provider/providerSnapshot.ts(L85-87): production probe behavior changes (stdin closed after spawn, resolved spawn cwd) are not covered by a focused test; the added tests only exercise the pure constants and helper.apps/server/src/provider/Layers/GrokProvider.ts(L49):VERSION_PROBE_TIMEOUT_MSis a pass-through alias of the imported constant.
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: the changed TypeScript under apps/server/src/provider/ (providerProbeTimeouts.ts, providerProbeTimeouts.test.ts, providerSnapshot.ts, Layers/CursorProvider.ts, Layers/GrokProvider.ts, Layers/CodexProvider.ts, Layers/CursorProvider.test.ts, Layers/ProviderRegistry.test.ts). docs/windows-provider-timeouts.md is outside the configured include patterns and was used only as context.
Checked and found compliant: namespace subpath imports (effect/Effect, effect/Stream, etc.); named imports from the new pure constants/helper module (explicitly allowed); no new Context.Service, make, or layer declarations, so service-definition ordering and naming rules do not apply; no new error classes, predicates, or catchTag/catchIf usage; the Stream.run(Stream.empty, child.stdin) stdin-close pattern matches existing repo usage in processRunner.ts and GitVcsDriverCore.ts; no ManagedRuntime.make, runPromise, or runPromiseExit introduced; existing comments and invariants were preserved.
Supporting evidence for the dependency-acquisition findings: packages/shared/src/hostProcess.ts defines HostProcessPlatform, HostProcessEnvironment, HostProcessWorkingDirectory, and isHostWindows as Context.Reference values, and apps/server/src/processRunner.ts (isWindowsCommandNotFound) plus packages/shared/src/shell.ts already acquire platform/env via yield*, making the environment-based approach the established pattern here.
🔍 Agent activity — 1 tool call
💭 I'm examining the changed files to see I'm checking the conventions around dependency management in this codebase, specifically whether
resolveProviderProbeCwdis properly handling its dependencies or hiding them in module globals. I need to see if the repo has an Effect-idiomatic pattern for reading environment variables and filesystem operations. I'm checking the import conventions and file structure against the project standards. The imports look acceptable with their namespace subpaths and named constants, but I need to verify that old service files are being properly removed rather than kept as compatibility shims. Looking at the specific cases:DEFAULT_TIMEOUT_MSis marked deprecated but still re-exported, and there are alias constants likeAUTH_PROBE_TIMEOUT_MSandVERSION_PROBE_TIMEOUT_MSthat mirror the new provider-namespaced versions. While the convention technically targets service/layer files, the spirit of "mechanically update every consumer" suggests these compatibility shims should be eliminated entirely — I should count how many places still depend onDEFAULT_TIMEOUT_MSto assess if this is a real violation. The new test file for the pure helper function is acceptable since it's testing actual behavior changes in the backend, not just proving the refactor worked. The bigger issue is thatresolveProviderProbeCwdis doing synchronous filesystem operations and accessingprocess.env/process.platformdirectly inside Effect service code, bypassing theFileSystem.FileSystemservice that's already available in the environment. This violates the principle of not hiding runtime dependencies in imperative code within supposedly pure Effect layers — the probe cwd resolution is performing blocking I/O that should be traced through the Effect environment. I'm noticing thatDEFAULT_TIMEOUT_MSstill has one consumer in ClaudeProvider, and marking it as deprecated while leaving that consumer unchanged violates the migration conventions—the proper approach would be to update ClaudeProvider to import from the new location instead of using a compatibility shim. There's a similar pattern withVERSION_PROBE_TIMEOUT_MSin GrokProvider, which is just a local alias. More critically, the PR modifiesspawnAndCollectto close stdin on all provider probes, which is a behavioral change in production code, but the tests only cover the pure helper functions rather than the actual integration points where this change takes effect. The test adjusts the clock by 46 seconds to make assertions pass across platforms, which still validates the timeout fires correctly. There's also a platform-dependent timeout constant that changes non-Windows AUTH_PROBE_TIMEOUT_MS from 10s to 15s, and the test becomes somewhat tautological on non-Windows systems since it just asserts the constants meet minimum thresholds rather than testing the actual behavior. I'm noticing a significant issue: the codebase already has EffectContext.Referenceservices set up for platform, environment, and working directory details, but the new module is hardcodingprocess.platformat load time and directly accessingprocess.envandprocess.cwd()instead of pulling these from the Effect environment. This violates the established pattern of not hiding dependencies in module-level globals and instead acquiring them through the environment withyield*. Looking at the Effect service conventions from the config, the key rule is that dependencies shouldn't be hidden in module globals—they need to be acquired from the environment usingyield* Foo.Fooat runtime. SinceproviderProbeTimeouts.tsis used by Effect service code like CursorProvider, GrokProvider, and CodexProvider, and it reads from platform/env, I need to check if it's properly following this pattern. The issue is thatisWindowsis evaluated at module scope when the file is imported, which freezes the platform behavior and bypasses the Effect environment entirely. This breaks testability since tests can't control the platform state. The fix would be to export functions that useEffect.mapwith the existingHostProcessPlatformreference—something like makingproviderVersionProbeTimeoutMsreturn an Effect that maps over the platform context, which aligns with how the repo already handles platform dependencies elsewhere. There's a similar pattern inresolveProviderProbeCwdwhere it directly callsNodeFs.statSyncand accessesprocess.envas defaults, even though the calling code already hasFileSystem.FileSystemandHostProcessEnvironmentavailable in the environment. I could flag both issues together in a single comment on the file, or split them into separate inline notes. I also noticeDEFAULT_TIMEOUT_MSis a deprecated compatibility alias still sitting inproviderSnapshot.ts, but its consumer inClaudeProvider.tshasn't been updated to use the new constant—that's a cleanup task left incomplete. There's a behavior change here around closing stdin in the spawn functions and using cwd for spawning, but the test coverage only validates the constants and helpers, not the actual behavioral shift. The existing test suites with mock spawners would be the right place to add focused tests for these changes. The stdin behavior in probes is isolated to those tests, so that's not a broader concern. I'm also noticing thatEffect.ignoreswallows errors without clear conventions around that, but that's not explicitly specified so I'll skip it. Looking at the ProviderRegistry test, theTestClock.adjustcall depends on a platform-specific timeout constant that isn't in the Effect environment, which means the test can't injectHostProcessPlatformto make it deterministic — this actually reinforces the first finding about module-global platform reads. I should note this either in a comment on that finding or directly on the test line, and I need to verify the actual line numbers in the head files for my inline comments. I'm identifying a key issue where the platform is being read at the module level instead of going through HostProcessPlatform, and I need to add a comment to providerProbeTimeouts.ts suggesting we derive the platform value using the HostProcessPlatform utilities from the shared hostProcess module so that callers can properly yield within Effect.gen and tests can inject different platform values—this aligns with the test setup that now advances time by 46 seconds to cover both Windows and non-Windows scenarios. I'm also spotting a second problem in the same file whereresolveProviderProbeCwdis doing blocking filesystem operations and reading process environment directly instead of using the FileSystem, Path, HostProcessEnvironment, and HostProcessWorkingDirectory that are already available in the environment, so I'll suggest creating an Effect-returning helper to replace those direct calls. There's a deprecated alias in providerSnapshot.ts that should be removed after updating its single consumer in ClaudeProvider.ts, and a similar local alias pattern in GrokProvider.ts that can be cleaned up by using the imported constant directly instead of creating a redundant binding. I should also add a comment requesting focused tests for the stdin close behavior change, since this is a production behavior modification across all providers and the current test coverage only validates the constant values, not the actual behavioral change. The pattern checks out, so I'll move forward. UsingEffect.ignorefor a best-effort stdin close is fine since the existing codebase already maps errors to tagged variants. Now I'm drafting the comments—I'll include notes on platform globals, the cwd environment and filesystem setup, the DEFAULT_TIMEOUT_MS shim, and the Grok alias. Actually, I should be careful not to overload with comments. The PR does change backend behavior around stdin closing, cwd resolution, and timeouts, but the test coverage is only pure-unit tests. I need to add a focused test comment on the snapshot file to flag that gap. I'll keep it to four comments total: platform globals, cwd env/fs, DEFAULT_TIMEOUT_MS shim, and test coverage for the stdin and cwd behavior changes. Platform is read from a module global at import time, which hides a runtime dependency that the repo already models in the Effect environment throughHostProcessPlatformandisHostWindows. Since all consumers are insideEffect.gen, I should expose these as Effect values so they can be yielded at the probe sites, which would also eliminate the platform branching in tests and the TestClock workaround. The second comment covers howresolveProviderProbeCwddefaults toprocess.envand falls back to direct filesystem calls, bypassing the Effect environment's abstraction layer. I need to finalize the comment about DEFAULT_TIMEOUT_MS as a deprecated shim and note how AUTH_PROBE_TIMEOUT_MS aliases to it. For the review, I'm using the right-side line numbers from the diff—the new providerProbeTimeouts.ts file spans lines 1-80, with Comment A positioned around line 15-18.
1. modify_pr — Reviewed against the Effect service conventions. The new probe-timeout module reads platform/env/cwd/fs through process globals instead of the Effect environment the repo already models (HostProcessPlatform, HostProcessEnvironment, HostProcessWorkingDirectory, FileSystem.FileSystem), and a couple of compatibility aliases were introduced instead of updating consumers. Details inline.
Agent Credits: 120 credits