Skip to content

Merge branch 'pingdotgg:main' into feat/oh-my-pi-provider

MacroscopeApp / Macroscope - Effect Service Conventions failed Aug 25, 2026 in 3m 46s

Effect Service Conventions: 4 issues found

Four convention issues were found in the changed TypeScript scope and posted as inline review comments.

  • apps/server/src/provider/Layers/OhMyPiAdapter.ts (lines 272-277): the permission-handler failure is mapped to a hand-rolled object literal (_tag: "AcpTransportError") cast as never instead of constructing the real Schema.TaggedErrorClass (EffectAcpErrors.AcpTransportError), and its message is derived from the cause.
  • apps/server/src/provider/Layers/OhMyPiAdapter.ts (line 447): ProviderAdapterRequestError.detail merely copies cause.message instead of carrying stable structural context (the attachment id is available at the wrapping site).
  • apps/server/src/provider/Drivers/OhMyPiDriver.ts (line 121): ProviderDriverError.detail is built from cause.message ?? String(cause), so the wrapper message is derived from the cause rather than from stable attributes.
  • apps/web/src/components/settings/providerDriverMeta.ts (lines 36, 90): the PR deletes the badgeLabel and getDriverOption documentation comments while only adding a new provider entry, contrary to preserving useful comments during change.

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

Changed/added files matching the check's include patterns:

  • apps/server/src/provider/Drivers/OhMyPiDriver.ts
  • apps/server/src/provider/Layers/OhMyPiAdapter.ts
  • apps/server/src/provider/Layers/OhMyPiProvider.ts and its test
  • apps/server/src/provider/acp/OhMyPiAcpSupport.ts and its test
  • apps/server/src/provider/builtInDrivers.ts
  • apps/server/src/textGeneration/OhMyPiTextGeneration.ts
  • apps/web/src/components/chat/providerIconUtils.ts
  • apps/web/src/components/settings/providerDriverMeta.ts
  • packages/contracts/src/ohMyPi.ts, packages/contracts/src/index.ts

