Repository navigation
Effect Service Conventions: 2 issues found
apps/server/src/usage/usageOpenCodeDb.ts:1— new file-wide// @effect-diagnostics nodeBuiltinImport:offhas no adjacent comment explaining why the diagnostic must be disabled there.apps/server/src/usage/usageTranscripts.ts:500— newparseOpenCodeMessagebackend parsing behavior ships without focused tests, unlike the sibling Claude/Codex/Grok parsers covered inusageTranscripts.test.ts.
The three findings from the prior run are resolved: UsageService now uses the Effect Path service (the node:path import and its file-level suppression are gone), resolveOpenCodeDbPath receives HostProcessEnvironment from the service, and the turn.completed payload spreads only defined keys without the as never cast.
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: apps/server/src/usage/UsageService.ts, apps/server/src/usage/usageOpenCodeDb.ts, apps/server/src/usage/usageTranscripts.ts, apps/server/src/usage/usageScanCache.ts, apps/server/src/provider/Layers/OpenCodeAdapter.ts, packages/contracts/src/usage.ts, plus the web/mobile provider presentation maps.
Checked and considered acceptable:
usageOpenCodeDb.tsfollowing the existingusageTranscriptReader.tspattern (Promise helper module bridged viaEffect.promisefrom the service,nullfor unreadable sources so the caller can report afailedsource instead of caching an empty result). This matches established usage-module precedent and is not fake dependency injection or a hidden runtime.- No
ManagedRuntime.make,runPromise,runPromiseExit,Layer.succeed, or service-instance parameters were introduced in the changed code. turn.completedpayload construction now type-checks againstTurnCompletedPayload(usage: Schema.optional(Schema.Unknown),modelUsage: Schema.optional(UnknownRecordSchema)), with optional keys conditionally spread.- Contract version bump to 6 with
USAGE_MERGE_COMPATIBLE_SINCEunchanged, and theusageScanCacheprovider guard extended foropencode.
Minor observation not posted (outside this check's concrete-violation bar): resolveOpenCodeDbPath still defaults its env parameter to process.env, so a future caller that omits the argument bypasses HostProcessEnvironment; the service call site passes it correctly today. Also, the new mightCarryUsage branch for "opencode" is unreachable because OpenCode usage is read from the SQLite database rather than line scanning.
🔍 Agent activity — 15 tool calls
💭 I'm checking whether the prior review's three concerns were addressed between commit b9e723c and the current head at 8aeb626. It looks like the env parameter is now threaded through, with UsageService passing hostEnvironment instead of relying solely on the default process.env. I'm also verifying whether the turn.completed payload construction was cleaned up to avoid unsafe type casting, and whether path/os module usage in UsageService is using the Effect Path service correctly rather than the raw node modules. I want to pull up the actual files to confirm.
1. git_tools — NodeOS|NodePath|node:path|node:os|nodeBuiltinImport",|nodeBuiltinImport
2. browse_code — apps/server/src/usage/usageOpenCodeDb.ts
💭 Good, the path service, env threading, and cast fixes are all confirmed addressed. Now I'm checking the remaining item at the top of usageOpenCodeDb.ts. line 1, which has a file-wide
nodeBuiltinImport:offsuppression directive with no adjacent explanation — that violates the requirement that every new suppression needs a comment justifying it. I need to trace whether this suppression was already flagged elsewhere or is tied to a different file, since a grep of UsageService.ts shows it no longer has that directive. This particular file's suppression seems new and unflagged so far, but I want to check whether similar files in the repo, like usageTranscriptReader.ts, follow the same pattern with or without explanations before treating this as a clear-cut violation.
3. git_tools — effect-diagnostics nodeBuiltinImport
4. browse_code — apps/server/src/usage/UsageService.ts
💭 I'm noticing the bare directive without explanation is common elsewhere in the repo too, like usageTranscriptReader.ts. The module docstring nearby does hint at why node builtins are needed since it reads the SQLite file directly, though it's not an explicit justification tied to the directive itself. I should focus on whether this new module actually breaks Effect service conventions. It uses Promise-based code wrapped in
Effect.promiserather than going through Effect's FileSystem the way the sibling reader module does, which could be a real inconsistency worth flagging. I'm also weighing whether defaulting the env parameter toprocess.envcounts as hiding a dependency, though since it's threaded in from the calling service rather than accessed globally, it may be a lesser concern. Now I want to check how UsageService actually passes the host environment intoresolveOpenCodeDbPath, and compare the error-handling pattern in the new reader against the existing transcript reader to see if swallowing errors as null is already an established convention or a genuine deviation from the tagged-error approach.
5. browse_code — apps/server/src/usage/usageTranscriptReader.ts
6. browse_code — apps/server/src/usage/UsageService.ts
💭 I'm noticing the new file mirrors the sibling module's style but omits the justification for using node builtins instead of Effect FileSystem that the sibling explicitly includes in its docstring. I also recall a prior comment referenced UsageService.ts's suppression directive, not this file's, so this particular directive hasn't been flagged yet — it's a new file, so I'll note it with a suggestion to add justification. Now I want to check the OpenCodeAdapter changes for any service convention issues.
7. browse_code — apps/server/src/provider/Layers/OpenCodeAdapter.ts
8. browse_code — apps/server/src/provider/Layers/OpenCodeAdapter.ts
💭 I'm questioning whether the usage object passed into turn.completed actually matches the expected shape, since it's the raw OpenCodeTokens structure rather than whatever format the contract expects for Claude—now that the
as nevercast is gone, TypeScript should catch this mismatch if it's real. This feels like a correctness concern outside the scope of Effect service conventions, so I'll only flag it if the type check clearly fails; otherwise I should stay focused on the conventions review and check the contract's actual definition for turn.completed's usage field.
9. git_tools — modelUsage
💭 The raw promise usage in usageOpenCodeDb.ts seems acceptable given the sibling module follows the same pattern and isn't a service. The bare suppression directive without explanation is a real violation of the change discipline convention, though the sibling file has the same bare form, so precedent may excuse it. The
resolveOpenCodeDbPathdefault of process.env is a mild leftover from my earlier feedback -- the caller does pass hostEnvironment properly now, so re-flagging feels nitpicky and I'll skip it. I want to double check that the UsageService correctly passes hostEnvironment as a HostProcessEnvironment service by tracing its type back to where it's yielded.
10. git_tools — HostProcessEnvironment
11. browse_code — apps/server/src/usage/UsageService.ts
💭 With findings 1 and 3 resolved and finding 2 partly handled, I'm checking what else in this file still violates the rules. I notice a bare suppression comment in usageOpenCodeDb.ts without justification, but since it was present unchanged in the prior commit and wasn't flagged then, I shouldn't raise it now to avoid duplicating past feedback. I'm also weighing whether the module's docstring counts as sufficient explanation for disabling the node builtin import check, since it justifies the DB-scanning approach but not the specific suppression choice—so I'd lightly flag it with a suggested rationale addition. I'm also looking at the empty catch blocks around error handling and connection closing, but these seem consistent with existing patterns elsewhere in the codebase, so probably not worth flagging. Now I'm considering whether the significant new parsing logic added in this PR—message parsing, token extraction, and DB reading—requires focused tests, since this isn't a mechanical refactor but genuinely new backend behavior. I want to check whether existing parser tests exist for the other adapters, so I can point to where a corresponding OpenCode parser test should live.
12. browse_code — apps/server/src/usage/*.test.ts
13. git_tools — parseGrokLine|parseCodexLine
💭 I notice the new parseOpenCodeMessage function lacks the focused unit tests that other provider parsers have in usageTranscripts.test.ts, which violates the existing testing convention. I'm also spotting that mightCarryUsage's new "opencode" branch is effectively dead code since OpenCode uses the DB reader path rather than line-based parsing. Deciding what to flag: the file-wide nodeBuiltinImport:off in usageOpenCodeDb.ts needs an inline comment suggesting rationale, and the missing tests for parseOpenCodeMessage deserve their own inline comment. Now I need to pin down the exact diff line numbers for both files to post these as inline review comments.
14. git_tools — export function parseOpenCodeMessage
💭 The node builtin imports in usageOpenCodeDb.ts genuinely need the suppression since it's importing node:fs, node:os, node:path, and node:sqlite, but the file lacks any rationale explaining why. Confirming this is a new file so the whole thing falls within the diff, I'm drafting a comment flagging that the suppression at line 1 needs justification. For the second finding, I'm noting that the new parser in usageTranscripts.ts around line 500 lacks focused tests, unlike its sibling parsers which are covered — I want to ask for specific test cases around role handling, cache-exclusive tokens, reasoning clamps, and timestamp fallbacks. Given both findings are concrete violations, I'm setting the review state to failure rather than passing, and then posting the review.
15. modify_pr — Two findings on this revision. The three items from the previous run (Effect Path in UsageService, threading HostProcessEnvironment into resolveOpenCodeDbPath, and the as never cast on the turn.completed payload) are resolved.
Agent Credits: 104 credits
Token usage: 20 uncached input · 545,849 cache-read input · 76,731 cache-write input · 9,440 output
Agent Credits may also include non-token charges from external tools such as web research.