refactor(effect): unify service namespaces and align naming#18093
Merged
kitlangton merged 6 commits intodevfrom Mar 18, 2026
Merged
refactor(effect): unify service namespaces and align naming#18093kitlangton merged 6 commits intodevfrom
kitlangton merged 6 commits intodevfrom
Conversation
7b1e927 to
6e5e24f
Compare
bb00a9f to
ce6a32e
Compare
Contributor
Author
|
CI status: Linux unit tests pass. Windows unit test failure is pre-existing on dev (last 4 dev test runs all fail on Windows). The Windows error is an unhandled ENOENT from |
422f628 to
f84b148
Compare
Fully-migrated modules now use a single domain namespace with Interface, Service, layer, and defaultLayer directly on it — collapsing the old two-namespace pattern (e.g. File + FileService → File.Service). Mixed-mode modules renamed to *Effect suffix per migration plan: - account/service.ts → account/effect.ts (AccountEffect) - auth/service.ts → auth/effect.ts (AuthEffect) - question/service.ts → question/effect.ts (QuestionEffect) - permission/service.ts → permission/effect.ts (PermissionEffect) - provider/auth-service.ts → provider/auth-effect.ts (ProviderAuthEffect) Other cleanups: - DiscoveryService → Discovery for naming consistency - AuthServiceError → AuthError - Remove no-op init() methods and unnecessary defaultLayer = layer - Un-export internal-only helpers (stamp, session in FileTime) - Fix double hidden() call in sortHiddenLast - Effect.fn trace names use bare domain (e.g. "File.read")
Verifies that when the same file appears in multiple patches passed to revert(), the first patch's snapshot hash is used — not the last.
Instance.reload triggers InstanceBootstrap which fires File.init() without await (intentionally async warmup). On Windows, the background Ripgrep.files() call would fail with ENOENT after the temp directory was deleted by `await using tmp`. Disposing instances in the finally block ensures background work is torn down before the directory goes away.
kick() is fire-and-forget background work. If the instance directory is removed before indexing completes (e.g. test cleanup on Windows), the unhandled ENOENT from Ripgrep.files() would crash the process. Catch and leave the cache as-is instead.
dad6d16 to
0369451
Compare
Replace the fire-and-forget Promise-based kick() with an Effect fiber scoped to the layer. When the instance is disposed, Effect interrupts the fiber automatically — no more unhandled ENOENT from Ripgrep when the directory is deleted during test cleanup. File.init() now joins the fiber (waits for scan completion) instead of awaiting a raw Promise.
0369451 to
36d02d5
Compare
AbhishekChorotiya
pushed a commit
to AbhishekChorotiya/opencode
that referenced
this pull request
Mar 19, 2026
AvatarGanymede
pushed a commit
to AvatarGanymede/opencode-dev
that referenced
this pull request
Mar 19, 2026
demostanis
pushed a commit
to demostanis/opencode
that referenced
this pull request
Mar 19, 2026
raf1hh
pushed a commit
to raf1hh/opencode
that referenced
this pull request
Mar 20, 2026
demostanis
pushed a commit
to demostanis/opencode
that referenced
this pull request
Mar 20, 2026
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Unifies all Effect service namespaces to follow the patterns in
EFFECT_MIGRATION_PLAN.md.Fully-migrated modules (single namespace, no suffix)
Collapse the two-namespace pattern (
Foo+FooServiceclass) into a single domain namespace withInterface,Service,layer,defaultLayer, and facade functions:Mixed-mode modules collapsed into index
These had separate
effect.ts+index.tsfiles. Since they go throughinstances.ts(lazy via LayerMap), there's no circular import — collapsed into one file:question/service.tsdeleted, everything inquestion/index.tspermission/service.tsdeleted, everything inpermission/index.tsprovider/auth-service.tsdeleted, everything inprovider/auth.tsMixed-mode modules kept separate (eager runtime import)
These are imported eagerly by
runtime.tsforManagedRuntime.make, so they can't be collapsed without circular deps:account/service.ts→account/effect.tsauth/service.ts→auth/effect.tsOther changes
AuthServiceError→AuthErrorDiscoveryService→DiscoveryProviderAuth.methods()return type narrowed toRecord<ProviderID, Method[]>withProviderID.make()at the plugin boundaryprovider/auth.ts(replaced with EffectArray.filterMap)Effect.acquireReleaseinit()methods and unnecessarydefaultLayer = layeraliasesEffect.fntrace names use bare domain ("File.read","Permission.ask")InterfaceconsistentlysortHiddenLastdoublehidden()callrevertto use first patch hash for overlapping files (was using last due to Map overwrite)Test plan
tsc --noEmitpassesbun turbo typecheckpasses across all packages