(scripts/**, docs/**, .github/**, and package.json changes are outside this check's include patterns and were used only as context.)

Conforming observations

  • Effect modules are imported as namespaces from their subpaths; local service modules (TextGeneration, AcpSessionRuntime, BackgroundPolicy, McpProviderSession) are imported as namespaces and referenced through Foo["Service"].
  • Driver/adapter/text-generation constructors acquire their dependencies with yield* Foo.Foo and expose them in the effect requirements; no ManagedRuntime.make, runPromise, or runPromiseExit was introduced.
  • Effect.catchTags is used for the known SchemaError tag in OhMyPiTextGeneration.ts; the broad Effect.catch in the notification stream intentionally handles the whole channel.
  • makeOhMyPiAcpRuntime takes childProcessSpawner explicitly and re-provides it with Layer.succeed; this is an exact mirror of the pre-existing GrokAcpSupport/CursorAcpSupport port shape, so it was treated as the established repository pattern rather than a new violation.

Additional non-blocking note

OhMyPiAdapter.ts (637 lines of new backend behavior: session start/resume, turn/steer, permission approval, cancellation, MCP injection) ships without adapter-level tests, while sibling adapters (GrokAdapter, CursorAdapter, OpenCodeAdapter) each have focused test suites. Adding focused tests for start/turn/permission/stop paths using test layers for the ACP child process would keep parity.


🔍 Agent activity — 20 tool calls

💭 I'm reviewing the diff across the OhMyPi driver, adapter, provider, and ACP support files for Effect service convention issues, and noticing that the ACP runtime constructor takes a child process spawner service directly as a parameter rather than through proper dependency injection. I'm spotting several error convention violations too: raw error objects being cast rather than using proper tagged error classes, error messages being derived directly from the cause, and detail fields that just duplicate cause.message in both the adapter's transport error and the driver's snapshot-building error. I'm also noticing inconsistent import styles for ChildProcessSpawner across files—some use named imports, others namespace imports from a subpath—so I want to check how other analogous provider files in the repo handle this to see which pattern is actually the established convention.

1. browse_code — apps/server/src/provider/acp/*.ts

2. browse_code — apps/server/src/provider/**/*.ts

💭 I should check GrokAcpSupport.ts and CursorAcpSupport.ts to see if they follow the same pattern of taking childProcessSpawner as a parameter.

3. browse_code — apps/server/src/provider/acp/GrokAcpSupport.ts

4. browse_code — apps/server/src/provider/Errors.ts

💭 I'm noting that the AcpSupport pattern using childProcessSpawner mirrors existing conventions like GrokAcpSupport, so it's not a new violation to flag. Since instructions say not to demand unrelated cleanup, I'm weighing whether the new file's service injection approach still warrants a comment given it follows established repo patterns. Turning to stronger candidates, I want to check how the error mapping is handled in OhMyPiAdapter.ts — it's constructing an ad-hoc error object and casting it to never rather than using a proper tagged error class, so I want to compare this against how GrokAdapter handles the equivalent permission request error mapping.

5. git_tools — handleRequestPermission

💭 I want to check how GrokAdapter's mapAcpCallbackFailure handles mapping callback failures to AcpError, to follow the existing convention.

6. git_tools — mapAcpCallbackFailure|mapExtensionFailure

💭 I notice the new OhMyPiAdapter breaks convention by constructing a raw object literal with a manual _tag and cast instead of using the proper AcpTransportError TaggedErrorClass — it should derive its message from structured attributes rather than storing it unstructured. Also flagging that detail: cause.message in the sendTurn readFile mapError just duplicates cause.message into the wrapper, which the guidelines explicitly discourage even though older code in CursorAdapter does the same thing — the new instructions should take precedence here. I want the detail to reflect real context like the file path or attachment id instead, something like Failed to read attachment '${attachment.id}' rather than a bare copy of the cause. Then I need to check the OhMyPiDriver snapshot error, which builds its detail from cause.message ?? String(cause), and compare that approach against how GrokDriver handles the same kind of failure.

7. browse_code — apps/server/src/provider/Drivers/GrokDriver.ts

💭 I notice OhMyPiDriver mirrors GrokDriver's pattern of building its error message from cause.message, which conflicts with the rule that wrapper messages must come only from stable structural attributes, not from cause. But I need to weigh this against the instruction not to demand unrelated repo-wide cleanup—so I'm considering whether this counts as a violation retained in the current change versus pre-existing pattern. I think the stronger, unambiguous violation is the OhMyPiAdapter's ad-hoc error cast using as never, which deviates from both the repo's own convention and the check's rules—that's worth flagging as a failure. I also want to double check the Effect.orDie usage on the UUID generation versus the existing typed error mapping, since it may be losing structured error handling, so I should look at the actual file to confirm line numbers and details.

8. browse_code — apps/server/src/provider/Layers/OhMyPiAdapter.ts

💭 I'm working out the exact line numbers for the inline diff comments, targeting lines 272-277 of OhMyPiAdapter.ts where the mapError block sits, and checking whether the ProviderAdapterShape import should be inlined per the conventions. But since ProviderAdapterShape is already an exported type shared by other adapters like GrokAdapter, I should check how those other adapters use it before deciding whether to change it here.

9. browse_code — apps/server/src/provider/Services/ProviderAdapter.ts

10. browse_code — apps/server/src/textGeneration/GrokTextGeneration.ts

💭 I'm checking that the TextGeneration file follows the same pattern as GrokTextGeneration, then reviewing the rest of the diff — the removed uploadFeedback in OhMyPiAdapter looks optional and fine, the Effect.catch usage on the notification stream matches the rule for intentionally handling the whole error channel, and I'm now looking at whether Effect.orDie on the UUID generation should instead map to a typed error like other adapters do. More significantly, I've spotted that providerDriverMeta.ts strips out two useful JSDoc comments unrelated to the PR's actual purpose — one describing a warning badge and another for a lookup function — which conflicts with the guidance to preserve documentation when moving code. I want to confirm the fields those comments referenced are still present by comparing the file against its merge base. There's also a minor unrelated style tweak in providerIconUtils.ts, but that's just churn rather than a real violation.

11. browse_code — apps/web/src/components/settings/providerDriverMeta.ts

💭 I've confirmed two doc comments were deleted without functional justification, which violates the guideline to preserve useful documentation when moving code—worth flagging as an inline comment. I also want to verify whether PiAgentIcon actually exists in the Icons module, since if it doesn't that's a build-breaking issue worth noting even outside our review scope. The Effect import in the contracts file looks fine, only used for Effect.succeed. Export ordering in the contracts index doesn't matter here, and ProviderDriverKind accepting "ohMyPi" as a branded string via .make is also fine. Now I want to check McpProviderSession.readMcpProviderSession to see if it's reading from module-level global state, which would violate the rule against hiding dependencies in module globals.

12. git_tools — PiAgentIcon

13. browse_code — apps/server/src/mcp/McpProviderSession.ts

💭 McpProviderSession looks like a pre-existing module-global registry other adapters likely rely on, so I should check whether other adapters use readMcpProviderSession too.

14. git_tools — readMcpProviderSession

15. browse_code — apps/server/src/provider/Layers/OhMyPiAdapter.ts

💭 Let me check how the GrokAdapter handles attachment readFile errors for comparison.

16. git_tools — resolveAttachmentPath

💭 This mirrors an existing pattern elsewhere in the repo, so it's not really a new problem being introduced. Given the guidance to avoid demanding unrelated cleanup but still flag concrete new issues, I think the reasonable approach is to only call out the clearly novel deviations introduced by this file rather than pre-existing conventions. I should also weigh test coverage: this is a whole new provider driver and adapter with backend behavior changes, but only a couple of small tests covering it, whereas other providers have much more thorough adapter test suites. I think I'll flag the missing OhMyPiAdapter test coverage as a summary note rather than an inline comment, alongside the two stronger inline findings. I also want to verify whether the as never cast is a legitimate type workaround by checking if effect-acp actually exposes an AcpTransportError class I should be constructing directly instead of using a plain object literal.

17. git_tools — class AcpTransportError

💭 I've confirmed AcpTransportError is a proper tagged error class, so the PR should construct it directly with method, detail, and cause fields rather than hand-rolling an object cast to never—and that object literal also improperly derives a message from the cause, a second violation. Now I'm turning to check OhMyPiAcpSupport.ts for similar issues. I'm compiling three findings: the hand-rolled error cast on lines 271-278 of OhMyPiAdapter.ts, the detail: cause.message shortcut on line 447 that loses structural detail like attachment id, and the deleted doc comments in providerDriverMeta.ts that break change discipline—I'm figuring out which line to attach that inline comment to given the diff only shows removed lines.

18. github_api_read_only — repos/{owner}/{repo}/pulls/{pull_number}/files?per_page=100

💭 The build-desktop-artifact.ts change is out of scope since scripts/ isn't covered by the review patterns, and the provider icon import issue is pre-existing so I'll leave it be. Now I'm narrowing down the actual findings within scope, starting with the error handling in OhMyPiAdapter.ts where there's a hand-rolled error cast instead of using the proper error construction pattern. For the fix, since it needs both a code change and a new import, I can't offer it as a simple inline suggestion — I'll present the recommended replacement as a code snippet alongside a note about the required import. Next I'm looking at another spot in the same file where the detail message just copies the cause's message directly; this one I can fix with a clean inline suggestion that references the specific attachment id instead. I'm also weighing whether to flag a third violation in the driver file where detail is again derived from cause.message, mirroring an existing pattern elsewhere in the codebase — it's new code and directly violates the explicit rule against deriving messages from the cause, so despite the risk of feeling repetitive, I'll include it with a suggested static detail message. I need to check the exact line number in the new file to reference it correctly, so I'm reviewing that section of the file now. I'm also noting that some documentation comments were removed in providerDriverMeta.ts, which conflicts with the guidance to preserve existing comments. Now I'm figuring out the exact line numbers so my inline comments land correctly within the diff hunks — the badgeLabel field appears to fall in range for one comment, and I'm considering combining a mention of the getDriverOption doc removal into that same comment rather than adding a second one.

19. browse_code — apps/server/src/provider/Drivers/OhMyPiDriver.ts

💭 I'm drafting the first inline comment, flagging that the permission handler failure uses a hand-rolled object cast to never instead of the proper EffectAcpErrors.AcpTransportError class, and suggesting the fix. For the second comment at line 447, I'm noting the exact indentation needed and preparing a suggestion to replace detail: cause.message with a more descriptive error message referencing the attachment ID. Then I'm working through comment 3, which needs a similar indentation fix for a suggestion in the provider snapshot builder file, and noting comment 4 still needs to be addressed in the meta file before posting all the review comments.

20. modify_pr — Effect service conventions review of the new Oh My Pi provider files. The overall service/driver layout follows the existing driver template (namespace imports from effect/* subpaths, Foo["Service"] references, dependencies acquired with yield*), but a few error-modelling and change-discipline items in the changed scope need attention. See inline comments.


Agent Credits: 220 credits