oneie
Version:
Build apps, websites, and AI agents in English. Zero-interaction setup for AI agents (Claude Code, Cursor, Windsurf). Download to your computer, run in the cloud, deploy to the edge. Open source and free forever.
1,353 lines (1,074 loc) • 61.9 kB
Markdown
---
title: Todo Components
dimension: things
primary_dimension: things
category: todo-components.md
tags: agent, ai, architecture, cycle
related_dimensions: things, events, knowledge, groups, people, connections
scope: global
created: 2025-11-03
updated: 2025-11-03
version: 1.0.0
ai_context: |
This document is part of the things dimension in the todo-components.md category.
Location: one/things/todo-components.md
Purpose: Documents convex components + effect.ts integration - 100 cycle todo list
Related dimensions: events, knowledge
For AI agents: Read this to understand todo components.
---
# Convex Components + Effect.ts Integration - 100 Cycle Todo List
**Feature:** Effect.ts Service Layer Architecture with Convex Components
**Status:** Planning Complete → Ready for Execution
**Created:** 2025-10-30
## Overview
This document tracks all 100 cycles for implementing a production-ready service layer that combines Effect.ts functional programming patterns with Convex components (@convex-dev/agent, workflow, RAG, rate-limiter, etc.) to build sophisticated multi-agent AI systems.
**Key Principle:** Effect wraps components, not replaces. Components handle infrastructure, Effect handles business logic composition.
---
## Foundation Phase (Cycle 1-10)
**Agent:** agent-director
**Goal:** Validate architecture, map components, create execution plan
### ✅ Cycle 1: Validate Effect + Convex Components Architecture
**Status:** ✅ Complete
**Task:** Ensure Effect.ts service layer pattern works with all Convex components
**Validation:**
- Effect.tryPromise wraps component Promise calls ✅
- Context/Layer pattern for dependency injection ✅
- Tagged errors for type-safe error handling ✅
- No performance regression vs direct component usage ✅
- All 8 components compatible with Effect wrapper pattern ✅
### ✅ Cycle 2: Map 8 Convex Components to Effect Services
**Status:** ✅ Complete
**Component Mapping:**
1. **@convex-dev/agent** → AgentService
- Where Effect helps: Business logic orchestration, multi-agent composition, error handling
- Where component shines: Thread management, streaming, RAG, tool calling
2. **@convex-dev/workflow** → WorkflowService
- Where Effect helps: Step business logic, service composition, error handling
- Where component shines: Durable execution, journaling, retry policies
3. **@convex-dev/rag** → RAGService
- Where Effect helps: Composing RAG with other services, custom embeddings, error handling
- Where component shines: Vector storage, semantic search, chunking
4. **@convex-dev/rate-limiter** → RateLimitService
- Where Effect helps: Composing rate limits with business logic, multi-level limits, smart retries
- Where component shines: Token bucket, fixed window, capacity reservation
5. **@convex-dev/persistent-text-streaming** → StreamingService
- Where Effect helps: Error recovery during streaming, lifecycle management, backpressure
- Where component shines: WebSocket delivery, delta storage, client subscription
6. **@convex-dev/workpool** → TaskQueueService
- Where Effect helps: Batch enqueuing, error handling, coordinating multiple pools
- Where component shines: Task queuing, parallelism control, completion callbacks
7. **@convex-dev/retrier** → ResilientExecutionService
- Where Effect helps: Coordinating retries across operations, custom policies, composition
- Where component shines: Action retries with persistent state, status tracking
8. **@convex-dev/crons** → CronService
- Where Effect helps: Scheduled job logic composition, error handling, service orchestration
- Where component shines: Dynamic cron registration, schedule management
### ✅ Cycle 3: Define Service Layer Structure
**Status:** ✅ Complete
**Directory Structure:**
```
backend/convex/
├── services/ # Effect service layers (8 services)
├── domain/ # Business logic with Effect
│ ├── agents/ # Multi-agent orchestration
│ ├── workflows/ # Workflow definitions
│ └── users/ # User domain logic
├── api/ # Public endpoints (use services)
└── lib/ # Effect utilities
├── effect-utils.ts
├── convex-effect.ts
└── monitoring.ts
```
### ✅ Cycle 4: Identify Error Types and Patterns
**Status:** ✅ Complete
**Error Categories:**
**Domain Errors:**
- `UserNotFoundError` - User doesn't exist
- `ThreadNotFoundError` - Thread doesn't exist
- `InsufficientPermissionsError` - User lacks permissions
**Infrastructure Errors:**
- `AgentError` - Agent component failure
- `RAGError` - RAG component failure
- `DatabaseError` - Convex database error
**Rate Limiting Errors:**
- `RateLimitError` - Rate limit exceeded
- `QuotaExceededError` - Quota limit hit
**Pattern:** Tagged error classes with `Data.TaggedError`
### ✅ Cycle 5: Plan Dependency Injection Strategy
**Status:** ✅ Complete
**Strategy:**
- **Context.Tag:** Define service interfaces
- **Layer.effect:** Implement service layers
- **Layer.merge:** Compose multiple layers
- **Effect.provide:** Inject layers at runtime
- **Test Layers:** Swap real services for mocks
**Example:**
```typescript
class AgentService extends Context.Tag("AgentService")<...>() {}
const AgentServiceLive = Layer.effect(AgentService, ...)
const TestAgentServiceLive = Layer.succeed(AgentService, mockImpl)
```
### ✅ Cycle 6: Define Observability Requirements
**Status:** ✅ Complete
**Requirements:**
1. **Service Call Tracking:** Log start, complete, fail for every service call
2. **Token Usage:** Track AI model token consumption per request
3. **Error Tracking:** Log all errors with Effect error chain
4. **Performance Metrics:** Track latency per service operation
5. **Dependency Graph:** Visualize service dependencies
6. **Distributed Tracing:** Propagate trace IDs across service calls
**Implementation:** MonitoringService with Effect.tap
### ✅ Cycle 7: Create Integration Patterns Document
**Status:** ✅ Complete
**Patterns:**
1. **Effect-Wrapped Component:** `Effect.tryPromise` for component calls
2. **Service Layer:** Context.Tag + Layer for DI
3. **Error Handling:** `Effect.catchTag` for specific errors, `Effect.catchAll` for fallback
4. **Parallel Execution:** `Effect.all` with concurrency control
5. **Resource Management:** `Effect.Scope` + `acquireRelease`
6. **Retry Logic:** `Effect.retry` + `Schedule.exponential`
7. **Service Composition:** `Effect.gen` for sequential, `Effect.all` for parallel
### ✅ Cycle 8: Break Down Into 100 Cycles
**Status:** ✅ Complete
**Breakdown:**
- Foundation: 1-10 (planning)
- Core Services: 11-30 (Agent, RAG, Rate Limit, Workflow)
- Supporting Services: 31-50 (Streaming, Workpool, Retrier, Crons)
- Domain Logic: 51-70 (Multi-agent, workflows, tools)
- Observability & Testing: 71-90 (Monitoring, tests, error handling)
- Advanced & Documentation: 91-100 (Confect, docs, optimization, launch)
### ✅ Cycle 9: Assign Agents to Phases
**Status:** ✅ Complete
**Agent Assignments:**
- **agent-director:** Cycle 1-10, 99-100 (planning, coordination, launch)
- **agent-backend:** Cycle 11-50, 91-93, 97-98 (service implementation, optimization)
- **agent-builder:** Cycle 51-70 (domain logic, multi-agent orchestration)
- **agent-ops:** Cycle 71-75, 81-85 (monitoring, resource management)
- **agent-quality:** Cycle 76-80, 86-90 (testing, error handling)
- **agent-documenter:** Cycle 94-96 (documentation, guides, examples)
### ✅ Cycle 10: Create Complete Implementation Plan
**Status:** ✅ Complete
**Deliverable:** `/one/things/plans/components.md`
**Content:** Executive summary, 6-dimension mapping, architecture, phases, success metrics, risks, timeline
---
## Core Service Layers Phase (Cycle 11-30)
**Agent:** agent-backend
**Goal:** Implement Effect service layers for core components
### ⏳ Cycle 11: Wrap @convex-dev/agent with Effect (Part 1: Setup)
**Status:** Pending
**Dependencies:** Cycle 1-10 (Foundation complete)
**Task:** Create AgentService interface and basic structure
**File:** `backend/convex/services/agent.service.ts`
**Acceptance Criteria:**
- [ ] Import Effect, Context, Layer, Data
- [ ] Import Agent from @convex-dev/agent
- [ ] Define error types: `AgentError`, `ThreadNotFoundError`, `ToolExecutionError`
- [ ] Create `AgentService` Context.Tag with interface:
- `generateResponse(ctx, threadId, prompt)`
- `createThread(ctx, userId)`
- `continueThread(ctx, threadId, message)`
- [ ] Stub implementation (returns Effect.succeed with placeholder)
### ⏳ Cycle 12: Implement AgentServiceLive Layer
**Status:** Pending
**Dependencies:** Cycle 11
**Task:** Full implementation of AgentService
**File:** `backend/convex/services/agent.service.ts`
**Acceptance Criteria:**
- [ ] Initialize Agent component in Layer.effect
- [ ] Implement `generateResponse` with Effect.tryPromise wrapping agent.continueThread
- [ ] Implement `createThread` with proper error handling
- [ ] Inject RateLimitService dependency (yield\* RateLimitService)
- [ ] Check rate limit before agent calls
- [ ] Return typed errors (AgentError, RateLimitError)
- [ ] Add Effect.retry for transient failures
### ⏳ Cycle 13: Create Agent Tool Definitions with Effect
**Status:** Pending
**Dependencies:** Cycle 12
**Task:** Define agent tools that use Effect services internally
**File:** `backend/convex/services/agent.service.ts`
**Acceptance Criteria:**
- [ ] Create `emailTool` using EmailService (Effect-based)
- [ ] Create `searchTool` using RAGService (Effect-based)
- [ ] Create `databaseQueryTool` using database operations (Effect-based)
- [ ] Convert Effect programs to Promises in tool handlers (Effect.runPromise)
- [ ] Handle errors gracefully (return error messages to agent)
- [ ] Register tools with Agent component
### ⏳ Cycle 14: Add Agent Service Error Types
**Status:** Pending
**Dependencies:** Cycle 13
**Task:** Define comprehensive error types for AgentService
**File:** `backend/convex/domain/agents/errors.ts`
**Acceptance Criteria:**
- [ ] `AgentError` - General agent failure (includes agentName, cause)
- [ ] `ThreadNotFoundError` - Thread doesn't exist (includes threadId)
- [ ] `ToolExecutionError` - Tool failed (includes toolName, cause)
- [ ] `InvalidPromptError` - Prompt validation failed (includes reason)
- [ ] `ModelOverloadedError` - Model capacity exceeded (includes retryAfter)
- [ ] All errors extend `Data.TaggedError`
- [ ] All errors include helpful metadata
### ⏳ Cycle 15: Test AgentService with Effect
**Status:** Pending
**Dependencies:** Cycle 14
**Task:** Create test layer for AgentService
**File:** `backend/convex/services/agent.service.test.ts`
**Acceptance Criteria:**
- [ ] Create `TestAgentServiceLive` layer with mock implementation
- [ ] Mock `generateResponse` returns fixed response
- [ ] Mock `createThread` returns deterministic threadId
- [ ] Test successful agent call (Effect.runPromise passes)
- [ ] Test error handling (Effect.runPromise rejects with AgentError)
- [ ] Test rate limit integration (mocked RateLimitService)
- [ ] Test retry logic (transient errors recover)
### ⏳ Cycle 16: Wrap @convex-dev/rag with Effect (Part 1: Setup)
**Status:** Pending
**Dependencies:** Cycle 15
**Task:** Create RAGService interface and basic structure
**File:** `backend/convex/services/rag.service.ts`
**Acceptance Criteria:**
- [ ] Import Effect, Context, Layer, Data
- [ ] Import RAG from @convex-dev/rag
- [ ] Define error types: `RAGError`, `EmbeddingError`, `SearchError`
- [ ] Create `RAGService` Context.Tag with interface:
- `addDocument(ctx, namespace, content, metadata)`
- `search(ctx, namespace, query, limit)`
- `deleteDocument(ctx, namespace, entryId)`
- [ ] Stub implementation
### ⏳ Cycle 17: Implement RAGServiceLive Layer
**Status:** Pending
**Dependencies:** Cycle 16
**Task:** Full implementation of RAGService
**File:** `backend/convex/services/rag.service.ts`
**Acceptance Criteria:**
- [ ] Initialize RAG component with openai.embedding("text-embedding-3-small")
- [ ] Implement `addDocument` with Effect.tryPromise wrapping rag.add
- [ ] Implement `search` with Effect.tryPromise wrapping rag.search
- [ ] Implement `deleteDocument` with proper error handling
- [ ] Pre-process content before adding (Effect pipeline)
- [ ] Handle embedding generation failures gracefully
- [ ] Add vector score threshold filtering
### ⏳ Cycle 18: Compose RAG with Agent Service
**Status:** Pending
**Dependencies:** Cycle 17
**Task:** Use RAGService within AgentService for context retrieval
**File:** `backend/convex/domain/agents/orchestration.ts`
**Acceptance Criteria:**
- [ ] Create `contextualAnswerAgent` action
- [ ] Inject both AgentService and RAGService
- [ ] Search RAG for context (yield\* ragService.search)
- [ ] Generate agent response with context (yield\* agentService.generateResponse)
- [ ] Return answer + sources (with relevance scores)
- [ ] Handle errors (RAGError, AgentError) gracefully
- [ ] Add Effect.retry for robustness
### ⏳ Cycle 19: Add RAG Error Types
**Status:** Pending
**Dependencies:** Cycle 18
**Task:** Define comprehensive error types for RAGService
**File:** `backend/convex/domain/agents/errors.ts`
**Acceptance Criteria:**
- [ ] `RAGError` - General RAG failure (includes cause)
- [ ] `EmbeddingError` - Embedding generation failed (includes text, modelName)
- [ ] `SearchError` - Search query failed (includes query, namespace)
- [ ] `ChunkingError` - Document chunking failed (includes documentId)
- [ ] `InvalidNamespaceError` - Namespace doesn't exist (includes namespace)
- [ ] All errors extend `Data.TaggedError`
### ⏳ Cycle 20: Test RAGService with Effect
**Status:** Pending
**Dependencies:** Cycle 19
**Task:** Create test layer for RAGService
**File:** `backend/convex/services/rag.service.test.ts`
**Acceptance Criteria:**
- [ ] Create `TestRAGServiceLive` layer with mock implementation
- [ ] Mock `search` returns fixed results with scores
- [ ] Mock `addDocument` returns deterministic entryId
- [ ] Test successful search (Effect.runPromise passes)
- [ ] Test error handling (SearchError, EmbeddingError)
- [ ] Test composition with AgentService (integration)
- [ ] Test retry logic for transient failures
### ⏳ Cycle 21: Wrap @convex-dev/rate-limiter with Effect (Part 1: Setup)
**Status:** Pending
**Dependencies:** Cycle 20
**Task:** Create RateLimitService interface and basic structure
**File:** `backend/convex/services/rate-limit.service.ts`
**Acceptance Criteria:**
- [ ] Import Effect, Context, Layer, Data
- [ ] Import RateLimiter from @convex-dev/rate-limiter
- [ ] Define error types: `RateLimitError`, `QuotaExceededError`
- [ ] Create `RateLimitService` Context.Tag with interface:
- `checkLimit(ctx, name, key, count?)`
- `checkUserLimit(ctx, userId)`
- `checkGlobalLimit(ctx)`
- [ ] Stub implementation
### ⏳ Cycle 22: Implement RateLimitServiceLive Layer
**Status:** Pending
**Dependencies:** Cycle 21
**Task:** Full implementation of RateLimitService
**File:** `backend/convex/services/rate-limit.service.ts`
**Acceptance Criteria:**
- [ ] Initialize RateLimiter with config (token bucket, fixed window)
- [ ] Implement `checkLimit` with Effect.tryPromise wrapping rateLimiter.limit
- [ ] Return RateLimitError if limit exceeded (include retryAfter)
- [ ] Implement `checkUserLimit` (per-user rate limit)
- [ ] Implement `checkGlobalLimit` (system-wide rate limit)
- [ ] Add reserve parameter for capacity reservation
- [ ] Handle multiple rate limit tiers (starter, pro, enterprise)
### ⏳ Cycle 23: Multi-Level Rate Limiting with Effect
**Status:** Pending
**Dependencies:** Cycle 22
**Task:** Coordinate user and global rate limits in parallel
**File:** `backend/convex/domain/agents/orchestration.ts`
**Acceptance Criteria:**
- [ ] Create `protectedAgentCall` action
- [ ] Check user and global limits in parallel (Effect.all)
- [ ] Fail fast if any limit exceeded
- [ ] Return specific error (UserRateLimitExceeded vs GlobalRateLimitExceeded)
- [ ] Include retryAfter in error response
- [ ] Execute agent call only if both limits OK
- [ ] Log rate limit events
### ⏳ Cycle 24: Add Rate Limit Error Types
**Status:** Pending
**Dependencies:** Cycle 23
**Task:** Define comprehensive error types for rate limiting
**File:** `backend/convex/domain/agents/errors.ts`
**Acceptance Criteria:**
- [ ] `RateLimitError` - General rate limit (includes limitName, retryAfter)
- [ ] `UserRateLimitExceeded` - User-specific limit hit (includes userId, retryAfter)
- [ ] `GlobalRateLimitExceeded` - System-wide limit hit (includes retryAfter)
- [ ] `QuotaExceededError` - Monthly quota exceeded (includes quotaType, resetDate)
- [ ] `ReservationFailedError` - Capacity reservation failed (includes requested, available)
- [ ] All errors extend `Data.TaggedError`
### ⏳ Cycle 25: Test RateLimitService with Effect
**Status:** Pending
**Dependencies:** Cycle 24
**Task:** Create test layer for RateLimitService
**File:** `backend/convex/services/rate-limit.service.test.ts`
**Acceptance Criteria:**
- [ ] Create `TestRateLimitServiceLive` layer
- [ ] Mock `checkLimit` returns OK for first N calls, then RateLimitError
- [ ] Test successful limit check (Effect.runPromise passes)
- [ ] Test rate limit exceeded (Effect.runPromise rejects with RateLimitError)
- [ ] Test parallel limit checks (user + global)
- [ ] Test retry logic (Effect.retry with exponential backoff)
- [ ] Test capacity reservation
### ⏳ Cycle 26: Wrap @convex-dev/workflow with Effect (Part 1: Setup)
**Status:** Pending
**Dependencies:** Cycle 25
**Task:** Create WorkflowService interface and basic structure
**File:** `backend/convex/services/workflow.service.ts`
**Acceptance Criteria:**
- [ ] Import Effect, Context, Layer, Data
- [ ] Import WorkflowManager from @convex-dev/workflow
- [ ] Define error types: `WorkflowError`, `StepFailedError`
- [ ] Create `WorkflowService` Context.Tag with interface:
- `defineWorkflow(name, handler)`
- `startWorkflow(ctx, workflowId, args)`
- `getWorkflowStatus(ctx, workflowId)`
- [ ] Stub implementation
### ⏳ Cycle 27: Implement WorkflowServiceLive Layer
**Status:** Pending
**Dependencies:** Cycle 26
**Task:** Full implementation of WorkflowService
**File:** `backend/convex/services/workflow.service.ts`
**Acceptance Criteria:**
- [ ] Initialize WorkflowManager with default retry behavior
- [ ] Implement `defineWorkflow` wrapping workflow.define
- [ ] Implement `startWorkflow` with Effect.tryPromise
- [ ] Implement `getWorkflowStatus` for monitoring
- [ ] Handle workflow step errors gracefully
- [ ] Add retry policies per step
- [ ] Support long-running workflows (hours/days)
### ⏳ Cycle 28: Create Effect Programs for Workflow Steps
**Status:** Pending
**Dependencies:** Cycle 27
**Task:** Use Effect services within workflow steps
**File:** `backend/convex/domain/workflows/research.ts`
**Acceptance Criteria:**
- [ ] Define `researchWorkflow` using workflow.define
- [ ] Step 1: Classify query (Effect-based action)
- [ ] Step 2: Parallel research (web, academic, news agents)
- [ ] Step 3: Synthesize findings (Effect-based action using AgentService + RAGService)
- [ ] Step 4: Generate report (Effect-based action)
- [ ] Step 5: Save and notify (mutation)
- [ ] All actions use Effect.runPromise internally
- [ ] Error handling with Effect.catchAll
### ⏳ Cycle 29: Add Workflow Error Types
**Status:** Pending
**Dependencies:** Cycle 28
**Task:** Define comprehensive error types for workflows
**File:** `backend/convex/domain/workflows/errors.ts`
**Acceptance Criteria:**
- [ ] `WorkflowError` - General workflow failure (includes workflowId, cause)
- [ ] `StepFailedError` - Specific step failed (includes stepName, cause)
- [ ] `WorkflowTimeoutError` - Workflow exceeded time limit (includes workflowId, duration)
- [ ] `WorkflowCanceledError` - Workflow manually canceled (includes reason)
- [ ] `InvalidWorkflowStateError` - Workflow in invalid state (includes currentState)
- [ ] All errors extend `Data.TaggedError`
### ⏳ Cycle 30: Test WorkflowService with Effect
**Status:** Pending
**Dependencies:** Cycle 29
**Task:** Create test layer for WorkflowService
**File:** `backend/convex/services/workflow.service.test.ts`
**Acceptance Criteria:**
- [ ] Create `TestWorkflowServiceLive` layer
- [ ] Mock workflow steps return deterministic results
- [ ] Test successful workflow execution (all steps pass)
- [ ] Test step failure handling (StepFailedError propagates)
- [ ] Test retry logic (step retries 3 times before failing)
- [ ] Test long-running workflow (status polling)
- [ ] Test workflow cancellation
---
## Supporting Services Phase (Cycle 31-50)
**Agent:** agent-backend
**Goal:** Implement remaining service layers
### ⏳ Cycle 31: Wrap @convex-dev/persistent-text-streaming with Effect
**Status:** Pending
**Dependencies:** Cycle 30
**Task:** Create StreamingService interface and implementation
**File:** `backend/convex/services/streaming.service.ts`
**Acceptance Criteria:**
- [ ] Import Effect, Stream from effect
- [ ] Import PersistentTextStreaming from @convex-dev/persistent-text-streaming
- [ ] Define error types: `StreamingError`, `ChunkAppendError`
- [ ] Create `StreamingService` Context.Tag
- [ ] Implement `generateStream(ctx, prompt, streamId)`
- [ ] Use Effect.Stream for backpressure handling
- [ ] Wrap persistentTextStreaming.appendChunk with Effect.tryPromise
- [ ] Handle stream lifecycle (start, chunk, complete, error)
### ⏳ Cycle 32: Implement Streaming Error Recovery
**Status:** Pending
**Dependencies:** Cycle 31
**Task:** Add retry logic for failed stream chunks
**File:** `backend/convex/services/streaming.service.ts`
**Acceptance Criteria:**
- [ ] Retry chunk append on transient errors (Effect.retry)
- [ ] Use exponential backoff (Schedule.exponential)
- [ ] Max 3 retries per chunk
- [ ] Mark stream as failed if chunk repeatedly fails
- [ ] Store failed chunks for manual recovery
- [ ] Log streaming errors as events
### ⏳ Cycle 33: Test StreamingService with Effect
**Status:** Pending
**Dependencies:** Cycle 32
**Task:** Create test layer for StreamingService
**File:** `backend/convex/services/streaming.service.test.ts`
**Acceptance Criteria:**
- [ ] Create `TestStreamingServiceLive` layer
- [ ] Mock stream returns deterministic chunks
- [ ] Test successful streaming (all chunks delivered)
- [ ] Test chunk failure handling (retry + eventual success)
- [ ] Test stream cancellation (cleanup resources)
- [ ] Test backpressure (slow consumer)
- [ ] Test concurrent streams
### ⏳ Cycle 34: Add Streaming Error Types
**Status:** Pending
**Dependencies:** Cycle 33
**Task:** Define comprehensive error types for streaming
**File:** `backend/convex/domain/agents/errors.ts`
**Acceptance Criteria:**
- [ ] `StreamingError` - General streaming failure (includes streamId, cause)
- [ ] `ChunkAppendError` - Chunk append failed (includes chunk, attempt)
- [ ] `StreamCompletionError` - Failed to mark stream complete (includes streamId)
- [ ] `StreamProcessingError` - Stream processing logic failed (includes cause)
- [ ] All errors extend `Data.TaggedError`
### ⏳ Cycle 35: Integrate Streaming with Agent Component
**Status:** Pending
**Dependencies:** Cycle 34
**Task:** Use Agent component's built-in streaming instead of persistent-text-streaming
**File:** `backend/convex/services/agent.service.ts`
**Acceptance Criteria:**
- [ ] Enable `saveStreamDeltas: true` in Agent config
- [ ] Agent automatically handles streaming to Convex
- [ ] Client subscribes to stream deltas via useQuery
- [ ] StreamingService used only for custom HTTP streaming
- [ ] Document when to use each approach
- [ ] Update tests to use Agent streaming
### ⏳ Cycle 36: Wrap @convex-dev/workpool with Effect
**Status:** Pending
**Dependencies:** Cycle 35
**Task:** Create TaskQueueService interface and implementation
**File:** `backend/convex/services/workpool.service.ts`
**Acceptance Criteria:**
- [ ] Import Effect, Queue from effect
- [ ] Import Workpool from @convex-dev/workpool
- [ ] Define error types: `EnqueueError`, `TaskStatusError`
- [ ] Create `TaskQueueService` Context.Tag
- [ ] Implement `enqueueTask(ctx, priority, action, args)`
- [ ] Implement `getTaskStatus(ctx, taskId)`
- [ ] Support multiple workpools (high priority, low priority)
- [ ] Handle task completion callbacks
### ⏳ Cycle 37: Batch Task Enqueuing with Effect
**Status:** Pending
**Dependencies:** Cycle 36
**Task:** Enqueue multiple tasks in parallel
**File:** `backend/convex/domain/workflows/batch-processing.ts`
**Acceptance Criteria:**
- [ ] Create `processBatch` mutation
- [ ] Use Effect.all to enqueue tasks in parallel
- [ ] Control concurrency (max 10 concurrent enqueues)
- [ ] Return array of taskIds
- [ ] Handle partial failures gracefully
- [ ] Log batch processing metrics
- [ ] Add retry for failed enqueues
### ⏳ Cycle 38: Test TaskQueueService with Effect
**Status:** Pending
**Dependencies:** Cycle 37
**Task:** Create test layer for TaskQueueService
**File:** `backend/convex/services/workpool.service.test.ts`
**Acceptance Criteria:**
- [ ] Create `TestTaskQueueServiceLive` layer
- [ ] Mock `enqueueTask` returns deterministic taskId
- [ ] Mock `getTaskStatus` returns task progress
- [ ] Test successful task enqueuing
- [ ] Test task status polling
- [ ] Test batch enqueuing (parallel)
- [ ] Test priority queuing (high vs low)
- [ ] Test completion callbacks
### ⏳ Cycle 39: Add Workpool Error Types
**Status:** Pending
**Dependencies:** Cycle 38
**Task:** Define comprehensive error types for task queues
**File:** `backend/convex/domain/workflows/errors.ts`
**Acceptance Criteria:**
- [ ] `EnqueueError` - Task enqueue failed (includes action, cause)
- [ ] `TaskStatusError` - Failed to check task status (includes taskId)
- [ ] `TaskFailedError` - Task execution failed (includes taskId, error)
- [ ] `WorkpoolFullError` - Workpool at capacity (includes maxParallelism, current)
- [ ] All errors extend `Data.TaggedError`
### ⏳ Cycle 40: Integrate Workpool with Workflow
**Status:** Pending
**Dependencies:** Cycle 39
**Task:** Use TaskQueueService within workflows for async operations
**File:** `backend/convex/domain/workflows/research.ts`
**Acceptance Criteria:**
- [ ] Enqueue background tasks from workflow steps
- [ ] Poll task status within workflow
- [ ] Handle task failures within workflow
- [ ] Use Effect.retry for task status polling
- [ ] Log task enqueue/complete events
- [ ] Update workflow state based on task results
### ⏳ Cycle 41: Wrap @convex-dev/retrier with Effect
**Status:** Pending
**Dependencies:** Cycle 40
**Task:** Create ResilientExecutionService interface and implementation
**File:** `backend/convex/services/retrier.service.ts`
**Acceptance Criteria:**
- [ ] Import Effect, Schedule from effect
- [ ] Import ActionRetrier from @convex-dev/retrier
- [ ] Define error types: `RetrierStartError`, `ExecutionTimeout`
- [ ] Create `ResilientExecutionService` Context.Tag
- [ ] Implement `executeWithRetry(ctx, action, args)`
- [ ] Poll for completion with Effect.repeat
- [ ] Return result or throw ExecutionFailed
- [ ] Handle retrier-level and Effect-level retries
### ⏳ Cycle 42: Combine Retrier with Effect.retry
**Status:** Pending
**Dependencies:** Cycle 41
**Task:** Hybrid retry strategy (component + Effect)
**File:** `backend/convex/domain/workflows/reliable-execution.ts`
**Acceptance Criteria:**
- [ ] Use retrier for infrastructure-level retries (actions with persistent state)
- [ ] Use Effect.retry for application-level retries (in-memory operations)
- [ ] Example: Validate data (Effect.retry) → Process data (retrier.run)
- [ ] Document when to use each approach
- [ ] Add integration test for hybrid retries
- [ ] Log retry attempts as events
### ⏳ Cycle 43: Test ResilientExecutionService with Effect
**Status:** Pending
**Dependencies:** Cycle 42
**Task:** Create test layer for ResilientExecutionService
**File:** `backend/convex/services/retrier.service.test.ts`
**Acceptance Criteria:**
- [ ] Create `TestResilientExecutionServiceLive` layer
- [ ] Mock action execution with configurable success/failure
- [ ] Test successful execution (returns result)
- [ ] Test retries (fails 2 times, succeeds on 3rd)
- [ ] Test max retries exceeded (throws ExecutionFailed)
- [ ] Test timeout (throws ExecutionTimeout)
- [ ] Test status polling (Effect.repeat)
### ⏳ Cycle 44: Add Retrier Error Types
**Status:** Pending
**Dependencies:** Cycle 43
**Task:** Define comprehensive error types for retries
**File:** `backend/convex/domain/workflows/errors.ts`
**Acceptance Criteria:**
- [ ] `RetrierStartError` - Failed to start retry execution (includes cause)
- [ ] `StatusCheckError` - Failed to check execution status (includes runId)
- [ ] `ExecutionTimeout` - Execution exceeded time limit (includes runId, duration)
- [ ] `ExecutionFailed` - Execution failed after all retries (includes error, attempts)
- [ ] `ExecutionCanceled` - Execution manually canceled (includes runId)
- [ ] All errors extend `Data.TaggedError`
### ⏳ Cycle 45: Integrate Retrier with Workflow
**Status:** Pending
**Dependencies:** Cycle 44
**Task:** Use ResilientExecutionService for critical workflow steps
**File:** `backend/convex/domain/workflows/support.ts`
**Acceptance Criteria:**
- [ ] Define `supportTicketWorkflow` using workflow.define
- [ ] Use retrier for external API calls (email, Slack)
- [ ] Use Effect.retry for internal operations (validation, formatting)
- [ ] Handle ExecutionFailed gracefully (fallback actions)
- [ ] Log retry attempts and final outcomes
- [ ] Test workflow with simulated failures
### ⏳ Cycle 46: Wrap @convex-dev/crons with Effect
**Status:** Pending
**Dependencies:** Cycle 45
**Task:** Create CronService interface and implementation
**File:** `backend/convex/services/crons.service.ts`
**Acceptance Criteria:**
- [ ] Import Effect from effect
- [ ] Import Crons from @convex-dev/crons
- [ ] Define error types: `CronRegisterError`, `CronExecutionError`
- [ ] Create `CronService` Context.Tag
- [ ] Implement `register(ctx, schedule, action, args, name)`
- [ ] Implement `unregister(ctx, name)`
- [ ] Implement `list(ctx)` for registered crons
- [ ] Support cron specs (e.g., "0 0 \* \* \*")
### ⏳ Cycle 47: Effect-Based Cron Job Logic
**Status:** Pending
**Dependencies:** Cycle 46
**Task:** Use Effect in cron job handlers
**File:** `backend/convex/domain/crons/daily-maintenance.ts`
**Acceptance Criteria:**
- [ ] Create `dailyMaintenanceWithEffect` internalAction
- [ ] Use Effect.gen for job logic
- [ ] Inject services (RAGService, MonitoringService)
- [ ] Clean up old content (Effect-wrapped mutation)
- [ ] Generate daily report (Effect service call)
- [ ] Send report via email (Effect-wrapped action)
- [ ] Handle errors with Effect.catchAll (log + succeed)
- [ ] Run with Effect.runPromise
### ⏳ Cycle 48: Test CronService with Effect
**Status:** Pending
**Dependencies:** Cycle 47
**Task:** Create test layer for CronService
**File:** `backend/convex/services/crons.service.test.ts`
**Acceptance Criteria:**
- [ ] Create `TestCronServiceLive` layer
- [ ] Mock `register` stores cron definition
- [ ] Mock `list` returns registered crons
- [ ] Test cron registration (succeeds)
- [ ] Test cron execution (job runs on schedule)
- [ ] Test cron unregistration (removes from list)
- [ ] Test job errors (logged, job continues)
- [ ] Test Effect-based job logic (services injected)
### ⏳ Cycle 49: Add Cron Error Types
**Status:** Pending
**Dependencies:** Cycle 48
**Task:** Define comprehensive error types for crons
**File:** `backend/convex/domain/crons/errors.ts`
**Acceptance Criteria:**
- [ ] `CronRegisterError` - Failed to register cron (includes cronspec, cause)
- [ ] `CronExecutionError` - Cron job execution failed (includes jobName, cause)
- [ ] `InvalidCronspecError` - Cron schedule format invalid (includes cronspec)
- [ ] `CronNotFoundError` - Cron doesn't exist (includes cronName)
- [ ] All errors extend `Data.TaggedError`
### ⏳ Cycle 50: Integrate Crons with Monitoring
**Status:** Pending
**Dependencies:** Cycle 49
**Task:** Track cron job executions via MonitoringService
**File:** `backend/convex/domain/crons/daily-maintenance.ts`
**Acceptance Criteria:**
- [ ] Inject MonitoringService in cron job
- [ ] Track job start (Effect.tap)
- [ ] Track job completion (Effect.tap)
- [ ] Track job errors (Effect.tapError)
- [ ] Log execution duration
- [ ] Alert if job fails repeatedly (3+ times)
- [ ] Store job metrics in database
---
## Domain Logic Phase (Cycle 51-70)
**Agents:** agent-backend, agent-builder
**Goal:** Build complex business logic using Effect services
### ⏳ Cycle 51: Multi-Agent Orchestration with Effect
**Status:** Pending
**Dependencies:** Cycle 50
**Task:** Compose multiple agents in parallel and sequential flows
**File:** `backend/convex/domain/agents/orchestration.ts`
**Acceptance Criteria:**
- [ ] Create `multiAgentPipeline` action
- [ ] Inject AgentService and RAGService
- [ ] Sequential: Fetch context → Classify intent → Route to agent
- [ ] Parallel: Quality checks (grammar + factuality)
- [ ] Use Effect.gen for sequential, Effect.all for parallel
- [ ] Handle errors from multiple agents gracefully
- [ ] Return combined result
### ⏳ Cycle 52: Parallel Agent Execution (Effect.all)
**Status:** Pending
**Dependencies:** Cycle 51
**Task:** Run multiple agents concurrently with concurrency control
**File:** `backend/convex/domain/agents/orchestration.ts`
**Acceptance Criteria:**
- [ ] Use Effect.all with concurrency: 2 (limit parallel agents)
- [ ] Execute: [webSearchAgent, academicAgent, newsAgent]
- [ ] Collect results in array
- [ ] Handle partial failures (mode: "default" vs "either")
- [ ] Return all results or fail fast
- [ ] Log agent execution metrics
### ⏳ Cycle 53: Sequential Agent Pipelines (Effect.gen)
**Status:** Pending
**Dependencies:** Cycle 52
**Task:** Chain agents where output of one feeds into next
**File:** `backend/convex/domain/agents/orchestration.ts`
**Acceptance Criteria:**
- [ ] Use Effect.gen for sequential composition
- [ ] Example: ClassifyAgent → (if technical) TechnicalAgent → QualityCheckAgent
- [ ] Pass results between steps (yield\* pattern)
- [ ] Short-circuit on errors (automatic with Effect)
- [ ] Add Effect.tap for logging intermediate results
- [ ] Return final result
### ⏳ Cycle 54: Conditional Agent Routing
**Status:** Pending
**Dependencies:** Cycle 53
**Task:** Route to different agents based on classification
**File:** `backend/convex/domain/agents/orchestration.ts`
**Acceptance Criteria:**
- [ ] Classify query type (technical, sales, support)
- [ ] Route to appropriate agent based on classification
- [ ] Use Effect conditional logic (ternary or if/else in Effect.gen)
- [ ] Fall back to general agent if classification fails
- [ ] Log routing decisions as events
- [ ] Test all routing paths
### ⏳ Cycle 55: Error Propagation Across Agents
**Status:** Pending
**Dependencies:** Cycle 54
**Task:** Handle errors from any agent in pipeline
**File:** `backend/convex/domain/agents/orchestration.ts`
**Acceptance Criteria:**
- [ ] Use Effect.catchTag for specific agent errors
- [ ] Example: Catch ClassificationError, use default route
- [ ] Example: Catch AgentError from any agent, return fallback response
- [ ] Use Effect.catchAll for unexpected errors
- [ ] Log all errors as events
- [ ] Graceful degradation (partial results)
### ⏳ Cycle 56: Research Workflow Implementation (Part 1: Structure)
**Status:** Pending
**Dependencies:** Cycle 55
**Task:** Define research workflow structure
**File:** `backend/convex/domain/workflows/research.ts`
**Acceptance Criteria:**
- [ ] Import workflow from services/workflow.service
- [ ] Define `researchWorkflow` with workflow.define
- [ ] Args: { query: v.string(), userId: v.string() }
- [ ] Return type: ResearchResult
- [ ] Stub handler (async function with steps)
- [ ] Plan 5 steps: Classify, Parallel Research, Synthesize, Generate Report, Save
### ⏳ Cycle 57: Research Workflow (Part 2: Parallel Research)
**Status:** Pending
**Dependencies:** Cycle 56
**Task:** Implement parallel research step
**File:** `backend/convex/domain/workflows/research.ts`
**Acceptance Criteria:**
- [ ] Step 2: Parallel research with Promise.all
- [ ] Run: webSearchAgent, academicAgent, newsAgent (all actions)
- [ ] Use step.runAction for each agent
- [ ] Collect results in array
- [ ] Handle failures (log but continue)
- [ ] Pass results to next step
### ⏳ Cycle 58: Research Workflow (Part 3: Synthesis with Effect)
**Status:** Pending
**Dependencies:** Cycle 57
**Task:** Synthesize findings using Effect services
**File:** `backend/convex/domain/workflows/research.ts`
**Acceptance Criteria:**
- [ ] Create `synthesisAgentWithEffect` internalAction
- [ ] Use Effect.gen for composition
- [ ] Inject AgentService and RAGService
- [ ] Fetch background context (RAGService.search)
- [ ] Synthesize findings with agent
- [ ] Add Effect.retry for robustness
- [ ] Return synthesis result
- [ ] Call from workflow step
### ⏳ Cycle 59: Research Workflow (Part 4: Report Generation)
**Status:** Pending
**Dependencies:** Cycle 58
**Task:** Generate final report
**File:** `backend/convex/domain/workflows/research.ts`
**Acceptance Criteria:**
- [ ] Step 4: Generate report (step.runAction)
- [ ] Create `reportGeneratorWithEffect` internalAction
- [ ] Use AgentService to format report
- [ ] Include: Summary, key findings, sources, recommendations
- [ ] Format as markdown
- [ ] Add Effect error handling
- [ ] Return formatted report
### ⏳ Cycle 60: Research Workflow (Part 5: Save and Notify)
**Status:** Pending
**Dependencies:** Cycle 59
**Task:** Save report and notify user
**File:** `backend/convex/domain/workflows/research.ts`
**Acceptance Criteria:**
- [ ] Step 5: Save report (step.runMutation)
- [ ] Create mutation to save to database
- [ ] Send notification email (optional action)
- [ ] Log workflow completion event
- [ ] Return final report
- [ ] Test complete workflow end-to-end
### ⏳ Cycle 61: Support Ticket Workflow (Part 1: Structure)
**Status:** Pending
**Dependencies:** Cycle 60
**Task:** Define support ticket workflow
**File:** `backend/convex/domain/workflows/support.ts`
**Acceptance Criteria:**
- [ ] Define `supportTicketWorkflow` with workflow.define
- [ ] Args: { userId: v.string(), issue: v.string() }
- [ ] Return type: SupportResult
- [ ] Plan 4 steps: Create thread, Generate response, Quality check, Save ticket
- [ ] Stub handler
### ⏳ Cycle 62: Support Workflow (Part 2: Create Thread)
**Status:** Pending
**Dependencies:** Cycle 61
**Task:** Create agent thread for support
**File:** `backend/convex/domain/workflows/support.ts`
**Acceptance Criteria:**
- [ ] Step 1: Fetch user context (step.runQuery)
- [ ] Step 2: Create agent thread (step.runAction)
- [ ] Use `createSupportThreadWithEffect` internalAction
- [ ] Inject AgentService and RAGService
- [ ] Fetch relevant KB articles (RAG)
- [ ] Create thread with context
- [ ] Return threadId and initial response
### ⏳ Cycle 63: Support Workflow (Part 3: Quality Check)
**Status:** Pending
**Dependencies:** Cycle 62
**Task:** Check response quality in parallel
**File:** `backend/convex/domain/workflows/support.ts`
**Acceptance Criteria:**
- [ ] Step 3: Parallel quality checks (Promise.all)
- [ ] Check grammar score (step.runAction)
- [ ] Check factuality score (step.runAction)
- [ ] Both use Effect services internally
- [ ] Return scores
- [ ] Refine response if scores < 0.8
### ⏳ Cycle 64: Support Workflow (Part 4: Refine Response)
**Status:** Pending
**Dependencies:** Cycle 63
**Task:** Refine response if quality checks fail
**File:** `backend/convex/domain/workflows/support.ts`
**Acceptance Criteria:**
- [ ] Conditional: If grammarScore < 0.8 OR factualityScore < 0.8
- [ ] Run: `refineResponseWithEffect` (step.runAction)
- [ ] Use Effect.retry (max 2 attempts)
- [ ] Re-run quality checks
- [ ] Return refined response or original if retries fail
- [ ] Log refinement attempts
### ⏳ Cycle 65: Support Workflow (Part 5: Save Ticket)
**Status:** Pending
**Dependencies:** Cycle 64
**Task:** Save support ticket to database
**File:** `backend/convex/domain/workflows/support.ts`
**Acceptance Criteria:**
- [ ] Step 4: Save ticket (step.runMutation)
- [ ] Store: userId, threadId, issue, response, qualityScores
- [ ] Create ticket entity in database
- [ ] Send notification to support team (optional)
- [ ] Log ticket creation event
- [ ] Return ticket result
### ⏳ Cycle 66: Tool Definition: Email Tool with Effect
**Status:** Pending
**Dependencies:** Cycle 65
**Task:** Create email tool using Effect services
**File:** `backend/convex/domain/agents/tools.ts`
**Acceptance Criteria:**
- [ ] Define `EmailService` Context.Tag
- [ ] Implement `EmailServiceLive` (uses SendGrid or Resend)
- [ ] Create `emailTool` with createTool
- [ ] Tool handler uses Effect.gen internally
- [ ] Inject EmailService (yield\* EmailService)
- [ ] Send email with service
- [ ] Convert Effect to Promise (Effect.runPromise)
- [ ] Return success/failure message
### ⏳ Cycle 67: Tool Definition: Database Query Tool with Effect
**Status:** Pending
**Dependencies:** Cycle 66
**Task:** Create database query tool using Effect
**File:** `backend/convex/domain/agents/tools.ts`
**Acceptance Criteria:**
- [ ] Define `DatabaseService` Context.Tag
- [ ] Implement `DatabaseServiceLive` (wraps ctx.db operations)
- [ ] Create `databaseQueryTool` with createTool
- [ ] Tool handler uses Effect.gen
- [ ] Inject DatabaseService
- [ ] Execute query (e.g., search users by email)
- [ ] Return results as string (formatted)
- [ ] Handle errors gracefully
### ⏳ Cycle 68: Tool Definition: External API Tool with Effect
**Status:** Pending
**Dependencies:** Cycle 67
**Task:** Create external API tool using Effect
**File:** `backend/convex/domain/agents/tools.ts`
**Acceptance Criteria:**
- [ ] Define `ExternalAPIService` Context.Tag
- [ ] Implement `ExternalAPIServiceLive` (uses fetch)
- [ ] Create `externalAPITool` with createTool
- [ ] Tool handler uses Effect.gen
- [ ] Inject ExternalAPIService
- [ ] Make API call with retry (Effect.retry)
- [ ] Parse response
- [ ] Return result to agent
### ⏳ Cycle 69: Error Handling in Agent Tools
**Status:** Pending
**Dependencies:** Cycle 68
**Task:** Handle errors gracefully in all tools
**File:** `backend/convex/domain/agents/tools.ts`
**Acceptance Criteria:**
- [ ] Wrap all tool operations in Effect.tryPromise
- [ ] Define tool-specific error types (EmailError, APIError, etc.)
- [ ] Use Effect.catchAll to return error messages
- [ ] Log tool errors as events
- [ ] Return helpful error messages to agent (not exceptions)
- [ ] Agent continues even if tool fails
### ⏳ Cycle 70: Register Tools with Agent
**Status:** Pending
**Dependencies:** Cycle 69
**Task:** Add all tools to Agent component
**File:** `backend/convex/services/agent.service.ts`
**Acceptance Criteria:**
- [ ] Import all tools (emailTool, databaseQueryTool, externalAPITool)
- [ ] Register in Agent config: `tools: { sendEmail: emailTool, queryDB: databaseQueryTool, callAPI: externalAPITool }`
- [ ] Agent can now call tools
- [ ] Test agent using tools (integration test)
- [ ] Verify Effect services injected correctly in tools
- [ ] Log tool usage metrics
---
## Observability & Testing Phase (Cycle 71-90)
**Agents:** agent-quality, agent-ops
**Goal:** Monitoring, testing, error handling, resource management
### ⏳ Cycle 71: Create MonitoringService with Effect
**Status:** Pending
**Dependencies:** Cycle 70
**Task:** Implement observability service
**File:** `backend/convex/services/monitoring.service.ts`
**Acceptance Criteria:**
- [ ] Define `MonitoringService` Context.Tag
- [ ] Interface: `trackServiceCall(name, duration, result)`, `trackError(error)`, `trackTokenUsage(tokens)`
- [ ] Implement `MonitoringServiceLive` (logs to console + database)
- [ ] Use Effect.tap to track service calls
- [ ] Use Effect.tapError to track errors
- [ ] Store metrics in database (events table)
- [ ] Export metrics for external tools (Sentry, Datadog)
### ⏳ Cycle 72: Track Service Call Lifecycle
**Status:** Pending
**Dependencies:** Cycle 71
**Task:** Log start, complete, fail for every service call
**File:** `backend/convex/lib/monitoring.ts`
**Acceptance Criteria:**
- [ ] Wrap service calls with Effect.tap
- [ ] Log service_call_started event (service name, args)
- [ ] Log service_call_completed event (service name, duration, result)
- [ ] Log service_call_failed event (service name, error, duration)
- [ ] Include trace ID for distributed tracing
- [ ] Store in events table with metadata
### ⏳ Cycle 73: Track Token Usage for AI Services
**Status:** Pending
**Dependencies:** Cycle 72
**Task:** Monitor AI model token consumption
**File:** `backend/convex/services/agent.service.ts`
**Acceptance Criteria:**
- [ ] Extract token usage from agent response (response.usage)
- [ ] Call `MonitoringService.trackTokenUsage`
- [ ] Store: promptTokens, completionTokens, totalTokens, model, timestamp
- [ ] Aggregate usage per user, per organization
- [ ] Alert if usage exceeds quota
- [ ] Display in usage dashboard (frontend)
### ⏳ Cycle 74: Error Tracking with Sentry Integration
**Status:** Pending
**Dependencies:** Cycle 73
**Task:** Send errors to Sentry for debugging
**File:** `backend/convex/lib/monitoring.ts`
**Acceptance Criteria:**
- [ ] Install `@sentry/node`
- [ ] Initialize Sentry in MonitoringService
- [ ] Capture Effect errors with Sentry.captureException
- [ ] Include: Error type, stack trace, service context, user context
- [ ] Group errors by error type (\_tag)
- [ ] Link Sentry issues to Convex functions
- [ ] Test error capture
### ⏳ Cycle 75: Performance Metrics Tracking
**Status:** Pending
**Dependencies:** Cycle 74
**Task:** Track latency per service operation
**File:** `backend/convex/lib/monitoring.ts`
**Acceptance Criteria:**
- [ ] Measure duration for every service call (Date.now())
- [ ] Store: service name, operation, duration, timestamp
- [ ] Calculate: p50, p95, p99 latency (in database query)
- [ ] Alert if latency exceeds threshold (p95 > 500ms)
- [ ] Display in monitoring dashboard
- [ ] Export to external APM (Application Performance Monitoring)
### ⏳ Cycle 76: Create Test Layers (Mock Implementations)
**Status:** Pending
**Dependencies:** Cycle 75
**Task:** Build test implementations for all services
**File:** `backend/convex/services/test-layers.ts`
**Acceptance Criteria:**
- [ ] Create `TestAgentServiceLive` with mock generateResponse
- [ ] Create `TestRAGServiceLive` with mock search
- [ ] Create `TestRateLimitServiceLive` with mock checkLimit
- [ ] Create `TestWorkflowServiceLive` with mock workflow steps
- [ ] Create `TestMonitoringServiceLive` (no-op logging)
- [ ] Export all test layers for use in tests
- [ ] Document how to use test layers
### ⏳ Cycle 77: Test AgentService with Mock Layer
**Status:** Pending
**Dependencies:** Cycle 76
**Task:** Write unit tests for AgentService using test layer
**File:** `backend/convex/services/agent.service.test.ts`
**Acceptance Criteria:**
- [ ] Test: `generateResponse` returns mock response
- [ ] Test: `createThread` returns deterministic threadId
- [ ] Test: Rate limit check (mocked RateLimitService)
- [ ] Test: Error handling (AgentError thrown and caught)
- [ ] Test: Retry logic (transient errors recover)
- [ ] All tests use `TestAgentServiceLive` layer
- [ ] All tests pass
### ⏳ Cycle 78: Test RAGService with Mock Layer
**Status:** Pending
**Dependencies:** Cycle 77
**Task:** Write unit tests for RAGService
**File:** `backend/convex/services/rag.service.test.ts`
**Acceptance Criteria:**
- [ ] Test: `search` returns mock results with scores
- [ ] Test: `addDocument` returns deterministic entryId
- [ ] Test: Error handling (SearchError, EmbeddingError)
- [ ] Test: Composition with AgentService (integration)
- [ ] Use `TestRAGServiceLive` layer
- [ ] All tests pass
### ⏳ Cycle 79: Test Effect Error Handling (Effect.catchTag)
**Status:** Pending
**Dependencies:** Cycle 78
**Task:** Validate error handling patterns
**File:** `backend/convex/domain/agents/orchestration.test.ts`
**Acceptance Criteria:**
- [ ] Test: Catch specific error (Effect.catchTag("AgentError"))
- [ ] Test: Catch all errors (Effect.catchAll)
- [ ] Test: Error propagation (child service error bubbles up)
- [ ] Test: Graceful degradation (return fallback on error)
- [ ] Test: Retry on specific errors (Effect.retry with Schedule.whileInput)
- [ ] All tests use test layers
- [ ] All tests pass
### ⏳ Cycle 80: Integration Tests with Real Components
**Status:** Pending
**Dependencies:** Cycle 79
**Task:** Test with actual Convex components (not mocks)
**File:** `backend/convex/integration/services.test.ts`
**Acceptance Criteria:**
- [ ] Test: AgentService with real @convex-dev/agent
- [ ] Test: RAGService with real @convex-dev/rag
- [ ] Test: RateLimitService with real @convex-dev/rate-limiter
- [ ] Test: End-to-end flow (create thread → search RAG → generate response)
- [ ] Test: Error handling with real components
- [ ] Test: Performance (latency within acceptable range)
- [ ] All integration tests pass
### ⏳ Cycle 81: Layered Error Handling Pattern
**Status:** Pending
**Dependencies:** Cycle 80
**Task:** Implement layered error handling strategy
**File:** `backend/convex/lib/error-handling.ts`
**Acceptance Criteria:**
- [ ] Domain errors: Business logic failures (UserNotFoundError)
- [ ] Infrastructure errors: Component failures (AgentError, RAGError)
- [ ] Handle domain errors specifically (Effect.catchTag)
- [ ] Handle infrastructure errors with retry (Effect.retry)
- [ ] Catch-all for unexpected errors (Effect.catchAll)
- [ ] Example implementation in orchestration.ts
- [ ] Document pattern
### ⏳ Cycle 82: Retry Strategies (Schedule.exponentia