diff --git a/ts/packages/base/src/processor/async-processor.ts b/ts/packages/base/src/processor/async-processor.ts index 1737d0f6..2a988d53 100644 --- a/ts/packages/base/src/processor/async-processor.ts +++ b/ts/packages/base/src/processor/async-processor.ts @@ -77,11 +77,6 @@ export interface AsyncProcessorRuntimeOptions< ) => Effect.Effect; } -interface RegisteredSignalHandler { - readonly signal: NodeJS.Signals; - readonly handler: () => void; -} - export function makeAsyncProcessor< RunError = ProcessorLifecycleError, RunRequirements = never, @@ -94,41 +89,6 @@ export function makeAsyncProcessor< const configHandlers: Array> = []; const shutdownCallbacks: Array<() => Effect.Effect> = []; let running = false; - let signalHandlers: RegisteredSignalHandler[] = []; - - const registerProcessSignalHandlers = (): void => { - if (config.manageProcessSignals === false || signalHandlers.length > 0) { - return; - } - - const shutdown = () => { - Effect.runFork( - Effect.log(`[${config.id}] Shutting down...`).pipe( - Effect.flatMap(() => processor.stop), - Effect.mapError((error) => processorLifecycleError(config.id, "signal-shutdown", error)), - Effect.match({ - onFailure: () => process.exit(1), - onSuccess: () => process.exit(0), - }), - ), - ); - }; - const handlers: RegisteredSignalHandler[] = [ - { signal: "SIGINT", handler: shutdown }, - { signal: "SIGTERM", handler: shutdown }, - ]; - for (const { signal, handler } of handlers) { - process.once(signal, handler); - } - signalHandlers = handlers; - }; - - const unregisterProcessSignalHandlers = (): void => { - for (const { signal, handler } of signalHandlers) { - process.off(signal, handler); - } - signalHandlers = []; - }; const processor: AsyncProcessorRuntime = { config, @@ -152,7 +112,6 @@ export function makeAsyncProcessor< const startProcessor = Effect.fn("trustgraph.processor.start")(function* () { yield* Effect.sync(() => { running = true; - registerProcessSignalHandlers(); }); yield* processor.runEffect; @@ -169,7 +128,6 @@ export function makeAsyncProcessor< const stopProcessor = Effect.fn("trustgraph.processor.stop")(function* () { yield* Effect.sync(() => { running = false; - unregisterProcessSignalHandlers(); }); for (const cb of shutdownCallbacks) { diff --git a/ts/packages/flow/src/agent/mcp-tool/service.ts b/ts/packages/flow/src/agent/mcp-tool/service.ts index 4ff42613..5a2380dd 100644 --- a/ts/packages/flow/src/agent/mcp-tool/service.ts +++ b/ts/packages/flow/src/agent/mcp-tool/service.ts @@ -337,16 +337,13 @@ export const makeMcpToolConfigHandlers = (): ReadonlyArray< export type McpToolService = FlowProcessorRuntime; export function makeMcpToolService(config: ProcessorConfig): McpToolService { - const runtime = Effect.runSync(makeMcpToolRuntime); const service = makeFlowProcessor(config, { specifications: makeMcpToolSpecs(), - provide: (effect) => effect.pipe(Effect.provideService(McpToolRuntime, runtime)), - }); - service.registerConfigHandler((pushedConfig, version) => - onMcpConfig(pushedConfig, version).pipe( - Effect.provideService(McpToolRuntime, runtime), + provide: (effect) => effect.pipe( + Effect.provideServiceEffect(McpToolRuntime, makeMcpToolRuntime), ), - ); + }); + service.registerConfigHandler(onMcpConfig); return service; } diff --git a/ts/packages/flow/src/agent/react/service.ts b/ts/packages/flow/src/agent/react/service.ts index 303fa60b..11601455 100644 --- a/ts/packages/flow/src/agent/react/service.ts +++ b/ts/packages/flow/src/agent/react/service.ts @@ -507,17 +507,13 @@ export const makeAgentConfigHandlers = (): ReadonlyArray< export type AgentService = FlowProcessorRuntime; export function makeAgentService(config: ProcessorConfig): AgentService { - const runtime = Effect.runSync(makeAgentRuntime); const service = makeFlowProcessor(config, { specifications: makeAgentSpecs(), - provide: (effect) => effect.pipe(Effect.provideService(AgentRuntime, runtime)), - }); - service.registerConfigHandler((pushedConfig, version) => - onToolsConfig(pushedConfig, version).pipe( - Effect.provideService(AgentRuntime, runtime), + provide: (effect) => effect.pipe( + Effect.provideServiceEffect(AgentRuntime, makeAgentRuntime), ), - ); - Effect.runSync(Effect.log("[AgentService] Service initialized")); + }); + service.registerConfigHandler(onToolsConfig); return service; } diff --git a/ts/packages/flow/src/chunking/service.ts b/ts/packages/flow/src/chunking/service.ts index 82b256dc..9f2c558c 100644 --- a/ts/packages/flow/src/chunking/service.ts +++ b/ts/packages/flow/src/chunking/service.ts @@ -96,11 +96,9 @@ export const makeChunkingSpecs = (): ReadonlyArray< export type ChunkingService = FlowProcessorRuntime; export function makeChunkingService(config: ProcessorConfig): ChunkingService { - const service = makeFlowProcessor(config, { + return makeFlowProcessor(config, { specifications: makeChunkingSpecs(), }); - Effect.runSync(Effect.log("[ChunkingService] Service initialized")); - return service; } export const ChunkingService = makeChunkingService; diff --git a/ts/packages/flow/src/decoding/pdf-decoder.ts b/ts/packages/flow/src/decoding/pdf-decoder.ts index 526c97cd..d18ef995 100644 --- a/ts/packages/flow/src/decoding/pdf-decoder.ts +++ b/ts/packages/flow/src/decoding/pdf-decoder.ts @@ -237,11 +237,9 @@ export const makePdfDecoderSpecs = (): ReadonlyArray => [ export type PdfDecoderService = FlowProcessorRuntime; export function makePdfDecoderService(config: ProcessorConfig): PdfDecoderService { - const service = makeFlowProcessor(config, { + return makeFlowProcessor(config, { specifications: makePdfDecoderSpecs(), }); - Effect.runSync(Effect.log("[PdfDecoder] Service initialized")); - return service; } export const PdfDecoderService = makePdfDecoderService; diff --git a/ts/packages/flow/src/embeddings/ollama.ts b/ts/packages/flow/src/embeddings/ollama.ts index f763f8be..f77093c2 100644 --- a/ts/packages/flow/src/embeddings/ollama.ts +++ b/ts/packages/flow/src/embeddings/ollama.ts @@ -138,7 +138,11 @@ export const makeOllamaEmbeddingsEffect = Effect.fn("makeOllamaEmbeddingsEffect" }); export function makeOllamaEmbeddings(config: OllamaEmbeddingsConfig): EmbeddingsServiceShape { - return Effect.runSync(makeOllamaEmbeddingsEffect(config)); + return makeOllamaEmbeddingsFromConfig({ + defaultModel: config.model ?? "mxbai-embed-large", + ollamaHost: config.ollamaHost ?? "http://localhost:11434", + fetchImpl: config.fetch ?? globalThis.fetch, + }); } export function OllamaEmbeddingsLive(config: OllamaEmbeddingsConfig): Layer.Layer { diff --git a/ts/packages/flow/src/extract/knowledge-extract.ts b/ts/packages/flow/src/extract/knowledge-extract.ts index 6233bec6..b48f1dca 100644 --- a/ts/packages/flow/src/extract/knowledge-extract.ts +++ b/ts/packages/flow/src/extract/knowledge-extract.ts @@ -30,6 +30,7 @@ import type { Spec, } from "@trustgraph/base"; import { + errorMessage, makeFlowProcessor, makeConsumerSpec, makeProducerSpec, @@ -179,7 +180,7 @@ const onKnowledgeExtractMessage = Effect.fn("KnowledgeExtractService.onMessage") const relationships = yield* extractRelationships(promptClient, llmClient, text).pipe( Effect.catch((error: unknown) => Effect.logError("[KnowledgeExtract] Relationship extraction failed", { - error: error instanceof Error ? error.message : String(error), + error: errorMessage(error), }).pipe(Effect.as(null)), ), ); @@ -233,7 +234,7 @@ const onKnowledgeExtractMessage = Effect.fn("KnowledgeExtractService.onMessage") const definitions = yield* extractDefinitions(promptClient, llmClient, text).pipe( Effect.catch((error: unknown) => Effect.logError("[KnowledgeExtract] Definition extraction failed", { - error: error instanceof Error ? error.message : String(error), + error: errorMessage(error), }).pipe(Effect.as(null)), ), ); @@ -294,11 +295,9 @@ export const makeKnowledgeExtractSpecs = (): ReadonlyArray => [ export type KnowledgeExtractService = FlowProcessorRuntime; export function makeKnowledgeExtractService(config: ProcessorConfig): KnowledgeExtractService { - const service = makeFlowProcessor(config, { + return makeFlowProcessor(config, { specifications: makeKnowledgeExtractSpecs(), }); - Effect.runSync(Effect.log("[KnowledgeExtract] Service initialized")); - return service; } export const KnowledgeExtractService = makeKnowledgeExtractService; @@ -332,9 +331,6 @@ export function parseJsonResponse(raw: string): T | null { if (O.isSome(decoded)) return decoded.value as T; } - Effect.runSync(Effect.logWarning("[KnowledgeExtract] Failed to parse JSON from LLM response", { - response: raw.slice(0, 300), - })); return null; } @@ -343,9 +339,6 @@ function parseRelationshipsResponse(raw: string): ReadonlyArray = Clock.currentTimeMillis.pipe( Effect.map((millis) => Math.floor(millis / 1000)), ); @@ -1504,6 +1514,7 @@ export const LibrarianService = makeLibrarianService; export const program = makeProcessorProgram({ id: "librarian-svc", + loadConfig: loadLibrarianServiceConfig, make: (config) => makeLibrarianService(config), }); diff --git a/ts/packages/flow/src/model/text-completion/azure-openai.ts b/ts/packages/flow/src/model/text-completion/azure-openai.ts index 01555740..8586176a 100644 --- a/ts/packages/flow/src/model/text-completion/azure-openai.ts +++ b/ts/packages/flow/src/model/text-completion/azure-openai.ts @@ -176,7 +176,22 @@ const makeAzureOpenAIProviderFromClient = ( export function makeAzureOpenAIProvider( config: AzureOpenAIProcessorConfig, ): LlmProvider { - return Effect.runSync(makeAzureOpenAIProviderEffect(config)); + const resolved = { + defaultModel: config.model ?? "gpt-4o", + defaultTemperature: config.temperature ?? 0.0, + maxOutput: config.maxOutput ?? 4096, + apiKey: config.apiKey ?? "", + endpoint: config.endpoint ?? "", + apiVersion: config.apiVersion ?? "2024-12-01-preview", + } satisfies ResolvedAzureOpenAIConfig; + return makeAzureOpenAIProviderFromClient( + resolved, + new AzureOpenAI({ + apiKey: resolved.apiKey, + apiVersion: resolved.apiVersion, + endpoint: resolved.endpoint, + }), + ); } export const makeAzureOpenAIProviderEffect = Effect.fn("makeAzureOpenAIProvider")(function*( diff --git a/ts/packages/flow/src/model/text-completion/claude.ts b/ts/packages/flow/src/model/text-completion/claude.ts index 3da2a461..32aac96f 100644 --- a/ts/packages/flow/src/model/text-completion/claude.ts +++ b/ts/packages/flow/src/model/text-completion/claude.ts @@ -16,7 +16,7 @@ import { makeFlowProcessorProgram, makeLlmSpecs, } from "@trustgraph/base"; -import { Effect, Layer, Redacted } from "effect"; +import { Context, Effect, Layer, Redacted } from "effect"; import { FetchHttpClient } from "effect/unstable/http"; import type { TextCompletionConfigError, @@ -69,7 +69,32 @@ const makeClaudeLayer = (apiKey: string) => export function makeClaudeProvider( config: ClaudeProcessorConfig, ): LlmProvider { - return Effect.runSync(Effect.scoped(makeClaudeProviderEffect(config))); + const resolved = { + defaultModel: config.model ?? "claude-sonnet-4-20250514", + defaultTemperature: config.temperature ?? 0.0, + maxOutput: config.maxOutput ?? 8192, + apiKey: config.apiKey ?? "", + } satisfies ResolvedClaudeConfig; + return makeLanguageModelProvider({ + provider: "Claude", + defaultModel: resolved.defaultModel, + defaultTemperature: resolved.defaultTemperature, + context: Context.empty(), + makeLanguageModel: ({ model, temperature }) => + Effect.scoped( + Layer.build(makeClaudeLayer(resolved.apiKey)).pipe( + Effect.flatMap((context) => + AnthropicLanguageModel.make({ + model, + config: { + max_tokens: resolved.maxOutput, + temperature, + }, + }).pipe(Effect.provideContext(context)) + ), + ), + ), + }); } export const makeClaudeProviderEffect = Effect.fn("makeClaudeProvider")(function* ( diff --git a/ts/packages/flow/src/model/text-completion/mistral.ts b/ts/packages/flow/src/model/text-completion/mistral.ts index 8eb3c54f..990039ef 100644 --- a/ts/packages/flow/src/model/text-completion/mistral.ts +++ b/ts/packages/flow/src/model/text-completion/mistral.ts @@ -156,7 +156,16 @@ const makeMistralProviderFromClient = ( export function makeMistralProvider( config: MistralProcessorConfig, ): LlmProvider { - return Effect.runSync(makeMistralProviderEffect(config)); + const resolved = { + defaultModel: config.model ?? "ministral-8b-latest", + defaultTemperature: config.temperature ?? 0.0, + maxOutput: config.maxOutput ?? 4096, + apiKey: config.apiKey ?? "", + } satisfies ResolvedMistralConfig; + return makeMistralProviderFromClient( + resolved, + new Mistral({ apiKey: resolved.apiKey }), + ); } export const makeMistralProviderEffect = Effect.fn("makeMistralProvider")(function*( diff --git a/ts/packages/flow/src/model/text-completion/ollama.ts b/ts/packages/flow/src/model/text-completion/ollama.ts index dbbbb15a..6e4cc604 100644 --- a/ts/packages/flow/src/model/text-completion/ollama.ts +++ b/ts/packages/flow/src/model/text-completion/ollama.ts @@ -132,7 +132,14 @@ const makeOllamaProviderFromClient = ( export function makeOllamaProvider( config: OllamaProcessorConfig, ): LlmProvider { - return Effect.runSync(makeOllamaProviderEffect(config)); + const resolved = { + defaultModel: config.model ?? "qwen2.5:0.5b", + host: config.ollamaUrl ?? "http://localhost:11434", + } satisfies ResolvedOllamaConfig; + return makeOllamaProviderFromClient( + resolved, + new Ollama({ host: resolved.host }), + ); } export const makeOllamaProviderEffect = Effect.fn("makeOllamaProvider")(function*( diff --git a/ts/packages/flow/src/model/text-completion/openai-compatible.ts b/ts/packages/flow/src/model/text-completion/openai-compatible.ts index c9ea316f..d6b0e8e5 100644 --- a/ts/packages/flow/src/model/text-completion/openai-compatible.ts +++ b/ts/packages/flow/src/model/text-completion/openai-compatible.ts @@ -165,7 +165,17 @@ const makeOpenAICompatibleProviderFromClient = ( export function makeOpenAICompatibleProvider( config: OpenAICompatibleProcessorConfig, ): LlmProvider { - return Effect.runSync(makeOpenAICompatibleProviderEffect(config)); + const resolved = { + defaultModel: config.model ?? "default", + defaultTemperature: config.temperature ?? 0.0, + maxOutput: config.maxOutput ?? 4096, + apiKey: config.apiKey ?? "sk-no-key-required", + baseURL: config.baseUrl ?? "http://localhost:1234/v1", + } satisfies ResolvedOpenAICompatibleConfig; + return makeOpenAICompatibleProviderFromClient( + resolved, + new OpenAI({ baseURL: resolved.baseURL, apiKey: resolved.apiKey }), + ); } export const makeOpenAICompatibleProviderEffect = Effect.fn("makeOpenAICompatibleProvider")(function*( diff --git a/ts/packages/flow/src/model/text-completion/openai.ts b/ts/packages/flow/src/model/text-completion/openai.ts index 2e97593c..6f7790e5 100644 --- a/ts/packages/flow/src/model/text-completion/openai.ts +++ b/ts/packages/flow/src/model/text-completion/openai.ts @@ -155,7 +155,20 @@ const makeOpenAIProviderFromClient = ( export function makeOpenAIProvider( config: OpenAIProcessorConfig, ): LlmProvider { - return Effect.runSync(makeOpenAIProviderEffect(config)); + const resolved = { + defaultModel: config.model ?? "gpt-4o", + defaultTemperature: config.temperature ?? 0.0, + maxOutput: config.maxOutput ?? 4096, + apiKey: config.apiKey ?? "", + baseURL: config.baseUrl, + } satisfies ResolvedOpenAIConfig; + return makeOpenAIProviderFromClient( + resolved, + new OpenAI({ + apiKey: resolved.apiKey, + baseURL: resolved.baseURL, + }), + ); } export const makeOpenAIProviderEffect = Effect.fn("makeOpenAIProvider")(function*( diff --git a/ts/packages/flow/src/prompt/template.ts b/ts/packages/flow/src/prompt/template.ts index e439a2b5..f5750d26 100644 --- a/ts/packages/flow/src/prompt/template.ts +++ b/ts/packages/flow/src/prompt/template.ts @@ -171,7 +171,6 @@ export function makePromptTemplateService(config: PromptTemplateConfig): PromptT for (const handler of runtime.configHandlers) { service.registerConfigHandler(handler); } - Effect.runSync(Effect.log("[PromptTemplate] Service initialized")); return service; } diff --git a/ts/packages/mcp/src/server-effect.ts b/ts/packages/mcp/src/server-effect.ts index 47f3043b..96d62e36 100644 --- a/ts/packages/mcp/src/server-effect.ts +++ b/ts/packages/mcp/src/server-effect.ts @@ -1269,10 +1269,6 @@ export const loadTrustGraphMcpConfig = Effect.fn("loadTrustGraphMcpConfig")(func } }) -export const resolveTrustGraphMcpConfig = ( - options: TrustGraphMcpOptions = {}, -): TrustGraphMcpConfigShape => Effect.runSync(loadTrustGraphMcpConfig(options)) - export class TrustGraphMcpConfig extends Context.Service()( "@trustgraph/mcp/server-effect/TrustGraphMcpConfig", ) { diff --git a/ts/packages/workbench/src/atoms/workbench.ts b/ts/packages/workbench/src/atoms/workbench.ts index b5f58a7d..ae79af9f 100644 --- a/ts/packages/workbench/src/atoms/workbench.ts +++ b/ts/packages/workbench/src/atoms/workbench.ts @@ -566,13 +566,11 @@ function parseConfigValue(value: unknown): unknown { return typeof value === "string" ? parseJsonUnknown(value) ?? value : value; } -function parseConfigEntries(raw: unknown, label: string): T[] { +function parseConfigEntries(raw: unknown): T[] { const entries: T[] = []; for (const item of mapConfigEntries(raw)) { const config = parseJsonUnknown(item.value); - if (config === undefined) { - Effect.runSync(Effect.logWarning(`[workbench-atoms] Failed to parse ${label}: ${item.key}`)); - } else { + if (config !== undefined) { entries.push({ key: item.key, config } as T); } } @@ -1751,7 +1749,7 @@ export const mcpServersAtom = queryAtom( "mcpServers", Effect.fn("trustgraph.workbench.mcpServers")(function*(_get, api) { const values = yield* api.config().getValues("mcp"); - return parseConfigEntries(values, "MCP server config"); + return parseConfigEntries(values); }), { reactivityKeys: ["config", "mcp"] }, ).pipe(Atom.setIdleTTL("2 minutes")); @@ -1760,7 +1758,7 @@ export const mcpToolsAtom = queryAtom( "mcpTools", Effect.fn("trustgraph.workbench.mcpTools")(function*(_get, api) { const values = yield* api.config().getValues("tool"); - return parseConfigEntries(values, "tool config"); + return parseConfigEntries(values); }), { reactivityKeys: ["config", "tool"] }, ).pipe(Atom.setIdleTTL("2 minutes")); diff --git a/ts/packages/workbench/src/components/error-boundary.tsx b/ts/packages/workbench/src/components/error-boundary.tsx index 056d9b74..726ee0a1 100644 --- a/ts/packages/workbench/src/components/error-boundary.tsx +++ b/ts/packages/workbench/src/components/error-boundary.tsx @@ -6,7 +6,6 @@ import { ErrorBoundary as ReactErrorBoundary, } from "react-error-boundary"; import { AlertTriangle, RefreshCw } from "lucide-react"; -import { Effect } from "effect"; interface Props { children: ReactNode; @@ -46,9 +45,6 @@ export function ErrorBoundary({ children, fallback }: Props) { return ( fallback ?? } - onError={(error, info) => { - Effect.runSync(Effect.logError("[ErrorBoundary]", { error, componentStack: info.componentStack })); - }} > {children} diff --git a/ts/packages/workbench/src/qa/mock-api.ts b/ts/packages/workbench/src/qa/mock-api.ts index 75c8d9b0..02dba61a 100644 --- a/ts/packages/workbench/src/qa/mock-api.ts +++ b/ts/packages/workbench/src/qa/mock-api.ts @@ -1,6 +1,6 @@ import type { BaseApi, DocumentMetadata, ProcessingMetadata, StreamingMetadata, Triple } from "@trustgraph/client"; import { makeBaseApiWithRpc, } from "@trustgraph/client"; -import { Clock, Effect, Match, Option, Schema as S } from "effect"; +import { Match, Option, Schema as S } from "effect"; type ConfigValues = Record>; @@ -324,7 +324,7 @@ function configValues(state: MockState, type: string) { function addDocument(state: MockState, metadata: DocumentMetadata): DocumentMetadata { const id = metadata.id ?? `qa-doc-${state.library.documents.length + 1}`; - const currentTimeSeconds = Math.floor(Effect.runSync(Clock.currentTimeMillis) / 1000); + const currentTimeSeconds = state.library.documents.length + 1; const document = { ...metadata, id, diff --git a/ts/scripts/effect-laws.allowlist.json b/ts/scripts/effect-laws.allowlist.json index 57811ddf..522eda3a 100644 --- a/ts/scripts/effect-laws.allowlist.json +++ b/ts/scripts/effect-laws.allowlist.json @@ -1 +1 @@ -{"exemptions":[],"baseline":[{"rule":"no-effect-run","path":"packages/base/src/processor/async-processor.ts","count":1},{"rule":"no-effect-run","path":"packages/client/src/socket/effect-rpc-client.ts","count":10},{"rule":"no-effect-run","path":"packages/client/src/socket/trustgraph-socket.ts","count":9},{"rule":"no-effect-run","path":"packages/flow/src/agent/mcp-tool/service.ts","count":1},{"rule":"no-effect-run","path":"packages/flow/src/agent/react/service.ts","count":2},{"rule":"no-effect-run","path":"packages/flow/src/chunking/service.ts","count":1},{"rule":"no-effect-run","path":"packages/flow/src/decoding/pdf-decoder.ts","count":1},{"rule":"no-effect-run","path":"packages/flow/src/embeddings/ollama.ts","count":1},{"rule":"no-effect-run","path":"packages/flow/src/extract/knowledge-extract.ts","count":4},{"rule":"no-effect-run","path":"packages/flow/src/librarian/service.ts","count":1},{"rule":"no-effect-run","path":"packages/flow/src/model/text-completion/azure-openai.ts","count":1},{"rule":"no-effect-run","path":"packages/flow/src/model/text-completion/claude.ts","count":1},{"rule":"no-effect-run","path":"packages/flow/src/model/text-completion/mistral.ts","count":1},{"rule":"no-effect-run","path":"packages/flow/src/model/text-completion/ollama.ts","count":1},{"rule":"no-effect-run","path":"packages/flow/src/model/text-completion/openai-compatible.ts","count":1},{"rule":"no-effect-run","path":"packages/flow/src/model/text-completion/openai.ts","count":1},{"rule":"no-effect-run","path":"packages/flow/src/prompt/template.ts","count":1},{"rule":"no-effect-run","path":"packages/mcp/src/server-effect.ts","count":1},{"rule":"no-effect-run","path":"packages/workbench/src/atoms/workbench.ts","count":1},{"rule":"no-effect-run","path":"packages/workbench/src/components/error-boundary.tsx","count":1},{"rule":"no-effect-run","path":"packages/workbench/src/qa/mock-api.ts","count":1},{"rule":"no-error-throw","path":"packages/workbench/src/main.tsx","count":1},{"rule":"no-error-throw","path":"scripts/seed-config.ts","count":1},{"rule":"no-error-throw","path":"scripts/seed-demo.ts","count":4},{"rule":"no-error-throw","path":"scripts/seed-flows.ts","count":2},{"rule":"no-error-throw","path":"scripts/test-pipeline.ts","count":2},{"rule":"no-native-fetch","path":"scripts/seed-config.ts","count":1},{"rule":"no-native-fetch","path":"scripts/seed-demo.ts","count":11},{"rule":"no-native-fetch","path":"scripts/seed-flows.ts","count":1},{"rule":"no-native-fetch","path":"scripts/test-pipeline.ts","count":5},{"rule":"no-native-json","path":"scripts/seed-config.ts","count":6},{"rule":"no-native-json","path":"scripts/seed-demo.ts","count":6},{"rule":"no-native-json","path":"scripts/seed-flows.ts","count":3},{"rule":"no-native-json","path":"scripts/test-pipeline.ts","count":6},{"rule":"no-native-sort","path":"packages/client/src/socket/trustgraph-socket.ts","count":2},{"rule":"no-native-sort","path":"packages/flow/src/config/service.ts","count":3},{"rule":"no-native-sort","path":"packages/flow/src/cores/service.ts","count":1},{"rule":"no-native-sort","path":"packages/flow/src/flow-manager/service.ts","count":1},{"rule":"no-native-sort","path":"packages/flow/src/librarian/service.ts","count":1},{"rule":"no-native-sort","path":"packages/flow/src/retrieval/graph-rag.ts","count":1},{"rule":"no-native-sort","path":"packages/workbench/src/atoms/workbench.ts","count":2},{"rule":"no-native-sort","path":"packages/workbench/src/components/chat/explain-graph.tsx","count":1},{"rule":"no-native-sort","path":"packages/workbench/src/pages/graph.tsx","count":1},{"rule":"no-native-sort","path":"packages/workbench/src/qa/mock-api.ts","count":1},{"rule":"no-native-sort","path":"scripts/inventory-native-classes.ts","count":1},{"rule":"no-native-sort","path":"scripts/seed-demo.ts","count":1},{"rule":"no-native-sort","path":"scripts/seed-flows.ts","count":1},{"rule":"no-native-timers","path":"scripts/test-pipeline.ts","count":2},{"rule":"no-node-fs-path","path":"scripts/create-test-pdf.ts","count":1},{"rule":"no-node-fs-path","path":"scripts/inventory-native-classes.ts","count":2},{"rule":"no-process-env","path":"scripts/seed-config.ts","count":2},{"rule":"no-process-env","path":"scripts/seed-demo.ts","count":5},{"rule":"no-process-env","path":"scripts/seed-flows.ts","count":1},{"rule":"no-process-env","path":"scripts/test-pipeline.ts","count":11},{"rule":"no-schema-suffix","path":"packages/base/src/schema/primitives.ts","count":1},{"rule":"schema-first-data","path":"packages/client/src/models/Triple.ts","count":6},{"rule":"schema-first-data","path":"packages/client/src/models/messages.ts","count":58},{"rule":"schema-first-data","path":"packages/client/src/socket/effect-rpc-client.ts","count":2},{"rule":"schema-first-data","path":"packages/client/src/socket/trustgraph-socket.ts","count":4}]} +{"exemptions":[],"baseline":[{"rule":"no-effect-run","path":"packages/client/src/socket/effect-rpc-client.ts","count":10},{"rule":"no-effect-run","path":"packages/client/src/socket/trustgraph-socket.ts","count":9},{"rule":"no-error-throw","path":"packages/workbench/src/main.tsx","count":1},{"rule":"no-error-throw","path":"scripts/seed-config.ts","count":1},{"rule":"no-error-throw","path":"scripts/seed-demo.ts","count":4},{"rule":"no-error-throw","path":"scripts/seed-flows.ts","count":2},{"rule":"no-error-throw","path":"scripts/test-pipeline.ts","count":2},{"rule":"no-native-fetch","path":"scripts/seed-config.ts","count":1},{"rule":"no-native-fetch","path":"scripts/seed-demo.ts","count":11},{"rule":"no-native-fetch","path":"scripts/seed-flows.ts","count":1},{"rule":"no-native-fetch","path":"scripts/test-pipeline.ts","count":5},{"rule":"no-native-json","path":"scripts/seed-config.ts","count":6},{"rule":"no-native-json","path":"scripts/seed-demo.ts","count":6},{"rule":"no-native-json","path":"scripts/seed-flows.ts","count":3},{"rule":"no-native-json","path":"scripts/test-pipeline.ts","count":6},{"rule":"no-native-sort","path":"packages/client/src/socket/trustgraph-socket.ts","count":2},{"rule":"no-native-sort","path":"packages/flow/src/config/service.ts","count":3},{"rule":"no-native-sort","path":"packages/flow/src/cores/service.ts","count":1},{"rule":"no-native-sort","path":"packages/flow/src/flow-manager/service.ts","count":1},{"rule":"no-native-sort","path":"packages/flow/src/librarian/service.ts","count":1},{"rule":"no-native-sort","path":"packages/flow/src/retrieval/graph-rag.ts","count":1},{"rule":"no-native-sort","path":"packages/workbench/src/atoms/workbench.ts","count":2},{"rule":"no-native-sort","path":"packages/workbench/src/components/chat/explain-graph.tsx","count":1},{"rule":"no-native-sort","path":"packages/workbench/src/pages/graph.tsx","count":1},{"rule":"no-native-sort","path":"packages/workbench/src/qa/mock-api.ts","count":1},{"rule":"no-native-sort","path":"scripts/inventory-native-classes.ts","count":1},{"rule":"no-native-sort","path":"scripts/seed-demo.ts","count":1},{"rule":"no-native-sort","path":"scripts/seed-flows.ts","count":1},{"rule":"no-native-timers","path":"scripts/test-pipeline.ts","count":2},{"rule":"no-node-fs-path","path":"scripts/create-test-pdf.ts","count":1},{"rule":"no-node-fs-path","path":"scripts/inventory-native-classes.ts","count":2},{"rule":"no-process-env","path":"scripts/seed-config.ts","count":2},{"rule":"no-process-env","path":"scripts/seed-demo.ts","count":5},{"rule":"no-process-env","path":"scripts/seed-flows.ts","count":1},{"rule":"no-process-env","path":"scripts/test-pipeline.ts","count":11},{"rule":"no-schema-suffix","path":"packages/base/src/schema/primitives.ts","count":1},{"rule":"schema-first-data","path":"packages/client/src/models/Triple.ts","count":6},{"rule":"schema-first-data","path":"packages/client/src/models/messages.ts","count":58},{"rule":"schema-first-data","path":"packages/client/src/socket/effect-rpc-client.ts","count":2},{"rule":"schema-first-data","path":"packages/client/src/socket/trustgraph-socket.ts","count":4}]}