Repository navigation
Effect Service Conventions: 1 issue found
apps/desktop/src/shell/DesktopShellEnvironment.test.ts:377 — assert.equal(env.PATH, "${mockDir}") cannot hold. When skipProfile is taken, installWindowsEnvironment assigns config.env.PATH = staticPaths.value, and staticPaths merges knownWindowsCliDirs(config.env) (the four USERPROFILE-derived directories seeded by this test) ahead of the original PATH entry. Asserting that the quoted entry is still present (includes) covers the intent without depending on the merge order.
No other convention violations were found in the changed scope.
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.
Conventions verified as satisfied
- Imports: both touched files use namespace subpath imports (
import * as FileSystem from "effect/FileSystem"), matching the rest of the repository; no consolidated named imports from"effect". - Dependency acquisition:
installWindowsEnvironmentdeclaresFileSystem.FileSystemin itsEffect.fn.Returnrequirements and acquires it withyield* FileSystem.FileSystem;makestill resolves the service from the environment andlayerremains the canonical export. No module globals,ManagedRuntime.make, orrunPromisewere introduced. - Test seams: providing a stub
FileSystemthroughEffect.provideServiceinrunShellEnvironmentis a legitimate test-only injection; production construction is unchanged. - Error handling:
Effect.catchIf((err) => err.reason._tag === "NotFound", ...)is a genuine structural predicate on the underlying platform error code and matches existing usage (T3ProjectFileLoader.ts,DesktopBackendConfiguration.ts). The surroundingEffect.orElseSucceedintentionally collapses the whole channel to a boolean, consistent with theexistsprobe at line 559 of the same file. - Test error construction: stubs now use the typed
PlatformError.systemError({ _tag: "NotFound", module, method, pathOrDescriptor })constructor, matching repository-wide usage. - Change discipline: the comment documenting why the two PowerShell probes run concurrently was retained, and the new tests are focused on the behavior change rather than restating the refactor.
Behavioral trace of the four new tests
- quotes and no fnm —
nodeFound = true,profileMentionsFnm = false, probes skipped;PATHassertion is wrong (reported). - profile references fnm —
profileMentionsFnm = true, both probes run,FNM_DIRhydrated; assertions hold. - profile exists without fnm — probes skipped; assertion holds.
- node in knownWindowsCliDirs —
LOCALAPPDATAexpands to...\Programs\nodejs, probes skipped,PATHcontainsnodejs; assertions hold.
🔍 Agent activity — 1 tool call
💭 Checking the current state of the PR at commit 0249c45 to see what issues were flagged in previous runs and reviewing the files now. Looking at the
catchIfusage at line 417-420, it's checking for a structural predicate on the underlying error — specificallyerr.reason._tag === "NotFound"— which aligns with the convention for this pattern. Now moving on to review the test file. The test count is now at 354. I'm checking the order of Effect operations — specifically whetherprovideServicefor FileSystem followed byprovidefor NodeServices causes conflicts. The key insight is that once FileSystem is provided throughprovideService, that requirement is satisfied, so the subsequentprovidecall won't override it but rather supplies the remaining dependencies. Now I'm verifying the mock FileSystem cast and thePlatformError.systemErrorconstructor — whether it accepts the right parameters and if the error structure has the expectedreason._tagproperty in Effect v4. The error handling approach is consistent with the repo's conventions—usingcatchIffor structural predicates like checking error tags, thenorElseSucceedto intentionally collapse the error channel into a success case, which aligns with existing patterns in the file. For the test setup, themockFscast withas unknown as FileSystem.FileSystemis a pragmatic choice for a test double, though the repo typically spreads the real service and overrides specific methods. The current approach works fine for focused behavior tests. The service layering withprovideServicefollowed byprovide(NodeServices.layer)needs careful ordering—I should verify that FileSystem gets properly resolved before downstream dependencies try to use it. I need to check the rest of the file to see how the layer and FileSystem requirement are defined in the make section. Looking at the Effect conventions in the code, the production setup properly injects FileSystem through the environment inmake. For the diff itself, I'm checking for convention violations: thecatchIfwith a structural predicate on the error tag is allowed,orElseSucceedwrapping the generator is legitimate, and I'm starting to examine the test mock setup. The test uses a partial FileSystem stub cast withas unknown as, which isn't forbidden by the conventions. The key question is whether providing FileSystem outside the layer still reaches it — and yes, sinceEffect.provide(DesktopShellEnvironment.layer)leaves FileSystem as an unmet requirement in the outer context, a laterprovideServicecall satisfies it. But I need to check the ordering: whenprovideService(FileSystem, fs)is applied beforeEffect.provide(NodeServices.layer), and NodeServices.layer also provides FileSystem, I'm wondering how Effect merges these contexts... Actually, in Effect v4,provideServicewraps the effect and adds the service at that point, so the inner provideService takes precedence when the outer layer is applied. That's correct. Now I'm checking whether the tests actually pass logically — specifically whether the mock behavior aligns with what the code expects. The first test sets PATH with quotes and USERPROFILE, merges known directories with PATH, then iterates through them stripping quotes. Theexistsmock returns true for any path containing "node.exe", so the first directory should find it. For the profile check, readFile fails with NotFound, which gets caught and returns false, so skipProfile becomes true and config.env.PATH gets set to the merged static paths. But here's the issue: mergePaths combines the known Windows CLI directories with the original PATH value, so the final PATH would include all those directories plus the original quoted path. The test then asserts that env.PATH equals just the quoted temp path, which would fail because mergePaths produces a longer concatenated string. I need to check what mergePaths actually does — whether it deduplicates or normalizes paths. Also, config.env is actually process.env in the implementation, so the test's use of withProcessEn... I'm seeing that the test is checking whether the PATH environment variable gets set correctly after filtering out known Windows CLI directories, but the assertion is expecting only the mock temp directory to remain, which doesn't match what's actually being constructed. The test itself appears to be flawed. Looking at test 4, I'm checking how the PATH gets built when LOCALAPPDATA is set to the mock temp directory, which should contribute additional Node.js and Volta paths to the environment. I'm realizing the issue might be with how the layer is constructed —makereadsprocess.envwhen the layer is built, butwithProcessEnvsetsprocess.envbefore the effect runs, so there's a timing mismatch between when the environment is captured and when it's actually used. Looking at the other conventions:Effect.allwith concurrency options is fine, there's some minor duplication in howstaticPathsgets computed, and the profile file reading with timeout handling looks correct. I should check whetherEffect.catchIfon the file system read is the right approach here. The mock setup usingas unknown asfollows the repo's testing idiom, so that's not a violation. AndcheckProfileMentionsFnmcorrectly returns true when USERPROFILE is missing. The real issue I'm circling back to is whether that first test assertion aligns with the change discipline requirement — if backend behavior is changing, the test needs to be focused and specific about what's actually being validated. Let me trace through the actual execution:mergePathswith the Windows config, APPDATA and LOCALAPPDATA undefined, but USERPROFILE set to "C:\Users\test" produces 4 directory entries joined by semicolon. AftertrimNonEmpty, that becomes the first element of staticPaths. So the assertion expectingenv.PATH === '"C:\\mock\\temp"'would definitely fail because the path now includes those Windows directories. That's a concrete problem with the test. I should suggest a fix that checks whether the quoted mock directory is actually present in the PATH instead of expecting an exact match. For the second test around line 402-407, I need to verify the profile probe command includes the "-NoProfile" flag when loadProfile is false, and that both test cases correctly identify the command type as StandardCommand. Checking whethercommands.length === 2holds in test 2 — the readWindowsEnvironment function loops through shell candidates until it gets non-empty output, and since the handler returns envOutput for any command, it breaks after the first one, so two calls to readWindowsEnvironment means two commands total. That checks out. Test 1's assertion thatcommands.length === 0also holds. Now I need to verify the Effect.prov... Writing effect provider chain... SoFileSystem.FileSystemis the established pattern in this codebase for typing. Looking at the broader context, other modules do passfileSystem: FileSystem.FileSystemas parameters to helper functions, which is an accepted practice — but the new diff doesn't introduce any such parameters in production code. The real issue that stands out is the failing assertion in the first test, though I'm wondering if that actually falls under the scope of Effect Service Conventions or if it's something else entirely. The failing assertion does seem worth flagging though. The instructions are clear about reporting concrete violations in the changed scope, and a test with an incorrect assertion arguably isn't a valid focused test if the backend behavior has changed. That's distinct from the earlier comments about types and imports. I should also consider whether theas unknown ascast for the stub is worth mentioning — it's the accepted way to create partial stubs in this repo, unlike theas anypatterns flagged in previous runs, so that's probably fine to leave alone. The test file is definitely in scope for the check, and I can see the assertion on line 377 is newly added. The production behavior around the skip path and FNM_DIR looks intentional by design, so no concern there. I'll post a single inline comment on that assertion line and mark it as a failure.
1. modify_pr — One finding: the new Windows fast-path test asserts PATH is left untouched, but the fast path rewrites it with the merged static paths. Everything else (namespace subpath imports, FileSystem.FileSystem acquired from the environment in make, the structural reason._tag catchIf, and the typed PlatformError.systemError stubs) now matches the repository's Effect service conventions.
Agent Credits: 125 credits