Repository navigation
Effect Service Conventions: 1 issue found
1 finding
apps/desktop/src/preview/Manager.ts(startRecording, ~L3118-3140): the new recording-source size validation is a pure validation failure but is modeled by throwing a syntheticErrorinsideattempt, so callers only ever see a genericPreviewOperationErrorwhose real reason lives in a manufacturedcause. Convention requires aSchema.TaggedErrorClasswith structured attributes and amessagederived from them; validation errors created without an underlying failure should not fabricate a cause.
No other convention violations were found: Effect modules and local service modules are imported as namespaces, the new IPC handler uses DesktopIpc.makeIpcMethod with Effect.fn and acquires PreviewManager.PreviewManager from the environment, no new ManagedRuntime.make, runPromise, Layer.succeed, or service-instance parameters were introduced, and the widened startRecording signature is reflected in the inline Context.Service interface and the contracts schema.
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 (in scope)
apps/desktop/src/ipc/methods/preview.tsapps/desktop/src/preview/Manager.tsapps/desktop/src/preview/Manager.test.tsapps/web/src/browser/browserRecording.tsapps/web/src/browser/browserRecording.test.tspackages/contracts/src/ipc.ts
Checks performed
- Import style: Effect subpath namespace imports and named imports from
@t3tools/contracts(type-only forDesktopPreviewRecordingSource) both match convention. - Service definition:
PreviewManagerkeeps its inlineContext.Serviceinterface; the widenedstartRecordingreturn type is propagated to the interface and toDesktopPreviewRecordingSourceSchema, with no reintroducedFooShapetype. - Dependency acquisition/runtime boundaries: searched the touched files and affected call sites for
ManagedRuntime.make,runPromise/runPromiseExit,Layer.succeed, andFoo["Service"]parameters β none newly introduced; the IPC handler resolves the service from the environment. - Errors: existing
PreviewOperationError/BrowserRecordingOperationErrormodels were reused;BrowserRecordingOperationError.operationremains a multi-value discriminator, so the new"cleanup"/"capture-media-stream"literals do not create a redundant singleton discriminator. The one flagged item is the syntheticErrorused as a validation failure inManager.startRecording. - Related note (not flagged, outside this check's convention set): the debugger
Page.screencastFramepath inManager.tsstill delivers recording frames viarecordingFrameListenersRef, while its dedicated test ("emits debugger screencast frames only while recording is active") was deleted in this PR. Worth confirming that path is still intentionally covered.
π Agent activity β 15 tool calls
1. browse_code β apps/desktop/src/ipc/methods/preview.ts
2. git_tools β apps/desktop/src/preview/Manager.ts e4f7b14..7c0541f
π I'm checking the code against Effect service conventions, looking at how errors are used β like using a "main window closed" error for a missing hostWebContents, and whether throwing a generic Error inside
attemptfor missing dimensions properly gets wrapped into a structured error with operation and tabId context. The convention says domain validation errors don't need a manufactured cause, so throwing a synthetic Error just to populate a cause may be flagged. I'm also checking that Effect.onError handling looks fine, that imports from contracts follow the named-import rule, and noting that browserRecording.ts on the web side isn't actually an Effect service since it's plain promise-based code. Now I'm checking whether collapsing "stop-media-recorder" and stream stopping into a single "cleanup" operation counts as a caller-visible message change worth preserving, though it seems like an intended part of the refactor rather than a violation. I want to look at the attempt/attemptPromise helpers in Manager.ts to judge how errors are modeled there.
3. git_tools β const attempt|const attemptPromise|PreviewOperationFailedError|class Preview.*Error
π I'm noticing this pattern manufactures an Error just to populate a cause, when it's really a validation failure β that seems to violate the convention against creating synthetic errors for that purpose, since pure validation errors shouldn't need a fabricated cause at all. Let me check whether Manager.ts has any existing precedent for throwing a synthetic Error inside
attemptbefore deciding how to flag this.
4. git_tools β throw new Error(
π I'm noting this pattern is unique in the file, so it doesn't match existing repo convention β manufacturing an Error just to populate
causewhen a structured validation error would be more appropriate. I'm also weighing whether thePreviewMainWindowClosedErrormessage is accurate for the null hostWebContents case β it's borderline but likely acceptable since a missing host webContents does effectively mean the window closed. I'm also considering whether hand-rolled type guards versus schema decoding matters here, checking whether browserRecording.ts follows the Effect service pattern or uses plain module state, and confirming the AggregateError usage for collecting cleanup errors is a legitimate normalization rather than duplicated error encoding. Now I'm comparing the mutability of fields in DesktopPreviewRecordingSource against the readonly convention used in the neighboring DesktopPreviewRecordingFrame interface.
5. browse_code β packages/contracts/src/ipc.ts
6. browse_code β apps/web/src/browser/browserRecording.ts
π I'm checking that private
Schema.isconstant isn't wrapped redundantly, but since it's pre-existing code outside the diff, I'll skip flagging it. Now I'm confirming both the "cleanup" and "stop-media-recorder" operations still appear correctly in the literals list. I want to verify whether "stop-media-recorder" is still referenced anywhere after this change, since if the refactor stopped constructing it, that literal could be dead code. Let me search for its usages.
7. git_tools β stop-media-recorder|initialize-media-recorder|operation: "
π Still using stop-media-recorder at that line. Now I want to check the save-artifact region around line 440-470 for how the mimeType is derived and where that error about MediaRecorder not reporting its output format gets thrown.
8. browse_code β apps/web/src/browser/browserRecording.ts
π This file is mostly plain code with only error-handling conventions to follow, not real Effect service patterns. I'm checking whether that thrown error about MediaRecorder not reporting its output format is inside a properly wrapped save-artifact block.
9. browse_code β apps/web/src/browser/browserRecording.ts
π I notice that when the primary operation fails alongside a cleanup error, the resulting error's operation field gets set to "cleanup," which hides the actual failure. I want to check the base file to see how this was structured before the diff, since it looks like cleanupError was previously tied to stop-media-recorder.
10. git_tools β e4f7b14:apps/web/src/browser/browserRecording.ts
π The removal of that canvas error class looks fine since canvas is gone. I'm noticing a new manufactured Error thrown when MediaRecorder doesn't report its output format, then wrapped as a generic save-artifact operation failure β that pattern of creating an Error just to populate a cause field feels like it loses useful structure, even though it's meant as a validation guard for a missing mimeType. But checking the repo, this manufactured-cause pattern already exists elsewhere (like the recording startup cancellation default cause and the startup-settle timeout), so it's arguably consistent with existing conventions rather than a new violation. The Manager.ts instance is more clearly novel though, since it synthesizes an Error inside an Effect.try just to build a PreviewOperationError, and I want to check if similar patterns show up in other desktop Effect services using thrown Errors inside try/attempt blocks. What bothers me more is that this validation isn't really an operation that can fail unexpectedly β it's a pure guard being forced through Effect.try, so the resulting error message ends up generic while the real reason is buried in a manufactured cause, which cuts against the convention of using tagged error classes with structured attributes. I also want to verify whether hostWebContents exists on the Electron WebContents type in use, whether requireWebContents actually returns an Electron WebContents, and whether the startRecording error channel already includes something like PreviewMainWindowClosedError as part of PreviewManagerError. And I should check if there's an existing pattern elsewhere in Manager.ts using schema decoding to validate results of executeJavaScript, since that would be the more idiomatic way to handle this.
11. git_tools β executeJavaScript(
π I notice executeJavaScript is only used in Manager.ts, while other automation elsewhere relies on debugger sendCommand with Runtime.evaluate. Now I want to check how the manager decodes unknown values coming from the renderer, so I'm searching for decodeUnknown usage in Manager.ts alongside the existing encodeUnknownJson.
12. git_tools β decodeUnknown|Schema.decode
π I'm checking whether similar validation patterns elsewhere use manual type checks rather than schema decoding, focusing on the Manager.ts guard around line 3118 that throws a bare Error inside Effect.try -- which conflicts with the convention of using structured errors instead of manufacturing generic ones just to populate a cause field. Now I'm looking at a second finding: PreviewMainWindowClosedError being reused for the hostWebContents null case, where its message about the main window being closed may not accurately describe the actual failure condition being checked. I'm also examining whether Manager.ts still retains the subscribeRecordingFrames API and related recording frame listeners even though this PR removed all recording frame delivery, making that subscription path, IPC forwarding, and associated schema types dead code that violates the convention against leaving compatibility shims.
13. git_tools β recordingFrameListenersRef|subscribeRecordingFrames|onFrame|RECORDING_FRAME_CHANNEL
π My earlier grep was too broad. I noticed
recordingFrameListenersRefis still referenced in Manager.ts around lines 1112-1114, meaning the debugger screencast path still delivers recording frames when that consumer is activeβyet the PR removed the test covering that behavior, so I want to check whether the production code was actually supposed to change too. I should look at Manager.ts lines 1080-1140 alongside the test around line 2302 that now expects zero-length recording frames.
14. browse_code β apps/desktop/src/preview/Manager.ts
π I'm noting that the screencast recording-frame path still exists in production, but the PR removed the test verifying it emits frames only while recording is activeβthat's a coverage gap even though it may fall outside the strict service-convention scope, since the underlying behavior is retained but now untested. I'm weighing whether to flag this or focus on the manufactured-Error validation in Manager.ts's startRecording instead, since
subscribeRecordingFramesis still actively used by the debugger screencast path so it's not dead code. I'm also checking whether the new logic in browserRecording.ts introduces any other convention issues worth raising. I'm confirming this is a real flaggable issue since it's using a try-based effect for a pure validation guard rather than a dedicated tagged error. The fix would require introducing a new error class carrying the tabId, webContentsId, and measured values, but since that spans multiple hunks I'm leaning toward omitting a concrete diff and instead noting the suggested approach without a not-yet-defined error class reference. I'm now pinning down the exact comment range in Manager.ts β settling on lines 3118 to 3141 to cover the whole guard block including the throw, so the context is clear when I describe the fix. I'm weighing whether to also flag browserRecording.ts lines 444-449, which has a similar pattern but feels like a weaker case since it could pass as a legitimate guard rather than misused control flow. I'm leaning toward posting only the Manager.ts finding as an inline comment since it's the more precise example, keeping the review focused rather than noisy. Given this is a genuine convention violation explicitly covered by the instructions, I'll mark the check as failure rather than treating it as an optional style nitpick.
15. modify_pr β One convention finding in apps/desktop/src/preview/Manager.ts: the new recording-source size validation is a pure domain/validation failure but is modeled by throwing a synthetic Error inside attempt so it surfaces as a generic PreviewOperationError whose only real information lives in a manufactured cause. Details inline. The rest of the change looks consistent with the repo's Effect conventions: namespace imports (* as Effect, * as PreviewManager), the new IPC method uses DesktopIpc.makeIpcMethod with Effect.fn and resolves PreviewManager.PreviewManager from the environment, no new ManagedRuntime.make / runPromise / service-instance injection was introduced, and the widened startRecording return type is reflected in the inline Context.Service interface and the contracts schema.
Agent Credits: 171 credits
Token usage: 28 uncached input Β· 1,062,642 cache-read input Β· 131,027 cache-write input Β· 10,920 output
Agent Credits may also include non-token charges from external tools such as web research.