mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-07-01 17:39:39 +02:00
17 KiB
17 KiB
TrustGraph Effect-Native Rewrite Opportunity Audit
This is the first ranked audit produced from the playbook in
ts/EFFECT_NATIVE_REWRITE_PLAYBOOK.md. It is an opportunity map, not a code
rewrite. The branch was ts-port-effect-v4; the only unrelated local file seen
during the audit was .idea/effect.intellij.xml.
Inputs
Verified source roots:
- TrustGraph TS port:
/home/elpresidank/YeeBois/dev/trustgraph/ts - Effect v4 subtree:
/home/elpresidank/YeeBois/projects/beep-effect2/.repos/effect-v4 - Reactivity fallback:
ts/node_modules/effect/src/unstable/reactivity - Atom React fallback:
ts/packages/workbench/node_modules/@effect/atom-react
Signal counts from ts/packages:
| Signal | Count |
|---|---|
Effect.runPromise |
71 |
Map< |
54 |
JSON.stringify |
50 |
WebSocket |
45 |
process.env |
44 |
new Map |
42 |
toPromiseRequestor |
19 |
makeAsyncProcessor |
19 |
new Promise |
18 |
JSON.parse |
16 |
receive( |
16 |
setTimeout |
13 |
while ( |
10 |
localStorage |
8 |
Loop Passes
2026-06-02: Base Request/Response Facade
- Status: migrated and verified.
- Completed:
ts/packages/base/src/messaging/request-response.ts:50now creates an explicitScope.Closeableand:55builds the existingEffectRequestResponseruntime.ts/packages/base/src/messaging/request-response.ts:91rejects not-started calls withMessagingLifecycleError, and:108maps recipient callback failures intoMessagingDeliveryError. It no longer constructs normalErrorvalues.ts/packages/base/src/messaging/runtime.ts:427now lets request/response own its producer directly,:442runs the response dispatcher withEffect.forkScoped, and:445makes shutdown idempotent.ts/packages/base/src/__tests__/request-response.test.ts:115covers the Promise facade over the Effect runtime,:143asserts tagged timeout errors, and:164asserts tagged lifecycle errors.
- Verification:
bun run --cwd ts/packages/base testbun run --cwd ts/packages/base buildbun run --cwd ts check:tsgobun run --cwd ts buildbun run --cwd ts test
- Remaining base evidence:
makeSubscriber(has no currentts/packagescall sites after this slice, butts/packages/base/src/messaging/index.tsstill exportsmakeAsyncQueue,makeSubscriber, and related types.ts/packages/base/src/messaging/consumer.tsstill has a Promise polling loop and a normalErrorconstructor.ts/packages/base/src/messaging/producer.tsstill throws a normal not-startedError.
- Decision:
- Normal
Errorconstruction in library internals is migration evidence. Prefer existingS.TaggedErrorClasserrors fromts/packages/base/src/errors.ts, adding new tagged errors when needed. try/catchblocks are also migration evidence. PreferEffect.try,Effect.tryPromise, orResult.tryunless the block is a host/tool boundary or test-only helper.
- Normal
2026-06-02: Gateway Dispatcher Requestor Cache
- Status: migrated and package-verified.
- Completed:
ts/packages/flow/src/gateway/dispatch/manager.ts:121centralizes streaming completion detection asdispatcherManagerIsCompleteResponse.ts/packages/flow/src/gateway/dispatch/manager.ts:137stores requestors asEffectRequestResponsehandles, notPromise<RequestResponse>values.ts/packages/flow/src/gateway/dispatch/manager.ts:152starts the manager through an Effect program,:157creates aSynchronizedRefcache, and:164usesEffect.onErrorfor scope cleanup instead of atry/catchblock.ts/packages/flow/src/gateway/dispatch/manager.ts:200usesSynchronizedRef.modifyEffectso lazy requestor creation and caching are serialized under the manager scope.ts/packages/flow/src/gateway/dispatch/manager.ts:267and:312keep Fastify/RPC as Promise boundaries viaEffect.runPromise; streaming responder failures are mapped withMessagingDeliveryErrorat:290and:340.ts/packages/flow/src/gateway/server.ts:25accepts an optional injectedPubSubBackendfor tests without changing production NATS defaults.ts/packages/flow/src/__tests__/gateway-dispatcher.test.ts:150verifies scoped requestor reuse and shutdown,:172verifies streaming through the centralized completion predicate, and:192table-tests all final markers.
- Verification:
bun run --cwd ts/packages/flow testbun run --cwd ts/packages/flow buildbun run --cwd ts check:tsgo
- Remaining gateway evidence:
ts/packages/flow/src/gateway/rpc-server.tsstill has Promise callbacks around Effect RPC queues.ts/packages/flow/src/gateway/server.tsstill has Fastify routetry/catchblocks. These are boundary code, but should still be audited forEffect.tryPromisewrapping where it improves consistency.ts/packages/client/src/socket/trustgraph-socket.tsstill duplicates some streaming final-marker detection on the client side.
Ranked Findings
P0: Collapse Base Messaging Promise Facades
- Impact: 5
- Risk: 4
- Confidence: 4
- TrustGraph evidence:
ts/packages/base/src/messaging/runtime.tsalready defines Effect producer, consumer, request/response factories, queues, fibers, and scopes.ts/packages/base/src/messaging/consumer.tsstill has a manualwhile (running)receive loop,sleep, and Promise delay helpers.ts/packages/base/src/messaging/subscriber.tsstill manages resolver maps and timeout promises.ts/packages/base/src/processor/flow.tsexposes compatibility scope helpers and converts Effect handles back into Promise-style handles.
- Effect evidence:
effect/Queue,effect/PubSub,effect/Stream,effect/Scope,effect/Layer,effect/Schedule,effect/Ref.- Sources:
packages/effect/src/Queue.ts,PubSub.ts,Stream.ts,Scope.ts,Layer.ts,Schedule.ts,Ref.ts.
- Rewrite shape:
- Make the Effect runtime factories the canonical internal surface.
- Keep Promise adapters only at external compatibility boundaries. Rejected values at those boundaries should still be tagged TrustGraph errors.
- Replace polling sleep loops with scheduled scoped consumers where possible.
- Replace resolver maps with
Queue,Deferred, orPubSub-backed routing.
- Tests:
cd ts && bun run --cwd packages/base test- Existing runtime tests around request/response, flow specs, and consumers should be expanded before removing compatibility behavior.
- Blockers:
- Public package exports may still expect Promise-shaped producer, consumer, and request/response handles. Inventory callers before changing exports.
- First slice completed request/response facade migration. Next base follow-up
is either an Effect-backed consumer facade or a public export decision for
subscriber.ts.
P0: Convert Stateful Flow Services To Scoped Effect Services
- Impact: 5
- Risk: 4
- Confidence: 4
- TrustGraph evidence:
ts/packages/flow/src/config/service.tsusesmakeAsyncProcessor, mutable nestedMapstate,while (this.running),receive(2000),sleep, JSON persistence, and directprocess.env.ts/packages/flow/src/librarian/service.ts,cores/service.ts, andflow-manager/service.tsrepeat the same service-object pattern.
- Effect evidence:
Context,Layer.scoped,Ref,SynchronizedRef,Schedule,Effect.addFinalizer,Config,Schema,effect/FileSystem,effect/unstable/persistence/KeyValueStore.- Sources:
packages/effect/src/Context.ts,Layer.ts,Ref.ts,SynchronizedRef.ts,Schedule.ts,Config.ts,Schema.ts,ts/node_modules/effect/src/FileSystem.ts,ts/node_modules/effect/src/unstable/persistence/KeyValueStore.ts.
- Rewrite shape:
- Model each service as a
Contextservice plus a scoped layer. - Store service state in
ReforSynchronizedRef, not mutable object fields. - Express persistence with
effect/FileSystemorKeyValueStore.layerFileSystemwhen the installed beta exposes the needed provider. - Decode persisted payloads and config with schemas at boundaries.
- Model each service as a
- Tests:
- Service-specific tests plus
cd ts && bun run --cwd packages/flow test. - Add persistence round-trip tests before replacing file IO.
- Service-specific tests plus
- Blockers:
- These services are behavior-heavy. Do one service per PR after the shared runtime surface is stable.
P0: Make Gateway Dispatcher Effect-Native
- Impact: 5
- Risk: 3
- Confidence: 4
- TrustGraph evidence:
ts/packages/flow/src/gateway/server.tsalready builds RPC/WebSocket pieces with Effect.ts/packages/flow/src/gateway/rpc-server.tsusesQueueand RPC layers.ts/packages/flow/src/gateway/dispatch/manager.tsstill keepsMap<string, Promise<RequestResponse<unknown, unknown>>>, manual streaming completion checks, and per-publish producer construction.
- Effect evidence:
effect/unstable/rpcRpcClient,RpcServer,RpcSerialization.effect/unstable/socketSocket.effect/Queue,Stream,Scope,Layer.- Sources:
ts/node_modules/effect/src/unstable/rpc/RpcClient.ts,RpcServer.ts,RpcSerialization.ts, andts/node_modules/effect/src/unstable/socket/Socket.ts.
- Rewrite shape:
- Convert dispatcher manager methods to Effect-returning functions internally.
- Cache requestors as scoped resources instead of Promise values.
- Represent streaming dispatch as
StreamorQueueinstead of callback completion detection where the wire protocol allows it. - Keep Fastify route handlers as Promise boundaries.
- Tests:
- Gateway dispatch tests with fake pubsub.
cd ts && SKIP_LLM=1 bun run test:pipelineafter implementation.
- Blockers:
- The gateway is an integration boundary. Preserve current HTTP and WebSocket wire behavior during the first rewrite.
- First dispatcher-cache slice is complete. Follow-up gateway work should target RPC server Promise callbacks and client-side streaming completion duplication, not recreate the requestor cache migration.
P1: Remove RAG And Agent toPromiseRequestor Bridges
- Impact: 4
- Risk: 3
- Confidence: 5
- TrustGraph evidence:
ts/packages/flow/src/retrieval/document-rag-service.tsts/packages/flow/src/retrieval/graph-rag-service.tsts/packages/flow/src/agent/react/service.ts- All define
toPromiseRequestorand then immediately adapt Effect requestors back to Promise-style clients.
- Effect evidence:
- Existing TrustGraph
EffectRequestResponseints/packages/base/src/messaging/runtime.ts. effect/Stream,Effect.fn,Effect.runPromiseWithfor boundary-only execution.
- Existing TrustGraph
- Rewrite shape:
- Update RAG engines and agent helpers to accept Effect requestors or
functions returning
Effect. - Keep Promise wrappers only for old public APIs or tests that explicitly verify compatibility.
- Convert streaming agent flows to
Streamwhere possible.
- Update RAG engines and agent helpers to accept Effect requestors or
functions returning
- Tests:
- Existing RAG and agent service tests.
- Add tests that assert requestor errors stay typed through the Effect path.
- Blockers:
- Engine call signatures need a small design pass so RAG and agent rewrite in the same direction.
P1: Finish Client RPC Boundary Modernization
- Impact: 4
- Risk: 3
- Confidence: 4
- TrustGraph evidence:
ts/packages/client/src/socket/effect-rpc-client.tsalready usesSocket.makeWebSocket,RpcClient.layerProtocolSocket, andRpcSerialization.layerNdjson.- The same file still owns
scopePromise,clientPromise, repeatedEffect.runPromise, listener sets, a WebSocket constructor shim, and a Promise facade. ts/packages/client/src/socket/trustgraph-socket.tsis mostly a compatibility API over the Effect RPC client.
- Effect evidence:
effect/unstable/socket/Socket:makeWebSocket,fromWebSocket,toChannel,layerWebSocket.effect/unstable/rpc/RpcClient:layerProtocolSocket.effect/unstable/rpc/RpcSerialization:layerNdjson,layerNdJsonRpc.
- Rewrite shape:
- Treat
EffectRpcClientas an internal managed runtime or scoped layer. - Expose Promise-returning methods only through a thin compatibility adapter.
- Move browser vs Node WebSocket constructor selection into platform layers.
- Treat
- Tests:
cd ts && bun run --cwd packages/client test- Keep timeout/retry tests around
withDispatchRequestPolicy.
- Blockers:
- Workbench and CLI still consume Promise-shaped client APIs.
P1: Make SDK, Storage, And Provider Layers Managed Resources
- Impact: 4
- Risk: 3
- Confidence: 3
- TrustGraph evidence:
ts/packages/flow/src/storage/triples/falkordb.tsts/packages/flow/src/storage/embeddings/qdrant-graph.tsts/packages/flow/src/storage/embeddings/qdrant-doc.tsts/packages/flow/src/model/text-completion/*.ts- These files create direct SDK clients and read
process.envin live constructors.
- Effect evidence:
Effect.acquireRelease,Layer.scoped,Config,ConfigProvider,effect/FileSystem,effect/unstable/persistence/KeyValueStore,Metric,Logger.- AI provider modules from installed provider packages, with subtree source
proof under
packages/ai/*/src, includingOpenAiLanguageModel.ts,AnthropicLanguageModel.ts, andOpenRouterLanguageModel.ts.
- Rewrite shape:
- Move env reading into
Configloaders and provider-specific layers. - Scope SDK clients that need explicit close/disconnect.
- Replace
consoleor ad hoc logging withEffect.log*and metrics where useful.
- Move env reading into
- Tests:
- Provider config tests with
ConfigProvider.fromMap. - Storage tests with fake clients before changing real resource lifetimes.
- Provider config tests with
- Blockers:
- Some third-party SDK clients may not have meaningful finalizers. Mark those no-op after proof instead of forcing fake lifecycle code.
P2: Canonicalize MCP Around The Effect Server
- Impact: 3
- Risk: 2
- Confidence: 5
- TrustGraph evidence:
ts/packages/mcp/src/server.tsis the old SDK/Zod server.ts/packages/mcp/src/server-effect.tshas Effect AI tools, schemas,McpServer, HTTP API integration, and provider layers.
- Effect evidence:
effect/unstable/aiTool,Toolkit,McpServer,McpSchema,LanguageModel.- Sources:
ts/node_modules/effect/src/unstable/ai/Tool.ts,Toolkit.ts,McpServer.ts,McpSchema.ts,LanguageModel.ts.
- Rewrite shape:
- Do not rewrite the Effect server from scratch.
- Make the Effect server canonical after parity checks.
- Keep the old server only as compatibility or delete it once entrypoints and tests prove the Effect path is complete.
- Tests:
- MCP package build/test.
- Tool parity diff against
server.tsbefore removal.
- Blockers:
- Needs a policy decision about old SDK server lifetime.
P2: Tighten Workbench Platform And Reactivity Usage
- Impact: 3
- Risk: 2
- Confidence: 4
- TrustGraph evidence:
ts/packages/workbench/src/atoms/workbench.tsalready uses Atom, AsyncResult, Reactivity, browser layers, and metrics.- Remaining direct browser state includes
localStoragereads/writes and DOM theme inspection.
- Effect evidence:
BrowserKeyValueStore.layerLocalStorage,BrowserKeyValueStore.layerSessionStorage,BrowserHttpClient,Clipboard.AtomRpc,AtomHttpApi,AtomRegistry,AsyncResult,Reactivity.
- Rewrite shape:
- Leave the workbench out of the first rewrite wave.
- Later, move persistent UI state through
BrowserKeyValueStoreand keep remote state in Atom RPC/HTTP API families if the client API becomes fully typed Effect RPC.
- Tests:
cd ts && bun run workbench:qa.
- Blockers:
- Workbench is already the most modern surface. Backend/runtime wins should happen first.
Recommended PR Order
- Config service scoped state migration.
- RAG and agent requestor bridge removal.
- Base consumer facade and subscriber export cleanup.
- Client compatibility facade tightening.
- Gateway RPC callback and client streaming completion cleanup.
- Storage/provider managed resource cleanup.
- MCP canonicalization and Workbench polish.
No-Op Rules
Do not flag these as rewrite blockers without additional proof:
- Promise-returning CLI actions and Fastify route handlers at external
boundaries. This does not exempt normal
Errorconstruction inside shared library code. try/catchblocks at host/tool boundaries only when the catch maps into a typed error or wire error. Internal exception capture should useEffect.try,Effect.tryPromise, orResult.try.S.Class,S.TaggedErrorClass,Context.Service,Rpc.make, andHttpApi.makewhen they are required or idiomatic for the Effect API.- Plain
Mapusage for local pure transformations, such as graph utility construction, unless the state is long-lived, mutable service state. - JSON stringification that is part of the TrustGraph wire contract, unless a schema codec can preserve the exact encoded form.
Acceptance
This audit is complete when:
ts/EFFECT_NATIVE_REWRITE_PLAYBOOK.mdexists.- This ranked audit exists and cites concrete TrustGraph and Effect surfaces.
git diff --checkpasses for both files.- No code rewrite is mixed into this audit.