mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-07-01 01:19:38 +02:00
57 KiB
57 KiB
TrustGraph Effect-Native Rewrite Opportunity Audit
This is the current backlog snapshot for the playbook in
ts/EFFECT_NATIVE_REWRITE_PLAYBOOK.md. The branch is ts-port-effect-v4.
The unrelated local file .idea/effect.intellij.xml must stay uncommitted.
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 - Installed Effect beta used by this workspace:
ts/node_modules/effect
Current signal counts from ts/packages after the 2026-06-02 client socket
close Effect boundary slice:
| Signal | Count |
|---|---|
Effect.runPromise |
172 |
Effect.runPromiseWith |
0 |
Effect.cached |
0 |
Layer.succeed |
18 |
Map< |
82 |
WebSocket |
62 |
new Map |
60 |
toPromiseRequestor |
0 |
makeAsyncProcessor |
19 |
receive( |
17 |
while ( |
2 |
new Error |
8 |
new Promise |
10 |
JSON.parse |
4 |
localStorage |
8 |
JSON.stringify |
7 |
setTimeout |
4 |
process.env |
3 |
Notes:
- The remaining
process.envhits are inpackages/workbench/playwright.config.ts. - In production
packages/base,packages/cli, andpackages/mcpsources, the strict scans fornew Error,new Promise,setTimeout,JSON.parse,JSON.stringify, and directprocess.envreads are clean. Effect.runPromiseis expected at external Promise compatibility boundaries, but each match should still be audited for avoidable internal runtime ownership.- The
Map<andnew Mapcounts increased in this snapshot because the Librarian slice introduced explicit ref-backed state types and clone helpers while removing the service object's direct mutable maps/handles. - The
Effect.runPromiseandWebSocketcounts dropped in this snapshot becauseEffectRpcClientnow owns its RPC/socket layer withManagedRuntimeand uses Effect's WebSocket constructor layer. - The raw
WebSocketcount increased in this snapshot because the adapter slice added focused tests and typed adapter names; productionwebsocket-adapter.tsis now clean oftry/catch, normalError, and the previous constructor assertions. - The
new Errorcount dropped becausewebsocket-adapter.tsnow throwsS.TaggedErrorClassadapter errors. - The latest client socket slice removed the remaining production
trustgraph-socket.tsnormalError, rawJSON.parse, and listenertry/catchmatches. The remaining client socket modernization signal is the sharednewableFactoryconstructor assertion pattern. - The service entrypoint runtime slice dropped the
Effect.runPromisecount by replacing remaining flow servicerun()program facades withManagedRuntimeand routing localts/scripts/run-*launchers throughrunMain()/NodeRuntime.runMain. - The base processor compatibility runtime slice dropped the
Effect.runPromisecount again by movingAsyncProcessor,Flow, andFlowProcessorPromise compatibility facades ontoManagedRuntime. - The base flow definition schema slice removed hand-rolled
Predicate/object narrowing fromflow-processor.ts; signal counts are unchanged because this was a validation-quality migration. - The text completion stream sentinel slice removed the duplicated
Effect.void as Effect.Effect<undefined>assertions from provider stream unfold branches. Counts are unchanged because this was an Effect diagnostic and type-channel cleanup. - The text completion generator boundary slice removed the
Effect.runPromise(Effect.fail(...))fallback and the relatedAsyncGenerator/IteratorResultassertions frommodel/text-completion/common.ts. - The text completion provider status slice replaced manual status/statusCode
record assertions with
effect/Predicatenarrowing. - The base parameter spec accessor slice added Schema-backed
ParameterSpec<T>values plusflow.parameterEffect(spec)andflow.parameter(spec). Bare string parameter lookup remains available as anunknowncompatibility escape, while typed parameter access now decodes through Schema and fails with a taggedFlowParameterDecodeError. - The base producer/requestor spec accessor slice added typed spec-object
accessors for
ProducerSpec<T>andRequestResponseSpec<TReq, TRes>, then migrated flow service producer/requestor lookups off caller-chosen generic string calls. Spec object handles are scoped perFlowthrough WeakMaps and finalizers delete only the handle they registered. - The native PubSub boundary slice removed the unused legacy
messaging/subscriber.tsasync queue/fanout implementation. Effect's nativePubSubis an in-process hub and does not replace the broker-backedPubSubBackend/NATS boundary, but it should be preferred for future in-process broadcast/fanout needs. - The gateway streaming callback slice added Effect-returning dispatcher
streaming methods, switched the RPC stream server off nested
Effect.runPromiseWith(context)queue offers, and replaced the clientStopStreamingsentinel error withStream.runForEachWhile. - The FalkorDB scoped client lifecycle slice removed the remaining
Effect.cachedmatches fromts/packages. FalkorDB triples store/query Live layers and direct compatibility factories now acquire clients throughEffect.acquireReleaseand disconnect them on scope close. TheEffect.runPromisecount increased by two because the new lifecycle tests run scoped programs at the test boundary. - The Qdrant config/schema/fakeability slice removed direct production
new QdrantClient, sync config loading, payload casts, and QdrantLayer.succeedservice construction from graph/doc store/query modules. The installed Qdrant client exposes no public close/disconnect method, so this remains a fakeable construction and Schema decode slice rather than a scoped finalizer slice.Effect.runPromiseincreased because the new tests and legacy service initialization logs run Effects at compatibility boundaries. - The client streaming facade slice did not change signal counts. It
centralized the legacy streaming
{ response, complete, error }envelope decode intrustgraph-socket.ts, uses Schema pluseffect/Predicateproperty narrowing for streaming payload reads, and leaves service-specific legacy completion markers only where they preserve public callback behavior. - The Ollama embeddings effectful layer slice dropped one
Layer.succeedmatch by makingOllamaEmbeddingsLiveeffectful and mapping config/load failures toEmbeddingsError. TheJSON.stringifycount increased by one because the new layer test uses a JSON response fixture. - The text completion provider stream helper slice removed all provider-local
Stream.unfoldpull loops, dropped thewhile (count from 9 to 3, and removed the Mistralcontent as stringassertion. The only remaining text-completioniterator.nextmatch is thetoAsyncGeneratorcompatibility adapter that exposes Effect streams through the publicAsyncGenerator<LlmChunk>provider contract. - The request-response queue stream slice replaced the Effectful
waitForResponsegenerator loop withStream.fromQueue,Stream.filterMapEffect,Result, andStream.runHead, dropping the remainingwhile (count from 3 to 2. The two remaining productionwhilehits are synchronous parsing/CLI traversal loops, not async polling loops. - The gateway RPC WebSocket cause-handling slice removed the Promise
.catcharound the socket program by sandboxing the Effect and handling the resultingCausein the Effect pipeline before the Fastify fire-and-forgetrunPromiseboundary. - The client RPC acquisition cause tap slice removed the Promise
.catchused only to update connection state on runtime/client acquisition failure.effect-rpc-client.tsnow usesEffect.tapCauseandCause.prettybefore the public Promise boundary. - The client socket close Effect boundary slice removed the Promise
.catchfromBaseApi.close(). The void public facade now runsrpc.close()throughEffect.tryPromiseand logs the tagged socket close error throughEffect.catch. Record<string, any>andthrowLibrarianServiceErrorare now clean ints/packages.
Loop Passes
2026-06-02: Base Request/Response Facade
- Status: migrated and verified.
- Completed:
- Request/response startup now owns a scoped Effect runtime handle and maps failures to TrustGraph tagged messaging errors.
- Runtime shutdown is idempotent and uses scoped fibers.
- Tests cover Promise compatibility, tagged timeout errors, and 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
2026-06-02: Gateway Dispatcher Requestor Cache
- Status: migrated and package-verified.
- Completed:
- Gateway dispatcher caches scoped
EffectRequestResponsehandles instead ofPromise<RequestResponse>values. - Lazy requestor creation is serialized with
SynchronizedRef.modifyEffect. - Streaming final-marker detection is centralized.
- Dispatcher cleanup uses Effect scope/error handling instead of manual
try/catch.
- Gateway dispatcher caches scoped
- Verification:
bun run --cwd ts/packages/flow testbun run --cwd ts/packages/flow buildbun run --cwd ts check:tsgo
2026-06-02: Strict Base, CLI, MCP, And tsgo Slice
- Status: migrated, root-verified, committed, and pushed.
- Completed:
- Base messaging, NATS backend, producer, consumer, subscriber,
request/response, runtime factories, processor programs, flow specs, and
LLM service now use Effect-native boundaries, schema codecs, scoped
cleanup, and
S.TaggedErrorClass.make(...)errors. - CLI commands now run Effect programs at the command boundary, wrap socket
lifecycle with
Effect.acquireUseRelease, encode JSON through Effect Schema, and write output withoutconsole.log. - MCP Effect server now loads env/config through
Config, wraps gateway calls withEffect.tryPromise, constructs schema classes with.make, and uses tagged errors. - MCP stdio compatibility server keeps
createMcpServerandrun, but uses Effect callbacks/tryPromise/schema encoding internally.run()usesManagedRuntime;runMain()usesNodeRuntime.runMain. - Flow stateful service launch sites now pass an explicit
Context.Contextinto the base processor runtime instead of hiding requirements behind assertions.
- Base messaging, NATS backend, producer, consumer, subscriber,
request/response, runtime factories, processor programs, flow specs, and
LLM service now use Effect-native boundaries, schema codecs, scoped
cleanup, and
- Verification:
cd ts && bun run checkcd ts && bun run testcd ts && bun run buildgit diff --check
2026-06-02: ConfigService Ref-Backed State Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/flow/src/config/service.tsnow models runtime state as aSynchronizedRef<ConfigServiceState>instead of adding mutablestore,version, consumer, and producer fields onto the processor object.- Config operations have Effect-returning handlers with Promise facades only on the exported compatibility methods.
- Request narrowing now uses
effect/Predicaterather than request-record type assertions. - Persistence remains schema-backed and now reads/writes snapshots from the ref-backed state.
- The consume loop now uses
Effect.whileLoop; the remainingconsumer.receive(2000)call is a pubsub boundary for this service. - Service startup now exposes
runMain()throughNodeRuntime.runMain. The legacyrun()Promise facade usesManagedRuntime, andts/scripts/run-config.tsdelegates directly torunMain()instead of owning its own catch/process-exit wrapper. - Config-service tests cover tagged invalid mutation errors, workspace persistence, legacy load, concurrent ref-backed mutations, and push publishing from the stored producer handle.
- Verification:
bun run --cwd ts/packages/flow buildbun run --cwd ts/packages/flow testcd ts && bun run checkcd ts && bun run buildcd ts && bun run testgit diff --checkgit diff --check
2026-06-02: RAG And Agent Requestor Bridge Slice
- Status: migrated, root-verified, committed, and pushed.
- Completed:
ts/packages/flow/src/retrieval/graph-rag.tsandts/packages/flow/src/retrieval/document-rag.tsnow acceptEffectRequestResponseclients directly. The engines no longer adapt Effect requestors back to Promise requestors and then wrap those calls inEffect.tryPromise.ts/packages/flow/src/retrieval/graph-rag-service.tsandts/packages/flow/src/retrieval/document-rag-service.tsnow pass native flow requestors directly into the engines.ts/packages/flow/src/agent/react/tools.tsnow acceptsEffectRequestResponseclients directly for graph RAG, document RAG, triples, and MCP tool calls. Tool input narrowing uses Schema andeffect/Predicaterather than local request/response type assertions.ts/packages/flow/src/agent/react/service.tswires default and configured tools with native Effect requestors instead oftoPromiseRequestor.- Graph RAG, document RAG, and agent service startup now expose
runMain()throughNodeRuntime.runMain; their legacyrun()Promise facades useManagedRuntime. ts/scripts/run-graph-rag.ts,ts/scripts/run-document-rag.ts, andts/scripts/run-agent.tsnow delegate torunMain().
- Verification:
bun run --cwd ts/packages/flow buildbun run --cwd ts/packages/flow testcd ts && bun run checkcd ts && bun run buildcd ts && bun run test
2026-06-02: KnowledgeCore Ref-Backed State Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/flow/src/cores/service.tsnow exposes a typedKnowledgeCoreServiceinstead ofAsyncProcessorRuntime & Record<string, any>.- Runtime state now lives in
SynchronizedRef<KnowledgeCoreServiceState>withkgCores,deCores, the request consumer, and response producer. - Knowledge operations now have Effect-returning handlers with Promise facades only on exported compatibility methods.
- Persistence now decodes legacy and current snapshot shapes with Effect
Schema and encodes JSON through Schema rather than raw
JSON.parse/JSON.stringifyplus assertions. - The consume loop now uses
Effect.whileLoop; the remainingconsumer.receive(2000)call is a pubsub boundary for this service. - The service exposes
runMain()throughNodeRuntime.runMain; legacyrun()usesManagedRuntime, andts/scripts/run-knowledge.tsdelegates torunMain(). ts/packages/base/src/schema/messages.tsnow models legacy hyphenated knowledge request/response aliases so the service can preserve the wire shape without response type assertions.- New knowledge-core tests cover ref-backed mutation, graph embedding alias responses, concurrent state updates, and legacy persistence loading.
- Verification:
bun run --cwd ts/packages/base buildbun run --cwd ts/packages/flow buildbun run --cwd ts/packages/flow testcd ts && bun run checkcd ts && bun run buildcd ts && bun run test
2026-06-02: Flow Manager And Librarian Runtime Normalization
- Status: migrated and root-verified.
- Completed:
ts/packages/flow/src/flow-manager/service.tsandts/packages/flow/src/librarian/service.tsnow exposerunMain()throughNodeRuntime.runMain.- Their legacy
run()Promise facades now useManagedRuntimeinstead of directly owningEffect.runPromise. ts/scripts/run-flow-manager.tsandts/scripts/run-librarian.tsnow delegate torunMain()instead of wrapping startup with local.catch(console.error/process.exit)handlers.
- Verification:
bun run --cwd ts/packages/flow buildcd ts && bun run checkcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: FlowManager Ref-Backed State Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/flow/src/flow-manager/service.tsnow exposes a typedFlowManagerServiceinstead ofAsyncProcessorRuntime & Record<string, any>.- Runtime state now lives in
SynchronizedRef<FlowManagerServiceState>withflows,blueprints, the request consumer, response producer, and config request client. - Flow operations now have Effect-returning handlers with Promise facades only on exported compatibility methods.
- Blueprint config loading now narrows runtime values before constructing
Blueprintrecords, replacing the priorparsed as Blueprintshortcut. start-flowandstop-flowmutate the flow map throughSynchronizedRef.modifyEffect, making duplicate checks and map updates atomic.- The consume loop now uses
Effect.whileLoop; the remainingconsumer.receive(2000)call is a pubsub boundary for this service. - New flow-manager tests cover tagged errors, ref-backed flow mutation, config push/delete requests, blueprint narrowing, duplicate concurrent starts, and message-level flow-error responses.
- Verification:
bun run --cwd ts/packages/flow test -- src/__tests__/flow-manager-service.test.tsbun run --cwd ts/packages/flow buildbun run --cwd ts/packages/flow testcd ts && bun run checkcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: Librarian Schema And Assertion Cleanup Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/base/src/schema/messages.tsnow models librarian upload and stream request/response fields directly, instead of requiring service-sideas LibrarianResponsecasts for the existing wire protocol.ts/packages/flow/src/librarian/service.tsnow decodes persisted librarian state through a concreteS.fromJsonStringschema instead of a generic JSON decode plusas A.- Document metadata
metadatatriples now narrow through Schema decoding withOptionbefore being included in normalized metadata. - Upload, stream, and complete-upload request/response constructors now rely on the schema-modeled fields instead of local type assertions.
- New librarian tests cover modeled upload fields, concrete persisted-state loading, and schema-backed metadata triple normalization.
- Remaining:
- Resolved by the typed runtime loop and ref-backed state slices below.
- Verification:
bun run --cwd ts/packages/base buildbun run --cwd ts/packages/flow buildbun run --cwd ts/packages/flow test -- src/__tests__/librarian-service.test.tsbun run --cwd ts/packages/flow testcd ts && bun run checkcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: Librarian Tagged Operation Helper Slice
- Status: migrated and root-verified.
- Completed:
- Removed the librarian
throwLibrarianServiceErrorhelper. get-document-metadata,list-children,upload-chunk,get-upload-status, andabort-uploadnow dispatch through local Effect-returning helpers that fail withLibrarianServiceError.- Compatibility methods for those operations now return Promise facades
backed by
Effect.runPromise. - The librarian tests now await the Promise compatibility facade for upload status.
- Removed the librarian
- Remaining:
- Resolved by the typed runtime loop and ref-backed state slices below.
- Verification:
bun run --cwd ts/packages/flow test -- src/__tests__/librarian-service.test.tsbun run --cwd ts/packages/flow buildcd ts && bun run checkbun run --cwd ts/packages/flow testcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: Librarian Typed Runtime Loop Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/flow/src/librarian/service.tsnow exposes a typedLibrarianServiceinterface instead ofAsyncProcessorRuntime & Record<string, any>.- Service construction now uses
makeAsyncProcessor<LibrarianServiceError>withrunEffect; the old method-bagrunoverride andas LibrarianServicecast are gone. - The librarian startup poller now uses
Effect.whileLoop. - The local operation helpers retrieve the initialized service through an Effect gate rather than closing over an unsafe partially built value.
- Remaining:
- Resolved by the ref-backed state slice below.
- Verification:
bun run --cwd ts/packages/flow buildcd ts && bun run checkbun run --cwd ts/packages/flow testcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: Librarian Ref-Backed State Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/flow/src/librarian/service.tsnow stores documents, processing records, upload sessions, collection manager, and pubsub handles inSynchronizedRef<LibrarianServiceState>.- Document, processing, upload, collection, persistence, load, and stop paths now read snapshots or mutate cloned maps/managers through the ref instead of writing fields on the service object.
- Upload chunk updates clone nested
UploadSession.chunksbefore replacing the upload map entry, avoiding mutable nested state hidden behind the ref. - Librarian response producers and consumers are read/nullified through ref-backed handles.
- Verification:
bun run --cwd ts/packages/flow buildbun run --cwd ts/packages/flow test -- src/__tests__/librarian-service.test.tscd ts && bun run checkbun run --cwd ts/packages/flow testcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: Client RPC Managed Runtime Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/client/src/socket/effect-rpc-client.tsnow builds oneManagedRuntimefrom the RPC client layer instead of manually creating aScope, building the layer, and callingEffect.runPromisefor every operation.- RPC dispatch and stream dispatch continue to expose the existing
Promise-returning
EffectRpcClientfacade, but they run through the managed runtime and close withruntime.dispose(). - The Effect RPC socket path now consumes
Socket.layerWebSocketConstructorGlobalinstead of a duplicate local WebSocket constructor layer. - Dispatch payload construction now uses
DispatchPayload.make(...)so schema classes are not instantiated withnew. - Client socket logging and timestamp creation now use Effect
LoggerandClockinstead of direct console andDate.now()calls in the touched surface.
- Verification:
bun run --cwd ts/packages/client buildcd ts && bun run checkbun run --cwd ts/packages/client testcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: Client WebSocket Adapter Error Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/client/src/socket/websocket-adapter.tsnow models host fallback failures withWebSocketAdapterErrorviaS.TaggedErrorClass.- Synchronous
getWebSocketConstructor()andgetRandomValues()facades keep their public signatures while usingResult.tryinstead of localtry/catchblocks. - Runtime predicates now narrow WebSocket constructor modules and crypto modules without the previous constructor/result type assertions.
- New adapter tests cover global WebSocket selection, optional
wsfallback, global crypto, typed crypto failure, and typed adapter errors.
- Verification:
bun run --cwd ts/packages/client buildbun run --cwd ts/packages/client test -- src/__tests__/websocket-adapter.test.tsbun run --cwd ts/packages/client testcd ts && bun run checkcd ts && bun run buildcd ts && bun run testgit diff --checkgit diff --check
2026-06-02: Client Socket Tagged Error And JSON Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/client/src/socket/trustgraph-socket.tsnow models socket API failures withTrustGraphSocketErrorviaS.TaggedErrorClass.- Flow/blueprint JSON response parsing now uses Schema decoding through
S.UnknownFromJsonStringinstead of rawJSON.parse. - Token-cost config JSON keeps the previous invalid-string fallback behavior while decoding through Schema/Option.
- Connection-state listener isolation now uses
Result.tryand typed socket errors instead of a localtry/catch. - Flow start, row embeddings, collection update, and response-error
failures now reject with tagged socket errors instead of normal
Error. - Flow API tests cover invalid JSON and response-error rejections.
- Verification:
bun run --cwd ts/packages/client buildbun run --cwd ts/packages/client test -- src/__tests__/flows-api.test.tscd ts && bun run checkbun run --cwd ts/packages/client testcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: Client Newable Factory Compatibility Decision
- Status: documented no-op for the current loop.
- Evidence:
ts/packages/workbench/src/atoms/workbench.tsconstructsnew BaseApi(...).ts/packages/client/src/__tests__/flows-api.test.tsconstructsnew FlowsApi(...), and sibling API facades expose the same constructor shape.EffectRpcClientandBaseApialso preserve callable factory exports for compatibility with the vendored TrustGraph client shape.
- Decision:
- The remaining
newableFactory(... ) as unknown as NewableFactory<...>assertions in client socket files are TypeScript compatibility boundaries, not Effect error/requirement channel assertions and not replacements for an Effect primitive. - Removing them safely requires a deliberate public API redesign or explicit class implementations for every API facade, not a local Effect-native rewrite.
- The remaining
- Verification:
- Current client/root verification from the tagged error slice covers this no-op decision.
2026-06-02: Service Entrypoint Runtime Slice
- Status: migrated and root-verified.
- Completed:
- Remaining flow service
run(): Promise<void>program facades now useManagedRuntime.make(Layer.empty)instead of directEffect.runPromise(program). - Remaining flow service modules now expose
runMain()throughNodeRuntime.runMain(program). - Local
ts/scripts/run-*launchers for gateway, prompt, chunker, extractor, PDF decoder, embeddings, triples, graph/document embeddings, text-completion providers, and MCP tool service now delegate directly torunMain(). - Direct
Effect.runPromise(program)matches ints/packages/flow/srcare clean. RemainingEffect.runPromisematches are callback/Promise compatibility boundaries for later slices.
- Remaining flow service
- Verification:
bun run --cwd ts/packages/flow buildgit diff --checkcd ts && bun run checkbun run --cwd ts/packages/flow testcd ts && bun run buildcd ts && bun run test
2026-06-02: Base Processor Compatibility Runtime Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/base/src/processor/async-processor.tsnow uses aManagedRuntimefor Promise compatibility methods, signal-shutdown execution, and legacyAsyncProcessor.launch.ts/packages/base/src/processor/flow.tsnow owns a per-flowManagedRuntimeforstart,stop,runInCompatibilityScope, and Promise resource facades.ts/packages/base/src/processor/flow-processor.tsnow uses aManagedRuntimefor the publicstart(context)facade instead of a localEffect.runPromiseWithrunner.ts/packages/base/src/spec/parameter-spec.tsnow routes legacyaddthroughflow.runInCompatibilityScope(...), matching the other specs.- Subagent checks confirmed
NodeRuntimeis process-entrypoint-only here;@trustgraph/baseshould not add an@effect/platform-nodedependency for these compatibility facades.
- Remaining:
- Constructor
as unknown asshims in base processors preserve callable-plus-newable public exports and are compatibility boundaries for this loop. - Typed string lookup casts in
Flowneed a real typed-spec/key redesign;HashMap/MutableHashMapalone cannot inferTfrom a bare string.
- Constructor
- Verification:
bun run --cwd ts/packages/base buildbun run --cwd ts/packages/base testcd ts && bun run checkgit diff --checkcd ts && bun run buildcd ts && bun run test
2026-06-02: Base Flow Definition Schema Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/base/src/processor/flow-processor.tsnow validatesconfig.flowswith Effect Schema instead of localPredicate/object/string-record guards.- Invalid flow definition payloads still log/skip and preserve the existing config-handler and acknowledgement behavior.
ts/packages/base/src/__tests__/flow-processor-runtime.test.tsnow covers an invalid nested flow definition that is acknowledged without starting resources.
- Verification:
bun run --cwd ts/packages/base test -- src/__tests__/flow-processor-runtime.test.tsbun run --cwd ts/packages/base buildcd ts && bun run checkcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: Text Completion Stream Sentinel Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/flow/src/model/text-completion/{ollama,openai,mistral,azure-openai,claude,openai-compatible}.tsnow return theStream.unfoldend sentinel withEffect.as(Effect.void, undefined).- Removed six
Effect.void as Effect.Effect<undefined>assertions without replacing them withEffect.succeed(undefined), which@effect/tsgoflags as a diagnostic.
- Verification:
bun run --cwd ts/packages/flow buildcd ts && bun run checkbun run --cwd ts/packages/flow testcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: Text Completion Generator Boundary Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/flow/src/model/text-completion/common.tsnow rejects fallbackAsyncGenerator.throw(...)calls with the mapped tagged provider error directly instead of runningEffect.fail(...)throughEffect.runPromise.- The custom generator object no longer uses
as AsyncGenerator,as Promise<IteratorResult<LlmChunk>>, oras LlmChunkassertions. - Added a focused unit test for fallback throw mapping.
- Verification:
bun run --cwd ts/packages/flow test -- src/__tests__/text-completion-common.test.tsbun run --cwd ts/packages/flow buildcd ts && bun run checkbun run --cwd ts/packages/flow testcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: Text Completion Provider Status Narrowing Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/flow/src/model/text-completion/common.tsnow useseffect/Predicatenarrowing for providerstatus/statusCodeinspection instead of local record assertions.ts/packages/flow/src/__tests__/text-completion-common.test.tscovers both rate-limit status fields.
- Verification:
bun run --cwd ts/packages/flow test -- src/__tests__/text-completion-common.test.tsbun run --cwd ts/packages/flow buildcd ts && bun run checkbun run --cwd ts/packages/flow testcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: Base Parameter Spec Accessor Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/base/src/spec/parameter-spec.tsnow modelsParameterSpec<T>with an Effect Schema codec. Legacy parameter specs default toS.Unknown, preserving name-based registration while making typed access schema-backed.ts/packages/base/src/processor/flow.tsnow exposesflow.parameterEffect(spec)andflow.parameter(spec)for inferred, Schema-decoded parameter values. String lookup remains available as anunknowncompatibility escape instead of a caller-chosen generic type.- Parameter schema failures now fail with the tagged
FlowParameterDecodeErrorrather than a normalError. ts/packages/flow/src/chunking/service.tsnow declares numeric chunk parameters once and retrieves them through the typed spec-object accessor.ts/packages/base/src/__tests__/flow-spec-runtime.test.tscovers typed parameter decoding, legacy string lookup, missing parameter errors, sync accessor decoding, and schema mismatch errors.
- Remaining:
- Add typed spec-object accessors for producers and requestors so call sites can stop spelling generic string lookups for those registries too.
- Verification:
bun run --cwd ts/packages/base test -- src/__tests__/flow-spec-runtime.test.tsbun run --cwd ts/packages/base buildbun run --cwd ts/packages/flow buildcd ts && bun run checkbun run --cwd ts/packages/base testbun run --cwd ts/packages/flow testcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: Base Producer And Requestor Spec Accessor Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/base/src/spec/producer-spec.tsnow exposesProducerSpec<T>.producerEffect(flow)and stores typed producer handles in a per-spec WeakMap keyed byFlow.ts/packages/base/src/spec/request-response-spec.tsnow exposesRequestResponseSpec<TReq, TRes>.requestorEffect(flow)and stores typed requestor handles in a per-spec WeakMap keyed byFlow.- Spec finalizers remove only the exact handle they registered, avoiding stale finalizers deleting newer registrations for the same flow/spec pair.
ts/packages/base/src/processor/flow.tsnow supportsflow.producerEffect(spec),flow.requestorEffect(spec),flow.producer(spec), andflow.requestor(spec)while keeping string accessors as untyped compatibility escapes.- Base service adapters and flow service handlers now reuse the same hoisted producer/requestor spec object in their spec arrays and handler lookups.
ts/packages/base/src/__tests__/flow-spec-runtime.test.tscovers typed spec-object lookups, duplicate spec identity failures, and scoped finalizer cleanup for producer and requestor handles.
- Remaining:
- Bare string
Flowproducer/requestor accessors remain compatibility escapes for external/legacy callers, but new Effect service code should use spec objects.
- Bare string
- Verification:
bun run --cwd ts/packages/base test -- src/__tests__/flow-spec-runtime.test.tsbun run --cwd ts/packages/base buildbun run --cwd ts/packages/flow buildbun run --cwd ts/packages/base testbun run --cwd ts/packages/flow testcd ts && bun run checkcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: Native PubSub Boundary Slice
- Status: migrated and package-verified.
- Completed:
- Confirmed Effect's native
PubSubmodule is an in-process asynchronous hub with scoped subscriptions, not a NATS/Pulsar-compatible broker boundary. - Kept TrustGraph's
PubSubBackendandPubSubservice as the broker adapter layer because it owns topics, broker producers/consumers, acknowledgement, schema codecs, and backend lifecycle. - Removed the unused legacy
ts/packages/base/src/messaging/subscriber.tsimplementation, which duplicated in-process async queue/fanout behavior. - Removed the corresponding
makeAsyncQueue,makeSubscriber,Subscriber, andAsyncQueuebarrel exports fromts/packages/base/src/messaging/index.ts.
- Confirmed Effect's native
- Remaining:
- Future in-process fanout or request-streaming code should use
effect/PubSub,Queue,Stream.fromPubSub, orChannel.fromPubSubrather than adding another local async queue implementation. - Do not replace
PubSubBackendwitheffect/PubSubunless the code path is explicitly local-only and does not need broker semantics.
- Future in-process fanout or request-streaming code should use
- Verification:
bun run --cwd ts/packages/base buildbun run --cwd ts/packages/base testcd ts && bun run check
2026-06-02: Gateway Streaming Callback Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/flow/src/gateway/dispatch/manager.tsnow exposesdispatchGlobalServiceStreamingEffectanddispatchFlowServiceStreamingEffectso Effect callers can handle stream chunks without Promise callback re-entry.- The existing Promise-returning streaming methods remain as compatibility
facades and wrap responders with
Effect.tryPromise. ts/packages/flow/src/gateway/rpc-server.tsnow writes stream chunks into the RPC queue through the dispatcher Effect path, removing the priorEffect.contextplusEffect.runPromiseWith(context)bridge.ts/packages/client/src/socket/effect-rpc-client.tsnow usesStream.runForEachWhilefor early stream termination instead of throwing a syntheticStopStreamingtagged error.- Gateway dispatcher tests now exercise both the Promise compatibility streaming path and the Effect-native responder path.
- Remaining:
ts/packages/flow/src/gateway/rpc-protocol.tsremains a Fastify socket compatibility bridge, not a direct replacement target for Effect RPC server layers yet.
- Verification:
bun run --cwd ts/packages/flow buildbun run --cwd ts/packages/client buildbunx --bun vitest run src/__tests__/gateway-dispatcher.test.tsbunx --bun vitest run src/__tests__/rpc-timeout.test.tscd ts && bun run checkcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: Client Streaming Facade Normalization Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/client/src/socket/trustgraph-socket.tsnow decodes the legacy streaming envelope with Schema before service-specific callback handling.- Streaming payload reads now use
effect/Predicateproperty narrowing helpers instead of repeated response-wrapper assertions. - Graph RAG, document RAG, text completion, prompt, agent, and document
stream callbacks now use a shared
streamComplete(...)helper. The RPCDispatchStreamChunk.completebit is the default transport completion source, with legacy service markers preserved for public compatibility. - Explainability triples are decoded through a recursive Schema instead of
as Triple[]. - The focused client test now proves normalized
DispatchStreamChunkcompletion flows throughgraphRagStreamingand final metadata.
- Verification:
bunx --bun vitest run src/__tests__/rpc-timeout.test.tsbun run --cwd ts/packages/client buildcd ts && bun run check:tsgobun run --cwd ts/packages/client testcd ts && bun run checkcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: Ollama Embeddings Effectful Layer Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/flow/src/embeddings/ollama.tsnow exposesmakeOllamaEmbeddingsEffectfor effectful config loading and service construction.OllamaEmbeddingsLivenow usesLayer.effectand maps config/load failures intoEmbeddingsErrorinstead of preconstructing the service withLayer.succeed.- The direct
makeOllamaEmbeddings(config)factory remains as a compatibility facade, while the canonicalprogramentrypoint preserves the provider tagged error channel. - Ollama response JSON parsing no longer uses a Promise type assertion.
- The focused embeddings tests now cover both direct factory use and the
effectful
OllamaEmbeddingsLivelayer.
- Verification:
bunx --bun vitest run src/__tests__/ollama-embeddings.test.tsbun run --cwd ts/packages/flow buildcd ts && bun run check:tsgobun run --cwd ts/packages/flow testcd ts && bun run checkcd ts && bun run buildcd ts && bun run test
2026-06-02: FalkorDB Scoped Client Lifecycle Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/flow/src/storage/triples/falkordb.tsandts/packages/flow/src/query/triples/falkordb.tsnow model FalkorDB client acquisition withEffect.acquireRelease.- FalkorDB Live layers now use
Layer.effectand own Redis client disconnect finalizers through the layer scope. - Direct Promise compatibility factories and direct service factories now
bracket each operation with scoped acquisition instead of hiding mutable
Effect.cachedconnection slots. - Legacy
makeTriplesStoreServiceandmakeTriplesQueryServiceprovider hooks now acquire scoped FalkorDB services and map acquisition failures toProcessorLifecycleError; modernprogramentrypoints preserve the FalkorDB tagged layer error type. - FalkorDB query row field extraction now uses
effect/Predicatenarrowing instead of record/string type assertions. - New lifecycle tests use fake clients/graphs to prove connect on acquire and disconnect on scope close for both triples store and triples query.
- Verification:
bunx --bun vitest run src/__tests__/falkordb-lifecycle.test.tsbun run --cwd ts/packages/flow buildcd ts && bun run checkbun run --cwd ts/packages/flow testcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: Qdrant Config, Schema, And Fakeable Construction Slice
- Status: migrated and root-verified.
- Completed:
- Added
ts/packages/flow/src/qdrant/client.tsas the narrow fakeable Qdrant surface used by graph/doc embedding store/query modules. - Graph and document Qdrant store/query constructors now create clients
through
Effect.try, load Qdrant config in Effect, and map config/client failures into their existingS.TaggedErrorClasserrors. - Graph and document query payload extraction now uses
Schema.decodeUnknownEffect(...).pipe(Effect.option)and skips malformed Qdrant payloads without type assertions. - Qdrant graph/doc query Live layers and graph store Live layer now use
Layer.effectinstead of preconstructing services withLayer.succeed. - Legacy graph store/query/doc query processor providers now acquire Qdrant
services with named
Effect.fnproviders and map startup failures toProcessorLifecycleError. - The installed Qdrant client still has no public close/disconnect method,
so no
Effect.acquireReleasefinalizer was added for Qdrant.
- Added
- Verification:
bunx --bun vitest run src/__tests__/qdrant-embeddings.test.tsbun run --cwd ts/packages/flow buildcd ts && bun run check:tsgobun run --cwd ts/packages/flow testcd ts && bun run checkcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: Text Completion Provider Stream Helper Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/flow/src/model/text-completion/common.tsnow exposesstreamTextCompletionChunks, an Effect-native helper built onStream.fromAsyncIterable,Ref,Stream.filterMap/Result, and a final token chunk append.- OpenAI, Azure OpenAI, OpenAI-compatible, Mistral, Ollama, and Claude
streaming providers now share the helper instead of each hand-rolling
Stream.unfoldplusiterator.nextloops. - Mistral non-streaming and streaming content normalization now uses
effect/PredicateandOptionnarrowing throughtextFromContent, removing the priorcontent as stringassertion. - The helper uses the installed Effect beta's
Option.fromNullishOrand Result-shapedStream.filterMapAPI, verified bycheck:tsgo. ts/packages/flow/src/__tests__/text-completion-common.test.tscovers token accumulation/final chunk emission and non-string content narrowing.
- Remaining:
- Full Effect AI provider swaps still need parity tests first; current OpenAI and Azure behavior is Chat Completions based, no installed Azure/Mistral/Ollama Effect AI provider exists, and Anthropic needs explicit text/token/streaming/rate-limit parity coverage before replacement.
- Verification:
bunx --bun vitest run src/__tests__/text-completion-common.test.tscd ts && bun run check:tsgobun run --cwd ts/packages/flow buildbun run --cwd ts/packages/flow testcd ts && bun run checkcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: Request-Response Queue Stream Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/base/src/messaging/runtime.tsnow waits for accepted request-response replies by converting the responseQueueto aStream.fromQueue.- Recipient filtering now uses
Stream.filterMapEffectwithResultto skip partial responses until the recipient returnstrue. Stream.runHeadreplaces the priorwhile (true)/Queue.takeloop and preserves the existing timeout behavior around request-response calls.ts/packages/base/src/__tests__/messaging-runtime.test.tsnow covers recipient filtering across partial and final responses.
- Remaining:
- The two remaining production
while (matches areagent/react/parser.tsline-buffer parsing andcli/src/commands/util.tsCommander parent traversal; neither is async polling or resource ownership.
- The two remaining production
- Verification:
bunx --bun vitest run src/__tests__/messaging-runtime.test.tsbun run --cwd ts/packages/base buildbun run --cwd ts/packages/base testcd ts && bun run checkcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: Gateway RPC WebSocket Cause Handling Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/flow/src/gateway/server.tsnow handles RPC WebSocket program defects and interruptions inside the Effect pipeline withEffect.sandbox,Effect.catch, andCause.pretty.- The previous Promise
.catch(...)aroundEffect.runPromise(...), plus the nestedEffect.runPromiseused only for logging and socket close, is removed. - The outer
Effect.runPromiseremains as the Fastify WebSocket host boundary.
- Verification:
cd ts && bun run check:tsgobun run --cwd ts/packages/flow buildbun run --cwd ts/packages/flow testcd ts && bun run checkcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: Client RPC Acquisition Cause Tap Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/client/src/socket/effect-rpc-client.tsnow observes runtime/client acquisition failures withEffect.tapCauseandCause.pretty.- Removed the Promise
.catch(...)that only updated local connection state afterruntime.runPromise(TrustGraphRpcClientService). - Removed the local
errorMessagehelper and its message-field assertion. - Public
dispatch,dispatchStream, andclosePromise facades remain compatibility boundaries.
- Verification:
cd ts && bun run check:tsgobun run --cwd ts/packages/client buildbun run --cwd ts/packages/client testcd ts && bun run checkcd ts && bun run buildcd ts && bun run testgit diff --check
2026-06-02: Client Socket Close Effect Boundary Slice
- Status: migrated and root-verified.
- Completed:
ts/packages/client/src/socket/trustgraph-socket.tsnow wrapsrpc.close()withEffect.tryPromiseinside the publicclose(): voidfacade.- Close failures are mapped to the existing tagged
TrustGraphSocketErrorshape and logged throughEffect.catchinstead of a Promise.catch. - The remaining client socket Promise
.catchmatches are streaming callback compatibility bridges that route failures to legacyonErrorcallbacks.
- Verification:
cd ts && bun run check:tsgobun run --cwd ts/packages/client buildbun run --cwd ts/packages/client testcd ts && bun run checkcd ts && bun run buildcd ts && bun run testgit diff --check
Subagent Findings To Preserve
- MCP/workbench:
- Make the Effect MCP server the canonical implementation. The old stdio server should remain only as compatibility while parity is needed.
- Workbench BaseApi atoms can move toward
AtomRpcorAtomHttpApiafter the client API is less Promise-first. - MCP env is now Config-backed; continue that policy for future MCP settings.
- Flow stateful services:
- Config service, KnowledgeCore service, FlowManager, and Librarian ref-backed state slices are complete. Follow-up service work should focus on scoped layers, schedules where polling semantics allow, and managed persistence providers rather than direct mutable service fields.
- Flow service startup facades now consistently use
ManagedRuntime, and local scripts should delegate torunMain()instead of adding local.catch(console.error/process.exit)wrappers. - Persistence IO should move toward
FileSystemorKeyValueStorewhere the installed beta has the needed provider surface.
- Base messaging/processors:
- Processor/flow Promise compatibility now uses
ManagedRuntime; keepNodeRuntimeonly for processrunMain()entrypoints. - Subscriber queues/maps and dynamic flow state should continue moving
toward
Queue,Deferred,SynchronizedRef,Schedule, and scoped layers. - The legacy
messaging/subscriber.tsasync queue/fanout implementation is removed. Use nativeeffect/PubSubfor future in-process fanout, while keepingPubSubBackendfor broker-backed messaging. - Existing constructor shims preserve callable-plus-newable public exports; removing them needs a public API split or real class redesign.
- Typed string registries in
Flownow have Schema-backed parameter specs and typed producer/requestor spec-object accessors. New service handlers should hoist spec objects and use those accessors; bare string accessors remain compatibility escapes.
- Processor/flow Promise compatibility now uses
- Gateway/client:
EffectRpcClientnow owns its socket/RPC layer withManagedRuntime. Socket errors/JSON parsing now use tagged errors and Schema decoding. The remaining clientnewableFactoryassertions are documented as public API compatibility boundaries for this loop.- Gateway
DispatchStreamnow uses Effect-native dispatcher streaming callbacks instead of nestedEffect.runPromiseWith, and client streaming facade callbacks now decode the legacy envelope through Schema before applying service-specific public callback semantics. - Do not make
gateway/rpc-protocol.tsthe next cleanup target: it is a Fastify socket compatibility bridge while the public Effect RPC server layers require SocketServer or Effect HTTP routing. - WebSocket adapter host fallbacks now use
Result.tryand tagged adapter errors while preserving sync exports.
- RAG/providers/storage:
- RAG and agent requestor bridges are complete:
toPromiseRequestorhas no remainingts/packagesmatches. - Provider SDKs and storage clients should become managed resources where they have meaningful lifecycle.
- Ollama embeddings now has an effectful canonical layer. There is no installed Effect AI Ollama provider package, so future Ollama work should focus on local Effect wrappers/adapters rather than provider replacement.
- Full text-completion provider swaps need parity tests first. OpenAI and
Azure currently use Chat Completions while
@effect/ai-openaiis Responses API oriented, and no installed Azure/Mistral/Ollama Effect AI provider is available. Anthropic is the closest direct provider swap, but must preserve text, token counts, streaming final usage, and rate-limit mapping. - FalkorDB scoped lifecycle is complete for triples query/store. Use the fakeable client/graph factory pattern from that slice for future storage client tests.
- Qdrant config/schema/fakeability is complete for graph/doc embedding
store/query modules. Qdrant still has no close/disconnect surface in the
installed client, so do not reopen it as an
acquireReleaseclose slice without new SDK evidence. - Shared text-completion stream iteration and the Mistral content assertion are complete. The remaining provider-layer item is parity-backed Effect AI adapter work, not a direct SDK swap.
- RAG and agent requestor bridges are complete:
Ranked Findings
P2: Provider Layer And Effect AI Cleanup
- TrustGraph evidence:
ts/packages/flow/src/model/text-completion/*.ts
- Effect primitives:
Config,ConfigProvider,Metric,Logger,effect/unstable/ai/LanguageModel,effect/unstable/ai/EmbeddingModel, Effect AI OpenAI/Anthropic provider layers.
- Rewrite shape:
- Add an Effect AI adapter layer beside the current
LlmProvidercontract before flipping any public provider interface. - Use Effect AI provider layers only where parity is proven.
- Keep OpenAI-compatible/Azure-compatible behavior behind parity tests because current code uses chat-completions style APIs while the Effect OpenAI language model is Responses API backed.
- Add an Effect AI adapter layer beside the current
- Tests:
- Provider parity for
LlmResult, final streaming chunk token counts, 429 mapping, missing-token config failures, and OpenAI-compatible local-server behavior.
- Provider parity for
P2: Canonicalize MCP Around The Effect Server
- Status:
- First blocker slice complete: MCP now builds under strict tsgo and the stdio server has an Effect-backed compatibility implementation.
- Remaining shape:
- Decide whether the old SDK/Zod stdio compatibility surface should stay as a wrapper or be removed.
- Add parity tests before deleting any public entry point.
- Tests:
cd ts && bun run --cwd packages/mcp build- Root
cd ts && bun run check
P2: Tighten Workbench Platform And Reactivity Usage
- TrustGraph evidence:
ts/packages/workbench/src/atoms/workbench.ts- Remaining direct browser state includes
localStorageand DOM theme inspection.
- Effect primitives:
BrowserKeyValueStore.layerLocalStorage,BrowserKeyValueStore.layerSessionStorage,BrowserHttpClient,Clipboard,AtomRpc,AtomHttpApi,AtomRegistry,AsyncResult,Reactivity.
- Rewrite shape:
- Leave workbench out of the next backend/runtime rewrite wave.
- Move persistent UI state through browser platform services later.
- Tests:
cd ts && bun run workbench:qa
Recommended PR Order
- Provider layer and Effect AI cleanup.
- MCP parity/deletion decision and workbench platform polish.
No-Op Rules
Do not flag these as rewrite blockers without additional proof:
- Promise-returning CLI actions, MCP SDK callbacks, client compatibility methods, and Fastify route handlers at true external boundaries. Boundary code still must map failures into typed errors or wire errors.
try/catchblocks at host/tool boundaries only when the catch maps into a typed error or a wire-contract 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. - Plain synchronous loops for parsing or tree traversal are not Effect migration blockers unless they hide async polling, resource ownership, or callback scheduling.
- JSON stringification in tests or wire-contract fixtures. Production JSON encode/decode should prefer schema codecs when the encoded form can be preserved.
- Client
newableFactoryassertions that preserve vendored callable-plus-new API facades are compatibility boundaries unless the public constructor API is intentionally redesigned. - Base
AsyncProcessor,Flow, andFlowProcessorcallable-plus-newable export assertions are compatibility boundaries unless the public constructor API is intentionally redesigned. - TrustGraph
PubSubBackend/ backendPubSubservice is a broker adapter boundary for NATS/Pulsar-style topics, acknowledgement, schema codecs, and backend lifecycle. Effect's nativePubSubcan replace in-process fanout helpers, but not the distributed broker abstraction by itself. ts/packages/flow/src/gateway/rpc-protocol.tsis a Fastify socket compatibility bridge. Do not flag its internal connection maps/sets as a standalone replacement target until the gateway is ready to move onto Effect SocketServer or Effect HTTP routing.
Acceptance For Final Loop Completion
The overall playbook loop is complete only when:
- All remaining playbook signal matches are migrated or documented as no-op external-boundary cases with concrete evidence.
- No P0/P1/P2 migration item remains in this audit.
cd ts && bun run check,cd ts && bun run build,cd ts && bun run test, andgit diff --checkpass after the final migration slice.