From 2310c8cdfd38320b8a377f8bcb62b5023cb43594 Mon Sep 17 00:00:00 2001 From: Felipe Cardoso Date: Tue, 30 Dec 2025 02:13:16 +0100 Subject: [PATCH] feat: Add MCP server stubs, development docs, and Docker updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add MCP server skeleton implementations for all 7 planned servers (llm-gateway, knowledge-base, git, issues, filesystem, code-analysis, cicd) - Add comprehensive DEVELOPMENT.md with setup and usage instructions - Add BACKLOG.md with detailed phase planning - Update docker-compose.dev.yml with Redis and Celery workers - Update CLAUDE.md with Syndarix-specific context Addresses issues #16, #20, #21 πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- CLAUDE.md | 90 +- docker-compose.dev.yml | 113 +- docs/BACKLOG.md | 1656 +++++++++++++++++++++ docs/DEVELOPMENT.md | 377 +++++ mcp-servers/README.md | 70 + mcp-servers/cicd/pyproject.toml | 23 + mcp-servers/cicd/server.py | 47 + mcp-servers/code-analysis/pyproject.toml | 23 + mcp-servers/code-analysis/server.py | 47 + mcp-servers/filesystem/pyproject.toml | 23 + mcp-servers/filesystem/server.py | 47 + mcp-servers/git/pyproject.toml | 24 + mcp-servers/git/server.py | 66 + mcp-servers/issues/pyproject.toml | 23 + mcp-servers/issues/server.py | 76 + mcp-servers/knowledge-base/pyproject.toml | 24 + mcp-servers/knowledge-base/server.py | 162 ++ mcp-servers/llm-gateway/pyproject.toml | 23 + mcp-servers/llm-gateway/server.py | 148 ++ 19 files changed, 3060 insertions(+), 2 deletions(-) create mode 100644 docs/BACKLOG.md create mode 100644 docs/DEVELOPMENT.md create mode 100644 mcp-servers/README.md create mode 100644 mcp-servers/cicd/pyproject.toml create mode 100644 mcp-servers/cicd/server.py create mode 100644 mcp-servers/code-analysis/pyproject.toml create mode 100644 mcp-servers/code-analysis/server.py create mode 100644 mcp-servers/filesystem/pyproject.toml create mode 100644 mcp-servers/filesystem/server.py create mode 100644 mcp-servers/git/pyproject.toml create mode 100644 mcp-servers/git/server.py create mode 100644 mcp-servers/issues/pyproject.toml create mode 100644 mcp-servers/issues/server.py create mode 100644 mcp-servers/knowledge-base/pyproject.toml create mode 100644 mcp-servers/knowledge-base/server.py create mode 100644 mcp-servers/llm-gateway/pyproject.toml create mode 100644 mcp-servers/llm-gateway/server.py diff --git a/CLAUDE.md b/CLAUDE.md index 4fd2b01..1b3c037 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -53,7 +53,95 @@ docs/ ``` ### Current Phase -**Architecture Spikes** - Validating key decisions before implementation. +**Backlog Population** - Creating detailed issues for Phase 0-1 implementation. + +--- + +## Development Workflow & Standards + +**CRITICAL: These rules are mandatory for all development work.** + +### 1. Issue-Driven Development + +**Every piece of work MUST have an issue in the Gitea tracker first.** + +- Issue tracker: https://gitea.pragmazest.com/cardosofelipe/syndarix/issues +- Create detailed, well-scoped issues before starting work +- Structure issues to enable parallel work by multiple agents +- Reference issues in commits and PRs + +### 2. Git Hygiene + +**Branch naming convention:** `feature/123-description` + +- Every issue gets its own feature branch +- No direct commits to `main` or `dev` +- Keep branches focused and small +- Delete branches after merge + +**Workflow:** +``` +main (production-ready) + └── dev (integration branch) + └── feature/123-description (issue branch) +``` + +### 3. Testing Requirements + +**All code must be tested. No exceptions.** + +- **TDD preferred**: Write tests first when possible +- **Test after**: If not TDD, write tests immediately after testable code +- **Coverage types**: Unit, integration, functional, E2E as appropriate +- **Minimum coverage**: Aim for >90% on new code + +### 4. Code Review Process + +**Before merging any feature branch, code must pass multi-agent review:** + +| Check | Description | +|-------|-------------| +| Bug hunting | Logic errors, edge cases, race conditions | +| Linting | `ruff check` passes with no errors | +| Typing | `mypy` passes with no errors | +| Formatting | Code follows style guidelines | +| Performance | No obvious bottlenecks or N+1 queries | +| Security | No vulnerabilities (OWASP top 10) | +| Architecture | Follows established patterns and ADRs | + +**Issue is NOT done until review passes with flying colors.** + +### 5. QA Before Main + +**Before merging `dev` into `main`:** + +- Full test suite passes +- Manual QA verification +- Performance baseline check +- Security scan +- Code must be clean, functional, bug-free, well-architected, and secure + +### 6. Implementation Plan Updates + +- Keep `docs/architecture/IMPLEMENTATION_ROADMAP.md` updated +- Mark completed items as work progresses +- Add new items discovered during implementation + +### 7. UI/UX Design Approval + +**Frontend tasks involving UI/UX require design approval:** + +1. **Design Issue**: Create issue with `design` label +2. **Prototype**: Build interactive React prototype (navigable demo) +3. **Review**: User inspects and provides feedback +4. **Approval**: User approves before implementation begins +5. **Implementation**: Follow approved design, respecting design system + +**Design constraints:** +- Prototypes: Best effort to match design system (not required) +- Production code: MUST follow `frontend/docs/design-system/` strictly + +--- ### Key Extensions to Add (from PragmaStack base) - Celery + Redis for agent job queue diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 59f73f2..f839132 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -1,6 +1,6 @@ services: db: - image: postgres:17-alpine + image: pgvector/pgvector:pg17 volumes: - postgres_data_dev:/var/lib/postgresql/data/ environment: @@ -17,6 +17,21 @@ services: networks: - app-network + redis: + image: redis:7-alpine + ports: + - "6379:6379" + volumes: + - redis_data_dev:/data + command: redis-server --appendonly yes + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 5s + timeout: 5s + retries: 5 + networks: + - app-network + backend: build: context: ./backend @@ -37,13 +52,108 @@ services: - ENVIRONMENT=development - DEBUG=true - BACKEND_CORS_ORIGINS=${BACKEND_CORS_ORIGINS} + - REDIS_URL=redis://redis:6379/0 depends_on: db: condition: service_healthy + redis: + condition: service_healthy networks: - app-network command: ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"] + # Celery workers for background task processing (per ADR-003) + celery-agent: + build: + context: ./backend + dockerfile: Dockerfile + target: development + volumes: + - ./backend:/app + - /app/.venv + env_file: + - .env + environment: + - DATABASE_URL=${DATABASE_URL} + - REDIS_URL=redis://redis:6379/0 + - CELERY_QUEUE=agent + depends_on: + db: + condition: service_healthy + redis: + condition: service_healthy + networks: + - app-network + command: ["celery", "-A", "app.celery_app", "worker", "-Q", "agent", "-l", "info", "-c", "4"] + + celery-git: + build: + context: ./backend + dockerfile: Dockerfile + target: development + volumes: + - ./backend:/app + - /app/.venv + env_file: + - .env + environment: + - DATABASE_URL=${DATABASE_URL} + - REDIS_URL=redis://redis:6379/0 + - CELERY_QUEUE=git + depends_on: + db: + condition: service_healthy + redis: + condition: service_healthy + networks: + - app-network + command: ["celery", "-A", "app.celery_app", "worker", "-Q", "git", "-l", "info", "-c", "2"] + + celery-sync: + build: + context: ./backend + dockerfile: Dockerfile + target: development + volumes: + - ./backend:/app + - /app/.venv + env_file: + - .env + environment: + - DATABASE_URL=${DATABASE_URL} + - REDIS_URL=redis://redis:6379/0 + - CELERY_QUEUE=sync + depends_on: + db: + condition: service_healthy + redis: + condition: service_healthy + networks: + - app-network + command: ["celery", "-A", "app.celery_app", "worker", "-Q", "sync", "-l", "info", "-c", "2"] + + celery-beat: + build: + context: ./backend + dockerfile: Dockerfile + target: development + volumes: + - ./backend:/app + - /app/.venv + env_file: + - .env + environment: + - DATABASE_URL=${DATABASE_URL} + - REDIS_URL=redis://redis:6379/0 + depends_on: + db: + condition: service_healthy + redis: + condition: service_healthy + networks: + - app-network + command: ["celery", "-A", "app.celery_app", "beat", "-l", "info"] + frontend: build: context: ./frontend @@ -68,6 +178,7 @@ services: volumes: postgres_data_dev: + redis_data_dev: frontend_dev_modules: frontend_dev_next: diff --git a/docs/BACKLOG.md b/docs/BACKLOG.md new file mode 100644 index 0000000..e410538 --- /dev/null +++ b/docs/BACKLOG.md @@ -0,0 +1,1656 @@ +# Syndarix Backlog + +**Generated:** 2025-12-30 +**Status:** Ready for Gitea import + +This document contains detailed issues for Phase 0-1 implementation. Each issue is structured for parallel agent work. + +--- + +## Labels + +Create these labels in Gitea first: + +| Label | Color | Description | +|-------|-------|-------------| +| `phase-0` | #0052CC | Phase 0: Foundation | +| `phase-1` | #00875A | Phase 1: Core Platform | +| `backend` | #5319E7 | Backend work | +| `frontend` | #F9A825 | Frontend work | +| `devops` | #212121 | DevOps/Infrastructure work | +| `database` | #006B75 | Database/migrations | +| `design` | #D4388C | UI/UX design work | +| `blocked` | #B60205 | Blocked by dependency | +| `epic` | #7057FF | Epic/parent issue | + +--- + +## Phase 0: Foundation + +### EPIC: Phase 0 - Foundation Infrastructure + +**Issue #E01: [EPIC] Phase 0 - Foundation Infrastructure** + +``` +Title: [EPIC] Phase 0 - Foundation Infrastructure +Labels: epic, phase-0, devops + +## Overview +Complete the remaining foundation infrastructure setup for Syndarix development. + +## Child Issues +- [ ] #01 Configure CI/CD pipelines +- [ ] #02 Set up development environment documentation +- [ ] #03 Configure Redis for cache + pub/sub +- [ ] #04 Set up Celery worker infrastructure +- [ ] #05 Configure pgvector extension +- [ ] #06 Create MCP server directory structure +- [ ] #07 Set up Docker Compose for local development + +## Success Criteria +- All developers can run the full stack locally +- CI/CD runs tests on every PR +- All infrastructure components healthy +``` + +--- + +### Issue #01: Configure CI/CD pipelines + +``` +Title: Configure CI/CD pipelines for Syndarix +Labels: phase-0, devops + +## Description +Set up Gitea Actions CI/CD pipeline for the Syndarix repository. + +## Requirements + +### Backend Pipeline +- Run `uv run ruff check app` (linting) +- Run `uv run mypy app` (type checking) +- Run `IS_TEST=True uv run pytest --cov=app` (tests with coverage) +- Coverage threshold: 90% for new code + +### Frontend Pipeline +- Run `npm run lint` (ESLint) +- Run `npm run type-check` (TypeScript) +- Run `npm test` (Jest unit tests) + +### Pipeline Structure +1. `lint` job (fast feedback) +2. `test` job (depends on lint) +3. `build` job (depends on test) +4. `deploy` job (only on main, depends on build) + +## Acceptance Criteria +- [ ] `.gitea/workflows/ci.yaml` created +- [ ] Backend linting, typing, and tests pass +- [ ] Frontend linting, typing, and tests pass +- [ ] Coverage reports generated +- [ ] Pipeline fails on any check failure +- [ ] Documentation updated + +## Technical Notes +- Use `uv` for Python dependency management +- Reference: ADR-003 (Celery/Redis architecture) +- Celery workers not needed for CI tests + +## Assignable To +devops-engineer agent +``` + +--- + +### Issue #02: Development environment documentation + +``` +Title: Create development environment setup documentation +Labels: phase-0, devops + +## Description +Write comprehensive documentation for setting up the Syndarix development environment. + +## Requirements + +### Documentation Contents +1. Prerequisites (Python 3.12+, Node 20+, Docker, uv) +2. Repository cloning and setup +3. Environment variables configuration +4. Database setup (PostgreSQL with pgvector) +5. Redis setup +6. Running the backend (`uv run uvicorn`) +7. Running the frontend (`npm run dev`) +8. Running with Docker Compose +9. Running tests +10. Common troubleshooting + +### File Structure +- `docs/DEVELOPMENT.md` - Main setup guide +- `docs/TROUBLESHOOTING.md` - Common issues and solutions + +## Acceptance Criteria +- [ ] Fresh developer can set up environment following docs only +- [ ] All commands tested and working +- [ ] Environment variable templates provided +- [ ] Troubleshooting section covers common issues + +## Technical Notes +- Reference existing README.md but expand significantly +- Include both local and Docker-based setup options + +## Assignable To +devops-engineer agent +``` + +--- + +### Issue #03: Configure Redis for cache and pub/sub + +``` +Title: Configure Redis for cache and pub/sub +Labels: phase-0, devops, backend + +## Description +Set up Redis configuration for caching and real-time event pub/sub. + +## Requirements + +### Redis Configuration +- Connection pooling +- Health check endpoint +- Separate logical databases or key prefixes for: + - Cache (sessions, API responses) + - Pub/Sub (real-time events) + - Celery broker + +### Backend Integration +- Create `app/core/redis.py` with Redis client setup +- Add health check for Redis in `/health` endpoint +- Configure connection string from environment + +### Docker Compose +- Add Redis service with health check +- Volume for persistence +- Expose port for local development + +## Acceptance Criteria +- [ ] Redis service in Docker Compose +- [ ] Health check endpoint includes Redis status +- [ ] Connection pooling configured +- [ ] Cache operations working (set/get/expire) +- [ ] Pub/sub working (publish/subscribe) +- [ ] Tests for Redis operations + +## Technical Notes +- Reference: ADR-003 (Redis for cache/pub-sub) +- Reference: SPIKE-003 (Real-time communication) +- Use `redis.asyncio` for async support + +## Assignable To +backend-engineer agent (primary) +devops-engineer agent (Docker Compose) +``` + +--- + +### Issue #04: Set up Celery worker infrastructure + +``` +Title: Set up Celery worker infrastructure +Labels: phase-0, devops, backend + +## Description +Configure Celery for background task processing with Redis as broker. + +## Requirements + +### Queue Configuration +Per ADR-003: +| Queue | Workers | Purpose | +|-------|---------|---------| +| agent | 4 | High-priority agent tasks | +| git | 2 | Git operations | +| sync | 2 | Issue synchronization | +| default | 2 | General tasks | + +### Backend Integration +- Create `app/core/celery_app.py` with Celery configuration +- Create `app/tasks/` directory structure +- Create sample task for testing + +### Docker Compose +- Add Celery worker service per queue +- Add Celery beat for scheduled tasks (optional for Phase 0) +- Health checks for workers + +### Monitoring +- Flower for Celery monitoring (optional for Phase 0) + +## Acceptance Criteria +- [ ] Celery app configured with Redis broker +- [ ] All 4 queues defined and routable +- [ ] Worker services in Docker Compose +- [ ] Sample task executes successfully +- [ ] Workers restart on failure +- [ ] Health checks pass + +## Technical Notes +- Reference: ADR-003 (Celery task queue architecture) +- Reference: SPIKE-002 (Agent orchestration patterns) +- Use `celery[redis]` package + +## Assignable To +backend-engineer agent (Celery config) +devops-engineer agent (Docker Compose) +``` + +--- + +### Issue #05: Configure pgvector extension + +``` +Title: Configure pgvector extension for PostgreSQL +Labels: phase-0, devops, database + +## Description +Set up pgvector extension for vector similarity search (RAG knowledge base). + +## Requirements + +### Database Configuration +- Use `pgvector/pgvector:pg17` Docker image +- Enable pgvector extension via migration +- Create vector index configuration utilities + +### Migration +- Create migration to enable pgvector extension +- Document vector dimension choices (1536 for OpenAI, 1024 for Cohere) + +### Testing +- Verify extension loads correctly +- Test basic vector operations + +## Acceptance Criteria +- [ ] Docker Compose uses pgvector image +- [ ] Migration enables pgvector extension +- [ ] Vector operations working (cosine similarity) +- [ ] Health check includes pgvector status +- [ ] Documentation for vector dimension choices + +## Technical Notes +- Reference: ADR-007 (pgvector for RAG) +- Reference: SPIKE-006 (pgvector RAG research) +- Default to 1536 dimensions (OpenAI embedding size) + +## Assignable To +devops-engineer agent (Docker) +backend-engineer agent (migration) +``` + +--- + +### Issue #06: Create MCP server directory structure + +``` +Title: Create MCP server directory structure +Labels: phase-0, backend + +## Description +Set up the directory structure and base classes for MCP (Model Context Protocol) servers. + +## Requirements + +### Directory Structure +``` +mcp/ +β”œβ”€β”€ __init__.py +β”œβ”€β”€ base/ +β”‚ β”œβ”€β”€ __init__.py +β”‚ β”œβ”€β”€ server.py # Base MCP server class +β”‚ └── types.py # Common MCP types +β”œβ”€β”€ llm_gateway/ # Phase 2 +β”œβ”€β”€ knowledge_base/ # Phase 2 +β”œβ”€β”€ git_ops/ # Phase 2 +β”œβ”€β”€ issues/ # Phase 2 +└── README.md # MCP development guide +``` + +### Base Server Class +- FastMCP-based server template +- Standard tool registration pattern +- Project scoping utilities +- Error handling patterns + +### Documentation +- How to create a new MCP server +- Tool naming conventions +- Project scoping requirements + +## Acceptance Criteria +- [ ] Directory structure created +- [ ] Base server class with project scoping +- [ ] Type definitions for common patterns +- [ ] README with development guide +- [ ] Example tool registration + +## Technical Notes +- Reference: ADR-004 (MCP-first architecture) +- Reference: ADR-005 (LiteLLM integration via MCP) +- All tools must accept `project_id` for scoping + +## Assignable To +backend-engineer agent +``` + +--- + +### Issue #07: Set up Docker Compose for local development + +``` +Title: Set up complete Docker Compose for local development +Labels: phase-0, devops + +## Description +Create comprehensive Docker Compose configuration for running the full Syndarix stack locally. + +## Requirements + +### Services +1. `db` - PostgreSQL with pgvector +2. `redis` - Cache and message broker +3. `backend` - FastAPI application +4. `frontend` - Next.js application +5. `celery-agent` - Celery worker (agent queue) +6. `celery-git` - Celery worker (git queue) +7. `celery-sync` - Celery worker (sync queue) +8. `celery-default` - Celery worker (default queue) + +### Configuration +- Health checks for all services +- Proper dependency ordering (`depends_on` with conditions) +- Volume mounts for development (hot reload) +- Environment variable templates +- Resource limits (optional for dev) + +### Files +- `docker-compose.yaml` - Main compose file +- `docker-compose.override.yaml` - Development overrides +- `.env.example` - Environment template + +## Acceptance Criteria +- [ ] All services start with `docker compose up` +- [ ] Health checks pass for all services +- [ ] Hot reload works for backend and frontend +- [ ] Database data persists across restarts +- [ ] All services can communicate +- [ ] Documented in DEVELOPMENT.md + +## Technical Notes +- Reference: Issue #03 (Redis), #04 (Celery), #05 (pgvector) +- This issue depends on #03, #04, #05 completion + +## Dependencies +- Blocked by: #03, #04, #05 + +## Assignable To +devops-engineer agent +``` + +--- + +## Phase 1: Core Platform + +### EPIC: Phase 1 - Core Platform + +**Issue #E02: [EPIC] Phase 1 - Core Platform** + +``` +Title: [EPIC] Phase 1 - Core Platform +Labels: epic, phase-1 + +## Overview +Build the basic project and agent management system without LLM integration. + +## Child Issues + +### Data Model (1.1) +- [ ] #08 Create Project entity and CRUD +- [ ] #09 Create AgentType entity and CRUD +- [ ] #10 Create AgentInstance entity and CRUD +- [ ] #11 Create Issue entity with external tracker fields +- [ ] #12 Create Sprint entity and CRUD + +### API Layer (1.2) +- [ ] #13 Project management API endpoints +- [ ] #14 Agent type configuration API endpoints +- [ ] #15 Agent instance management API endpoints +- [ ] #16 Issue CRUD API endpoints +- [ ] #17 Sprint management API endpoints + +### Real-time Infrastructure (1.3) +- [ ] #18 Implement EventBus with Redis Pub/Sub +- [ ] #19 Create SSE endpoint for project events +- [ ] #20 Client-side SSE handling + +### Frontend Foundation (1.4) +- [ ] #21 [DESIGN] Project dashboard page +- [ ] #22 [DESIGN] Agent configuration UI +- [ ] #23 [DESIGN] Issue list and detail views +- [ ] #24 [DESIGN] Real-time activity feed component +- [ ] #25 Implement project dashboard +- [ ] #26 Implement agent configuration UI +- [ ] #27 Implement issue views +- [ ] #28 Implement activity feed +- [ ] #29 Navigation and layout + +## Success Criteria +- CRUD operations for all core entities +- Real-time event streaming working +- Basic admin UI for configuration +``` + +--- + +### Issue #08: Create Project entity and CRUD + +``` +Title: Create Project entity and CRUD operations +Labels: phase-1, backend, database + +## Description +Implement the Project entity and all CRUD operations. + +## Requirements + +### Entity Fields +```python +class Project(Base): + id: UUID + name: str + slug: str # URL-friendly identifier + description: Optional[str] + autonomy_level: AutonomyLevel # FULL_CONTROL, MILESTONE, AUTONOMOUS + status: ProjectStatus # ACTIVE, PAUSED, COMPLETED, ARCHIVED + settings: dict # JSON field for project-specific settings + owner_id: UUID # FK to User + + # Relationships + sprints: List[Sprint] + agent_instances: List[AgentInstance] + issues: List[Issue] + + # Timestamps + created_at: datetime + updated_at: datetime +``` + +### Enums +```python +class AutonomyLevel(str, Enum): + FULL_CONTROL = "full_control" # Approve every action + MILESTONE = "milestone" # Approve sprint boundaries + AUTONOMOUS = "autonomous" # Only major decisions + +class ProjectStatus(str, Enum): + ACTIVE = "active" + PAUSED = "paused" + COMPLETED = "completed" + ARCHIVED = "archived" +``` + +### CRUD Operations +- `create(db, obj_in: ProjectCreate) -> Project` +- `get(db, id: UUID) -> Optional[Project]` +- `get_by_slug(db, slug: str) -> Optional[Project]` +- `get_multi_by_owner(db, owner_id: UUID) -> List[Project]` +- `update(db, db_obj: Project, obj_in: ProjectUpdate) -> Project` +- `delete(db, id: UUID) -> None` + +### Tests +- Unit tests for all CRUD operations +- Test slug uniqueness +- Test owner relationship +- Test status transitions + +## Acceptance Criteria +- [ ] Model defined with all fields +- [ ] Migration created and applied +- [ ] CRUD class with all methods +- [ ] Pydantic schemas (Create, Update, InDB, Response) +- [ ] Unit tests with >90% coverage +- [ ] Async patterns (SQLAlchemy 2.0 style) + +## Technical Notes +- Reference: ADR-009 (Issue synchronization architecture) +- Follow existing CRUD patterns from PragmaStack +- Use custom exceptions from `app.core.exceptions` + +## Assignable To +backend-engineer agent +``` + +--- + +### Issue #09: Create AgentType entity and CRUD + +``` +Title: Create AgentType entity and CRUD operations +Labels: phase-1, backend, database + +## Description +Implement the AgentType entity representing agent templates. + +## Requirements + +### Entity Fields +```python +class AgentType(Base): + id: UUID + name: str # e.g., "Product Owner", "Backend Engineer" + slug: str # URL-friendly + description: str + expertise: List[str] # JSON array of expertise areas + personality_prompt: str # System prompt defining personality + + # Model Configuration + primary_model: str # e.g., "claude-opus-4.5" + fallback_models: List[str] # JSON array, in order of preference + model_params: dict # temperature, max_tokens, etc. + + # MCP Configuration + mcp_servers: List[str] # Which MCP servers this agent can use + tool_permissions: dict # Tool-level permissions + + # Metadata + is_active: bool + created_at: datetime + updated_at: datetime +``` + +### CRUD Operations +- `create(db, obj_in: AgentTypeCreate) -> AgentType` +- `get(db, id: UUID) -> Optional[AgentType]` +- `get_by_slug(db, slug: str) -> Optional[AgentType]` +- `get_all_active(db) -> List[AgentType]` +- `update(db, db_obj: AgentType, obj_in: AgentTypeUpdate) -> AgentType` +- `delete(db, id: UUID) -> None` (soft delete via is_active) + +### Seed Data +Create initial agent types: +- Product Owner +- Business Analyst +- Solutions Architect +- Backend Engineer +- Frontend Engineer +- QA Engineer +- DevOps Engineer + +### Tests +- CRUD operations +- Model configuration validation +- MCP server permissions + +## Acceptance Criteria +- [ ] Model defined with all fields +- [ ] Migration created +- [ ] CRUD operations implemented +- [ ] Pydantic schemas +- [ ] Seed data script +- [ ] Unit tests with >90% coverage + +## Technical Notes +- Reference: ADR-002 (Agent orchestration) +- Reference: SPIKE-002 (Agent orchestration research) +- `model_params` should be validated against known LLM parameters + +## Assignable To +backend-engineer agent +``` + +--- + +### Issue #10: Create AgentInstance entity and CRUD + +``` +Title: Create AgentInstance entity and CRUD operations +Labels: phase-1, backend, database + +## Description +Implement AgentInstance entity representing spawned agents working on projects. + +## Requirements + +### Entity Fields +```python +class AgentInstance(Base): + id: UUID + agent_type_id: UUID # FK to AgentType + project_id: UUID # FK to Project + + # Instance State + status: AgentStatus # IDLE, WORKING, WAITING, PAUSED, TERMINATED + current_task: Optional[str] # Description of current work + + # Memory (per SPIKE-002) + short_term_memory: dict # Current context, clears between tasks + long_term_memory_ref: Optional[str] # Reference to RAG collection + + # Session + session_id: Optional[str] # Current active session + last_activity_at: Optional[datetime] + + # Metrics + tasks_completed: int + tokens_used: int + cost_incurred: float + + # Timestamps + created_at: datetime + updated_at: datetime + terminated_at: Optional[datetime] +``` + +### Enums +```python +class AgentStatus(str, Enum): + IDLE = "idle" + WORKING = "working" + WAITING = "waiting" # Waiting for human approval + PAUSED = "paused" + TERMINATED = "terminated" +``` + +### CRUD Operations +- `create(db, obj_in) -> AgentInstance` +- `get(db, id: UUID) -> Optional[AgentInstance]` +- `get_by_project(db, project_id: UUID) -> List[AgentInstance]` +- `get_active_by_project(db, project_id: UUID) -> List[AgentInstance]` +- `update_status(db, id: UUID, status: AgentStatus) -> AgentInstance` +- `update_metrics(db, id: UUID, tokens: int, cost: float) -> AgentInstance` +- `terminate(db, id: UUID) -> AgentInstance` + +### Tests +- CRUD operations +- Status transitions +- Metrics accumulation +- Project relationship + +## Acceptance Criteria +- [ ] Model with all fields +- [ ] Migration created +- [ ] CRUD operations +- [ ] Status transition validation +- [ ] Pydantic schemas +- [ ] Unit tests with >90% coverage + +## Technical Notes +- Reference: ADR-002 (Agent orchestration) +- Reference: SPIKE-007 (Inter-agent communication) +- short_term_memory should be cleared on task completion + +## Assignable To +backend-engineer agent +``` + +--- + +### Issue #11: Create Issue entity with external tracker fields + +``` +Title: Create Issue entity with external tracker fields +Labels: phase-1, backend, database + +## Description +Implement Issue entity that syncs with external trackers (Gitea, GitHub, GitLab). + +## Requirements + +### Entity Fields +```python +class Issue(Base): + id: UUID + project_id: UUID # FK to Project + + # Local Fields + title: str + body: str + status: IssueStatus + priority: IssuePriority + labels: List[str] # JSON array + + # Assignment + assigned_agent_id: Optional[UUID] # FK to AgentInstance + human_assignee: Optional[str] + + # Sprint + sprint_id: Optional[UUID] # FK to Sprint + story_points: Optional[int] + + # External Tracker Sync (per ADR-009) + external_tracker: Optional[str] # 'gitea', 'github', 'gitlab' + external_id: Optional[str] # Issue ID in external system + external_url: Optional[str] # Direct link + external_number: Optional[int] # Issue number + sync_status: SyncStatus + last_synced_at: Optional[datetime] + external_updated_at: Optional[datetime] # Conflict detection + + # Timestamps + created_at: datetime + updated_at: datetime + closed_at: Optional[datetime] +``` + +### Enums +```python +class IssueStatus(str, Enum): + OPEN = "open" + IN_PROGRESS = "in_progress" + IN_REVIEW = "in_review" + BLOCKED = "blocked" + CLOSED = "closed" + +class IssuePriority(str, Enum): + LOW = "low" + MEDIUM = "medium" + HIGH = "high" + CRITICAL = "critical" + +class SyncStatus(str, Enum): + SYNCED = "synced" + PENDING = "pending" + CONFLICT = "conflict" + ERROR = "error" +``` + +### CRUD Operations +- Standard CRUD +- `get_by_external_id(db, tracker, external_id) -> Optional[Issue]` +- `get_pending_sync(db, project_id: UUID) -> List[Issue]` +- `get_by_sprint(db, sprint_id: UUID) -> List[Issue]` +- `get_assigned_to_agent(db, agent_id: UUID) -> List[Issue]` + +### Tests +- CRUD operations +- External sync field handling +- Sprint assignment +- Agent assignment + +## Acceptance Criteria +- [ ] Model with all fields +- [ ] Migration created +- [ ] CRUD operations +- [ ] Conflict detection logic +- [ ] Pydantic schemas +- [ ] Unit tests with >90% coverage + +## Technical Notes +- Reference: ADR-009 (Issue synchronization) +- Reference: SPIKE-009 (Issue synchronization research) +- `external_updated_at` used for conflict detection + +## Assignable To +backend-engineer agent +``` + +--- + +### Issue #12: Create Sprint entity and CRUD + +``` +Title: Create Sprint entity and CRUD operations +Labels: phase-1, backend, database + +## Description +Implement Sprint entity for organizing work into time-boxed iterations. + +## Requirements + +### Entity Fields +```python +class Sprint(Base): + id: UUID + project_id: UUID # FK to Project + + # Sprint Info + name: str + number: int # Sequential sprint number + goal: Optional[str] + + # Dates + start_date: date + end_date: date + + # Status + status: SprintStatus + + # Velocity + planned_points: Optional[int] + completed_points: Optional[int] + + # Relationships + issues: List[Issue] + + # Timestamps + created_at: datetime + updated_at: datetime +``` + +### Enums +```python +class SprintStatus(str, Enum): + PLANNED = "planned" + ACTIVE = "active" + COMPLETED = "completed" + CANCELLED = "cancelled" +``` + +### CRUD Operations +- Standard CRUD +- `get_active(db, project_id: UUID) -> Optional[Sprint]` +- `get_by_project(db, project_id: UUID) -> List[Sprint]` +- `start_sprint(db, id: UUID) -> Sprint` +- `complete_sprint(db, id: UUID) -> Sprint` +- `get_next_number(db, project_id: UUID) -> int` + +### Tests +- CRUD operations +- Status transitions +- Sprint overlap prevention +- Velocity calculation + +## Acceptance Criteria +- [ ] Model with all fields +- [ ] Migration created +- [ ] CRUD operations +- [ ] Business logic (start, complete) +- [ ] Pydantic schemas +- [ ] Unit tests with >90% coverage + +## Technical Notes +- Reference: ADR-012 (Client approval flow) +- Only one sprint can be ACTIVE per project + +## Assignable To +backend-engineer agent +``` + +--- + +### Issue #13: Project management API endpoints + +``` +Title: Create Project management API endpoints +Labels: phase-1, backend + +## Description +Implement REST API endpoints for Project CRUD operations. + +## Requirements + +### Endpoints +``` +POST /api/v1/projects - Create project +GET /api/v1/projects - List user's projects +GET /api/v1/projects/{id} - Get project details +GET /api/v1/projects/slug/{slug} - Get project by slug +PATCH /api/v1/projects/{id} - Update project +DELETE /api/v1/projects/{id} - Archive project +POST /api/v1/projects/{id}/pause - Pause project +POST /api/v1/projects/{id}/resume - Resume project +``` + +### Authorization +- Users can only access their own projects +- Superusers can access all projects +- Owner check on all mutations + +### Response Schema +```json +{ + "id": "uuid", + "name": "string", + "slug": "string", + "description": "string", + "autonomy_level": "string", + "status": "string", + "settings": {}, + "owner": {...}, + "stats": { + "active_agents": 0, + "open_issues": 0, + "current_sprint": null + }, + "created_at": "datetime", + "updated_at": "datetime" +} +``` + +### Tests +- All endpoints with valid data +- Authorization (own projects only) +- Validation errors +- 404 handling +- Status transitions + +## Acceptance Criteria +- [ ] All endpoints implemented +- [ ] Authorization enforced +- [ ] Proper error responses +- [ ] Rate limiting configured +- [ ] Integration tests +- [ ] OpenAPI schema updated + +## Dependencies +- Depends on: #08 (Project entity) + +## Assignable To +backend-engineer agent +``` + +--- + +### Issue #14: Agent type configuration API endpoints + +``` +Title: Create Agent type configuration API endpoints +Labels: phase-1, backend + +## Description +Implement REST API endpoints for AgentType management. + +## Requirements + +### Endpoints +``` +POST /api/v1/agent-types - Create agent type (admin) +GET /api/v1/agent-types - List all active types +GET /api/v1/agent-types/{id} - Get agent type details +GET /api/v1/agent-types/slug/{slug} - Get by slug +PATCH /api/v1/agent-types/{id} - Update type (admin) +DELETE /api/v1/agent-types/{id} - Deactivate type (admin) +``` + +### Authorization +- Read endpoints: authenticated users +- Write endpoints: superusers only + +### Response Schema +Include model configuration, MCP permissions, and instance counts. + +### Tests +- All endpoints +- Admin-only enforcement +- Validation (model names, MCP servers) + +## Acceptance Criteria +- [ ] All endpoints implemented +- [ ] Admin authorization enforced +- [ ] Model validation +- [ ] Integration tests +- [ ] OpenAPI schema updated + +## Dependencies +- Depends on: #09 (AgentType entity) + +## Assignable To +backend-engineer agent +``` + +--- + +### Issue #15: Agent instance management API endpoints + +``` +Title: Create Agent instance management API endpoints +Labels: phase-1, backend + +## Description +Implement REST API endpoints for AgentInstance lifecycle management. + +## Requirements + +### Endpoints +``` +POST /api/v1/projects/{pid}/agents - Spawn agent +GET /api/v1/projects/{pid}/agents - List project agents +GET /api/v1/projects/{pid}/agents/{id} - Get agent details +PATCH /api/v1/projects/{pid}/agents/{id} - Update agent +POST /api/v1/projects/{pid}/agents/{id}/pause - Pause agent +POST /api/v1/projects/{pid}/agents/{id}/resume - Resume agent +DELETE /api/v1/projects/{pid}/agents/{id} - Terminate agent +GET /api/v1/projects/{pid}/agents/{id}/metrics - Get agent metrics +``` + +### Authorization +- Project owner or superuser only +- Agents scoped to projects + +### Response Schema +Include status, current task, metrics, and memory summary. + +### Tests +- All endpoints +- Project ownership check +- Status transitions +- Metrics calculation + +## Acceptance Criteria +- [ ] All endpoints implemented +- [ ] Project scoping enforced +- [ ] Status transitions validated +- [ ] Metrics endpoint accurate +- [ ] Integration tests +- [ ] OpenAPI schema updated + +## Dependencies +- Depends on: #08 (Project), #10 (AgentInstance) + +## Assignable To +backend-engineer agent +``` + +--- + +### Issue #16: Issue CRUD API endpoints + +``` +Title: Create Issue CRUD API endpoints +Labels: phase-1, backend + +## Description +Implement REST API endpoints for Issue management. + +## Requirements + +### Endpoints +``` +POST /api/v1/projects/{pid}/issues - Create issue +GET /api/v1/projects/{pid}/issues - List issues (filters) +GET /api/v1/projects/{pid}/issues/{id} - Get issue details +PATCH /api/v1/projects/{pid}/issues/{id} - Update issue +DELETE /api/v1/projects/{pid}/issues/{id} - Delete issue +POST /api/v1/projects/{pid}/issues/{id}/assign - Assign to agent +POST /api/v1/projects/{pid}/issues/{id}/sync - Trigger sync +``` + +### Query Filters +- status, priority, labels, sprint_id, assigned_agent_id +- search (title/body) +- sync_status + +### Response Schema +Include external tracker info, assignment, sprint. + +### Tests +- All endpoints +- Filtering and search +- Assignment validation +- Sync trigger + +## Acceptance Criteria +- [ ] All endpoints implemented +- [ ] Filtering works correctly +- [ ] Assignment validation +- [ ] Sync trigger initiates background job +- [ ] Integration tests +- [ ] OpenAPI schema updated + +## Dependencies +- Depends on: #08 (Project), #11 (Issue) + +## Assignable To +backend-engineer agent +``` + +--- + +### Issue #17: Sprint management API endpoints + +``` +Title: Create Sprint management API endpoints +Labels: phase-1, backend + +## Description +Implement REST API endpoints for Sprint management. + +## Requirements + +### Endpoints +``` +POST /api/v1/projects/{pid}/sprints - Create sprint +GET /api/v1/projects/{pid}/sprints - List sprints +GET /api/v1/projects/{pid}/sprints/active - Get active sprint +GET /api/v1/projects/{pid}/sprints/{id} - Get sprint details +PATCH /api/v1/projects/{pid}/sprints/{id} - Update sprint +POST /api/v1/projects/{pid}/sprints/{id}/start - Start sprint +POST /api/v1/projects/{pid}/sprints/{id}/complete - Complete sprint +GET /api/v1/projects/{pid}/sprints/{id}/issues - Get sprint issues +POST /api/v1/projects/{pid}/sprints/{id}/issues - Add issue to sprint +``` + +### Business Rules +- Only one active sprint per project +- Cannot modify completed sprints +- Start date validation + +### Response Schema +Include issues, velocity metrics, progress. + +### Tests +- All endpoints +- Business rules enforcement +- Velocity calculation + +## Acceptance Criteria +- [ ] All endpoints implemented +- [ ] Business rules enforced +- [ ] Velocity metrics accurate +- [ ] Integration tests +- [ ] OpenAPI schema updated + +## Dependencies +- Depends on: #08 (Project), #11 (Issue), #12 (Sprint) + +## Assignable To +backend-engineer agent +``` + +--- + +### Issue #18: Implement EventBus with Redis Pub/Sub + +``` +Title: Implement EventBus with Redis Pub/Sub +Labels: phase-1, backend + +## Description +Create centralized event bus for real-time notifications using Redis Pub/Sub. + +## Requirements + +### EventBus Class +```python +class EventBus: + async def publish(self, channel: str, event: Event) -> None + async def subscribe(self, channels: List[str]) -> AsyncIterator[Event] + def get_project_channel(self, project_id: UUID) -> str + def get_agent_channel(self, agent_id: UUID) -> str +``` + +### Event Types +```python +class EventType(str, Enum): + # Agent Events + AGENT_SPAWNED = "agent.spawned" + AGENT_STATUS_CHANGED = "agent.status_changed" + AGENT_MESSAGE = "agent.message" + AGENT_TERMINATED = "agent.terminated" + + # Issue Events + ISSUE_CREATED = "issue.created" + ISSUE_UPDATED = "issue.updated" + ISSUE_ASSIGNED = "issue.assigned" + ISSUE_CLOSED = "issue.closed" + + # Sprint Events + SPRINT_STARTED = "sprint.started" + SPRINT_COMPLETED = "sprint.completed" + + # Approval Events + APPROVAL_REQUESTED = "approval.requested" + APPROVAL_GRANTED = "approval.granted" + APPROVAL_DENIED = "approval.denied" +``` + +### Event Schema +```python +class Event(BaseModel): + id: str + type: EventType + timestamp: datetime + project_id: UUID + actor_id: Optional[UUID] # Agent or user who triggered + actor_type: str # 'agent', 'user', 'system' + payload: dict +``` + +### Tests +- Publish/subscribe cycle +- Multiple subscribers +- Channel isolation +- Event serialization + +## Acceptance Criteria +- [ ] EventBus class implemented +- [ ] All event types defined +- [ ] Redis Pub/Sub working +- [ ] Project channel isolation +- [ ] Unit tests +- [ ] Integration tests with real Redis + +## Technical Notes +- Reference: SPIKE-003 (Real-time communication) +- Reference: ADR-003 (Redis pub/sub) +- Use `redis.asyncio` for async support + +## Assignable To +backend-engineer agent +``` + +--- + +### Issue #19: Create SSE endpoint for project events + +``` +Title: Create SSE endpoint for project events +Labels: phase-1, backend + +## Description +Implement Server-Sent Events (SSE) endpoint for real-time project updates. + +## Requirements + +### Endpoint +``` +GET /api/v1/projects/{pid}/events/stream +``` + +### Implementation +```python +@router.get("/projects/{project_id}/events/stream") +async def stream_events( + project_id: UUID, + current_user: User = Depends(get_current_user), + event_bus: EventBus = Depends(get_event_bus) +): + # Authorization check + # Subscribe to project channel + # Yield SSE formatted events + # Keepalive every 30s +``` + +### SSE Format +``` +event: agent.status_changed +data: {"id": "...", "type": "agent.status_changed", ...} + +: keepalive + +event: issue.created +data: {...} +``` + +### Features +- Automatic reconnection support (Last-Event-ID) +- Keepalive every 30 seconds +- Connection cleanup on disconnect +- Rate limiting + +### Tests +- Event streaming +- Keepalive mechanism +- Authorization +- Reconnection + +## Acceptance Criteria +- [ ] SSE endpoint implemented +- [ ] Events stream correctly +- [ ] Keepalive working +- [ ] Authorization enforced +- [ ] Last-Event-ID support +- [ ] Integration tests + +## Dependencies +- Depends on: #18 (EventBus) + +## Assignable To +backend-engineer agent +``` + +--- + +### Issue #20: Client-side SSE handling + +``` +Title: Implement client-side SSE handling +Labels: phase-1, frontend + +## Description +Create React hooks and utilities for consuming SSE events. + +## Requirements + +### Hook: useProjectEvents +```typescript +function useProjectEvents(projectId: string): { + events: ProjectEvent[]; + isConnected: boolean; + error: Error | null; + reconnect: () => void; +} +``` + +### Features +- Automatic reconnection with exponential backoff +- Event parsing and type safety +- Connection state management +- Event buffer (last 100 events) + +### Event Store +```typescript +interface EventStore { + events: ProjectEvent[]; + addEvent: (event: ProjectEvent) => void; + clearEvents: () => void; +} +``` + +### Components +- ConnectionStatus indicator +- EventList component (for activity feed) + +### Tests +- Hook behavior +- Reconnection logic +- Event parsing +- Store management + +## Acceptance Criteria +- [ ] useProjectEvents hook implemented +- [ ] Auto-reconnection working +- [ ] Type-safe event handling +- [ ] Connection status UI +- [ ] Unit tests + +## Dependencies +- Depends on: #19 (SSE endpoint) + +## Assignable To +frontend-engineer agent +``` + +--- + +### Issue #21: [DESIGN] Project dashboard page + +``` +Title: [DESIGN] Project dashboard page +Labels: phase-1, frontend, design + +## Description +Design interactive React prototype for the project dashboard page. + +## Requirements + +### Page Sections +1. **Header**: Project name, status badge, autonomy level, quick actions +2. **Agent Panel**: Active agents, their status, current tasks +3. **Sprint Overview**: Current sprint progress, burndown +4. **Recent Activity**: Real-time event feed +5. **Issue Summary**: Open/in-progress/blocked counts + +### Interactions +- Click agent to view details +- Click sprint to view backlog +- Real-time activity updates +- Status change animations + +### Responsive Design +- Desktop: Multi-column layout +- Tablet: Stacked sections +- Mobile: Single column, collapsible sections + +## Deliverables +- `frontend/prototypes/project-dashboard/page.tsx` +- `frontend/prototypes/project-dashboard/README.md` +- Screenshots in issue comments + +## Acceptance Criteria +- [ ] Prototype navigable in browser +- [ ] All sections represented +- [ ] Interactive elements work +- [ ] Responsive breakpoints +- [ ] Design decisions documented +- [ ] User approval obtained + +## Assignable To +ui-designer agent +``` + +--- + +### Issue #22: [DESIGN] Agent configuration UI + +``` +Title: [DESIGN] Agent configuration UI +Labels: phase-1, frontend, design + +## Description +Design interactive React prototype for agent type configuration. + +## Requirements + +### Views +1. **Agent Type List**: All available types with status +2. **Agent Type Detail**: Full configuration view +3. **Agent Type Editor**: Form for creating/editing + +### Configuration Fields +- Name, description, expertise areas +- Model selection (primary + fallbacks) +- Model parameters (temperature, etc.) +- MCP server permissions +- Personality prompt + +### Interactions +- Create new type +- Edit existing type +- Duplicate type +- Deactivate type +- Test configuration + +## Deliverables +- `frontend/prototypes/agent-config/page.tsx` +- `frontend/prototypes/agent-config/README.md` +- Screenshots in issue comments + +## Acceptance Criteria +- [ ] All views represented +- [ ] Form interactions work +- [ ] Model selection UI clear +- [ ] Permission editor intuitive +- [ ] User approval obtained + +## Assignable To +ui-designer agent +``` + +--- + +### Issue #23: [DESIGN] Issue list and detail views + +``` +Title: [DESIGN] Issue list and detail views +Labels: phase-1, frontend, design + +## Description +Design interactive React prototype for issue management views. + +## Requirements + +### Issue List View +- Filterable by status, priority, labels, sprint, assignee +- Sortable columns +- Bulk actions (assign, move to sprint, change status) +- Quick status change +- Sync status indicator + +### Issue Detail View +- Full issue content (markdown) +- Status workflow buttons +- Assignment panel +- Sprint assignment +- External tracker link +- Activity timeline + +### Interactions +- Filter/sort +- Inline status change +- Assign to agent +- Add to sprint + +## Deliverables +- `frontend/prototypes/issues/page.tsx` +- `frontend/prototypes/issues/README.md` +- Screenshots in issue comments + +## Acceptance Criteria +- [ ] List and detail views +- [ ] Filters functional +- [ ] Status workflow clear +- [ ] Sync status visible +- [ ] User approval obtained + +## Assignable To +ui-designer agent +``` + +--- + +### Issue #24: [DESIGN] Real-time activity feed component + +``` +Title: [DESIGN] Real-time activity feed component +Labels: phase-1, frontend, design + +## Description +Design interactive React prototype for the activity feed component. + +## Requirements + +### Event Types to Display +- Agent status changes +- Agent messages +- Issue updates +- Sprint events +- Approval requests + +### Features +- Real-time updates (simulated) +- Event grouping by time +- Event type icons +- Click to expand details +- Connection status indicator + +### Interactions +- Auto-scroll to new events +- Pause auto-scroll on hover +- Filter by event type +- Mark as read + +## Deliverables +- `frontend/prototypes/activity-feed/page.tsx` +- `frontend/prototypes/activity-feed/README.md` +- Screenshots in issue comments + +## Acceptance Criteria +- [ ] All event types represented +- [ ] Real-time feel (simulated) +- [ ] Filtering works +- [ ] Visual hierarchy clear +- [ ] User approval obtained + +## Assignable To +ui-designer agent +``` + +--- + +### Issues #25-29: Implementation issues + +*(These are created after design approval and follow the approved designs)* + +``` +Issue #25: Implement project dashboard +Labels: phase-1, frontend +Dependencies: #13, #18, #19, #20, #21 (approved) + +Issue #26: Implement agent configuration UI +Labels: phase-1, frontend +Dependencies: #14, #22 (approved) + +Issue #27: Implement issue views +Labels: phase-1, frontend +Dependencies: #16, #23 (approved) + +Issue #28: Implement activity feed +Labels: phase-1, frontend +Dependencies: #19, #20, #24 (approved) + +Issue #29: Navigation and layout +Labels: phase-1, frontend +Dependencies: None (can be done in parallel) +``` + +--- + +## Parallel Work Tracks + +These issues can be worked on in parallel: + +### Track 1: DevOps (Issues #01, #02, #03, #04, #05, #07) +**Agent:** devops-engineer +**Parallelizable:** #01, #02 can run parallel. #03, #04, #05 can run parallel. #07 depends on all. + +### Track 2: Backend Data Model (Issues #08, #09, #10, #11, #12) +**Agent:** backend-engineer +**Parallelizable:** #08, #09 can run parallel. #10, #11, #12 can run after. + +### Track 3: Backend API (Issues #13-17) +**Agent:** backend-engineer +**Parallelizable:** After data models. Can parallelize API issues once entities exist. + +### Track 4: Real-time (Issues #18, #19, #20) +**Agent:** backend-engineer (18, 19), frontend-engineer (20) +**Parallelizable:** Sequential. + +### Track 5: UI Design (Issues #21, #22, #23, #24) +**Agent:** ui-designer +**Parallelizable:** All can run in parallel. + +### Track 6: Frontend Implementation (Issues #25-29) +**Agent:** frontend-engineer +**Parallelizable:** After design approval. Can parallelize implementations. + +--- + +## Dependency Graph + +``` +Phase 0: +#01, #02 ─────────────────────┐ +#03 ──────────────────────────┼──▢ #07 (Docker Compose) +#04 ─────────────────────────── +#05 ─────────────────────────── +#06 β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +Phase 1 - Data Model: +#08 (Project) ────────────────┬──▢ #10 (AgentInstance) +#09 (AgentType) ─────────────── + └──▢ #11 (Issue) ──▢ #12 (Sprint) + +Phase 1 - API: +#08 ──▢ #13 (Project API) +#09 ──▢ #14 (AgentType API) +#08, #10 ──▢ #15 (AgentInstance API) +#08, #11 ──▢ #16 (Issue API) +#08, #11, #12 ──▢ #17 (Sprint API) + +Phase 1 - Real-time: +#03 ──▢ #18 (EventBus) ──▢ #19 (SSE) ──▢ #20 (Client SSE) + +Phase 1 - UI: +#21, #22, #23, #24 (Design) ──[approval]──▢ #25, #26, #27, #28, #29 (Implementation) +``` diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md new file mode 100644 index 0000000..0e4557a --- /dev/null +++ b/docs/DEVELOPMENT.md @@ -0,0 +1,377 @@ +# Syndarix Development Environment + +This guide covers setting up and running the Syndarix development environment. + +## Prerequisites + +- Docker & Docker Compose v2+ +- Python 3.12+ +- Node.js 20+ +- uv (Python package manager) +- Git + +## Quick Start + +```bash +# Clone the repository +git clone https://gitea.pragmazest.com/cardosofelipe/syndarix.git +cd syndarix + +# Copy environment template +cp .env.example .env + +# Start all services +docker-compose -f docker-compose.dev.yml up -d + +# View logs +docker-compose logs -f +``` + +## Architecture Overview + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Docker Compose Development β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ PostgreSQLβ”‚ β”‚ Redis β”‚ β”‚ Backend β”‚ β”‚ Frontend β”‚ β”‚ +β”‚ β”‚ (pgvector)β”‚ β”‚ β”‚ β”‚ (FastAPI)β”‚ β”‚ (Next.js) β”‚ β”‚ +β”‚ β”‚ :5432 β”‚ β”‚ :6379 β”‚ β”‚ :8000 β”‚ β”‚ :3000 β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ Celery Workers β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ celery-agentβ”‚ β”‚ celery-git β”‚ β”‚ celery-sync β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ (4 workers)β”‚ β”‚ (2 workers)β”‚ β”‚ (2 workers)β”‚ β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ +β”‚ β”‚ β”‚ celery-beat β”‚ (Scheduler) β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## Services + +### Core Services + +| Service | Port | Description | +|---------|------|-------------| +| db | 5432 | PostgreSQL 17 with pgvector extension | +| redis | 6379 | Redis 7 for cache, pub/sub, Celery broker | +| backend | 8000 | FastAPI backend | +| frontend | 3000 | Next.js frontend | + +### Celery Workers + +| Worker | Queue | Concurrency | Purpose | +|--------|-------|-------------|---------| +| celery-agent | agent | 4 | Agent execution tasks | +| celery-git | git | 2 | Git operations | +| celery-sync | sync | 2 | Issue synchronization | +| celery-beat | - | 1 | Scheduled task scheduler | + +## Environment Variables + +Copy `.env.example` to `.env` and configure: + +```bash +# Database +POSTGRES_USER=syndarix +POSTGRES_PASSWORD=your_secure_password +POSTGRES_DB=syndarix +DATABASE_URL=postgresql://syndarix:your_secure_password@db:5432/syndarix + +# Redis +REDIS_URL=redis://redis:6379/0 + +# Security +SECRET_KEY=your_32_character_secret_key_here + +# Frontend +NEXT_PUBLIC_API_URL=http://localhost:8000 + +# CORS +BACKEND_CORS_ORIGINS=["http://localhost:3000"] +``` + +## Development Commands + +### Backend + +```bash +# Enter backend directory +cd backend + +# Install dependencies +uv sync + +# Run tests +IS_TEST=True uv run pytest + +# Run with coverage +IS_TEST=True uv run pytest --cov=app --cov-report=html + +# Run linting +uv run ruff check . + +# Run type checking +uv run mypy app + +# Generate migration +python migrate.py auto "description" + +# Apply migrations +python migrate.py upgrade +``` + +### Frontend + +```bash +# Enter frontend directory +cd frontend + +# Install dependencies +npm install + +# Run development server +npm run dev + +# Run tests +npm test + +# Run E2E tests +npm run test:e2e + +# Generate API client from backend OpenAPI spec +npm run generate:api + +# Type check +npm run type-check +``` + +### Docker Compose + +```bash +# Start all services +docker-compose -f docker-compose.dev.yml up -d + +# Start specific services +docker-compose -f docker-compose.dev.yml up -d db redis backend + +# View logs +docker-compose -f docker-compose.dev.yml logs -f backend + +# Rebuild after Dockerfile changes +docker-compose -f docker-compose.dev.yml build --no-cache backend + +# Stop all services +docker-compose -f docker-compose.dev.yml down + +# Stop and remove volumes (clean slate) +docker-compose -f docker-compose.dev.yml down -v +``` + +### Celery + +```bash +# View Celery worker status +docker-compose exec celery-agent celery -A app.celery_app inspect active + +# View scheduled tasks +docker-compose exec celery-beat celery -A app.celery_app inspect scheduled + +# Purge all queues (caution!) +docker-compose exec celery-agent celery -A app.celery_app purge +``` + +## Database Setup + +### Enable pgvector Extension + +The pgvector extension is automatically available with the `pgvector/pgvector:pg17` image. + +To enable it in your database: + +```sql +CREATE EXTENSION IF NOT EXISTS vector; +``` + +This is typically done in an Alembic migration. + +### Migrations + +```bash +# Check current migration status +python migrate.py current + +# Generate new migration +python migrate.py auto "Add agent tables" + +# Apply migrations +python migrate.py upgrade + +# Rollback one migration +python migrate.py downgrade -1 +``` + +## MCP Servers (Phase 2+) + +MCP servers are located in `mcp-servers/`. Each server is a FastMCP application. + +| Server | Priority | Status | +|--------|----------|--------| +| llm-gateway | 1 | Skeleton | +| knowledge-base | 2 | Skeleton | +| git | 3 | Skeleton | +| issues | 4 | Skeleton | +| filesystem | 5 | Skeleton | +| code-analysis | 6 | Skeleton | +| cicd | 7 | Skeleton | + +To run an MCP server locally: + +```bash +cd mcp-servers/llm-gateway +uv sync +uv run python server.py +``` + +## Testing + +### Backend Tests + +```bash +# Unit tests (uses SQLite in-memory) +IS_TEST=True uv run pytest + +# E2E tests (requires Docker) +make test-e2e + +# Run specific test file +IS_TEST=True uv run pytest tests/api/test_auth.py + +# Run with verbose output +IS_TEST=True uv run pytest -v +``` + +### Frontend Tests + +```bash +# Unit tests +npm test + +# E2E tests (Playwright) +npm run test:e2e + +# E2E with UI +npm run test:e2e:ui + +# E2E debug mode +npm run test:e2e:debug +``` + +## Debugging + +### Backend + +```bash +# View backend logs +docker-compose logs -f backend + +# Access container shell +docker-compose exec backend bash + +# Run Python REPL with app context +docker-compose exec backend python +>>> from app.core.config import settings +>>> print(settings.PROJECT_NAME) +``` + +### Database + +```bash +# Connect to PostgreSQL +docker-compose exec db psql -U syndarix -d syndarix + +# List tables +\dt + +# Describe table +\d users +``` + +### Redis + +```bash +# Connect to Redis CLI +docker-compose exec redis redis-cli + +# List all keys +KEYS * + +# Check pub/sub channels +PUBSUB CHANNELS * +``` + +## Common Issues + +### "Port already in use" + +Stop conflicting services or change ports in docker-compose.dev.yml. + +### "Database connection refused" + +Wait for PostgreSQL healthcheck to pass: +```bash +docker-compose logs db | grep "ready to accept connections" +``` + +### "Import error" for new dependencies + +Rebuild the container: +```bash +docker-compose build --no-cache backend +``` + +### Migrations out of sync + +```bash +# Check current state +python migrate.py current + +# If needed, stamp current revision +python migrate.py stamp head +``` + +## IDE Setup + +### VS Code + +Recommended extensions: +- Python +- Pylance +- Ruff +- ESLint +- Prettier +- Docker +- GitLens + +### PyCharm + +1. Set Python interpreter to uv's .venv +2. Enable Ruff integration +3. Configure pytest as test runner + +## Next Steps + +1. Set up your `.env` file with appropriate values +2. Start the development environment: `docker-compose -f docker-compose.dev.yml up -d` +3. Run migrations: `cd backend && python migrate.py upgrade` +4. Access the frontend at http://localhost:3000 +5. Access the API docs at http://localhost:8000/docs + +For architecture details, see [ARCHITECTURE.md](./architecture/ARCHITECTURE.md). diff --git a/mcp-servers/README.md b/mcp-servers/README.md new file mode 100644 index 0000000..11b9dc6 --- /dev/null +++ b/mcp-servers/README.md @@ -0,0 +1,70 @@ +# Syndarix MCP Servers + +Model Context Protocol (MCP) servers providing tool access for Syndarix agents. + +Per [ADR-005](../docs/adrs/ADR-005-mcp-integration.md), all tools require explicit project scoping. + +## Server Overview + +| Server | Priority | Purpose | Phase | +|--------|----------|---------|-------| +| llm-gateway | 1 | LLM routing with failover and cost tracking | Phase 2 | +| knowledge-base | 2 | RAG with pgvector for semantic search | Phase 2 | +| git | 3 | Git operations (clone, commit, push, PR) | Phase 2 | +| issues | 4 | Issue tracker sync (Gitea, GitHub, GitLab) | Phase 2 | +| filesystem | 5 | Sandboxed file operations | Phase 5 | +| code-analysis | 6 | AST parsing, linting, type checking | Phase 5 | +| cicd | 7 | CI/CD pipeline management | Phase 5 | + +## Architecture + +Each MCP server is a FastMCP application that: +1. Exposes tools via Model Context Protocol +2. Requires `project_id` for all operations (explicit scoping) +3. Uses Redis for pub/sub communication with agents +4. Logs all operations to PostgreSQL for audit + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Agent Runner β”‚ +β”‚ β”‚ β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β–Ό β–Ό β–Ό β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ LLM GW β”‚ β”‚ Git β”‚ β”‚ Issues β”‚ ... (7 total) β”‚ +β”‚ β”‚ MCP β”‚ β”‚ MCP β”‚ β”‚ MCP β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## Running Locally + +Each MCP server runs as a separate Docker container. See `docker-compose.dev.yml` for configuration. + +```bash +# Start all MCP servers (Phase 2+) +docker-compose -f docker-compose.dev.yml up -d llm-gateway knowledge-base git issues + +# View logs +docker-compose logs -f llm-gateway +``` + +## Development + +Each server follows the FastMCP pattern: + +```python +from fastmcp import FastMCP + +mcp = FastMCP("server-name") + +@mcp.tool() +def my_tool(project_id: str, ...): + """Tool with required project scoping.""" + # Validate project access + # Execute operation + # Log for audit + pass +``` + +See individual server READMEs for specific tool documentation. diff --git a/mcp-servers/cicd/pyproject.toml b/mcp-servers/cicd/pyproject.toml new file mode 100644 index 0000000..2b78bfd --- /dev/null +++ b/mcp-servers/cicd/pyproject.toml @@ -0,0 +1,23 @@ +[project] +name = "syndarix-mcp-cicd" +version = "0.1.0" +description = "Syndarix CI/CD MCP Server - Pipeline management" +requires-python = ">=3.12" +dependencies = [ + "fastmcp>=0.1.0", + "httpx>=0.27.0", + "redis>=5.0.0", + "pydantic>=2.0.0", + "pydantic-settings>=2.0.0", +] + +[project.optional-dependencies] +dev = [ + "pytest>=8.0.0", + "pytest-asyncio>=0.23.0", + "ruff>=0.8.0", +] + +[tool.ruff] +target-version = "py312" +line-length = 88 diff --git a/mcp-servers/cicd/server.py b/mcp-servers/cicd/server.py new file mode 100644 index 0000000..b27fb34 --- /dev/null +++ b/mcp-servers/cicd/server.py @@ -0,0 +1,47 @@ +""" +Syndarix CI/CD MCP Server. + +Provides CI/CD pipeline management with: +- Gitea Actions integration +- GitHub Actions integration +- Pipeline status monitoring + +Phase 5 implementation. +""" + +import os + +from fastmcp import FastMCP + +mcp = FastMCP( + "syndarix-cicd", + description="CI/CD pipeline management", +) + + +@mcp.tool() +async def get_pipeline_status(project_id: str, run_id: str | None = None) -> dict: + """Get CI/CD pipeline status.""" + return {"status": "not_implemented", "project_id": project_id} + + +@mcp.tool() +async def trigger_pipeline(project_id: str, workflow: str, ref: str = "main") -> dict: + """Trigger a CI/CD pipeline.""" + return {"status": "not_implemented", "project_id": project_id} + + +@mcp.tool() +async def list_workflows(project_id: str) -> dict: + """List available CI/CD workflows.""" + return {"status": "not_implemented", "project_id": project_id} + + +@mcp.tool() +async def get_logs(project_id: str, run_id: str, job: str | None = None) -> dict: + """Get logs from a pipeline run.""" + return {"status": "not_implemented", "project_id": project_id} + + +if __name__ == "__main__": + mcp.run() diff --git a/mcp-servers/code-analysis/pyproject.toml b/mcp-servers/code-analysis/pyproject.toml new file mode 100644 index 0000000..1a86c4e --- /dev/null +++ b/mcp-servers/code-analysis/pyproject.toml @@ -0,0 +1,23 @@ +[project] +name = "syndarix-mcp-code-analysis" +version = "0.1.0" +description = "Syndarix Code Analysis MCP Server - AST parsing, linting, type checking" +requires-python = ">=3.12" +dependencies = [ + "fastmcp>=0.1.0", + "tree-sitter>=0.21.0", + "redis>=5.0.0", + "pydantic>=2.0.0", + "pydantic-settings>=2.0.0", +] + +[project.optional-dependencies] +dev = [ + "pytest>=8.0.0", + "pytest-asyncio>=0.23.0", + "ruff>=0.8.0", +] + +[tool.ruff] +target-version = "py312" +line-length = 88 diff --git a/mcp-servers/code-analysis/server.py b/mcp-servers/code-analysis/server.py new file mode 100644 index 0000000..71686ec --- /dev/null +++ b/mcp-servers/code-analysis/server.py @@ -0,0 +1,47 @@ +""" +Syndarix Code Analysis MCP Server. + +Provides code analysis with: +- AST parsing via tree-sitter +- Linting integration +- Type checking + +Phase 5 implementation. +""" + +import os + +from fastmcp import FastMCP + +mcp = FastMCP( + "syndarix-code-analysis", + description="AST parsing, linting, type checking", +) + + +@mcp.tool() +async def parse_file(project_id: str, path: str) -> dict: + """Parse a file and return its AST.""" + return {"status": "not_implemented", "project_id": project_id} + + +@mcp.tool() +async def lint_file(project_id: str, path: str) -> dict: + """Run linting on a file.""" + return {"status": "not_implemented", "project_id": project_id} + + +@mcp.tool() +async def type_check(project_id: str, path: str | None = None) -> dict: + """Run type checking on file(s).""" + return {"status": "not_implemented", "project_id": project_id} + + +@mcp.tool() +async def find_references(project_id: str, symbol: str, path: str) -> dict: + """Find all references to a symbol.""" + return {"status": "not_implemented", "project_id": project_id} + + +if __name__ == "__main__": + mcp.run() diff --git a/mcp-servers/filesystem/pyproject.toml b/mcp-servers/filesystem/pyproject.toml new file mode 100644 index 0000000..103c2a5 --- /dev/null +++ b/mcp-servers/filesystem/pyproject.toml @@ -0,0 +1,23 @@ +[project] +name = "syndarix-mcp-filesystem" +version = "0.1.0" +description = "Syndarix Filesystem MCP Server - Sandboxed file operations" +requires-python = ">=3.12" +dependencies = [ + "fastmcp>=0.1.0", + "aiofiles>=24.0.0", + "redis>=5.0.0", + "pydantic>=2.0.0", + "pydantic-settings>=2.0.0", +] + +[project.optional-dependencies] +dev = [ + "pytest>=8.0.0", + "pytest-asyncio>=0.23.0", + "ruff>=0.8.0", +] + +[tool.ruff] +target-version = "py312" +line-length = 88 diff --git a/mcp-servers/filesystem/server.py b/mcp-servers/filesystem/server.py new file mode 100644 index 0000000..b1359a0 --- /dev/null +++ b/mcp-servers/filesystem/server.py @@ -0,0 +1,47 @@ +""" +Syndarix Filesystem MCP Server. + +Provides sandboxed file operations with: +- Project-scoped file access +- Read/write/delete operations +- Directory listing + +Phase 5 implementation. +""" + +import os + +from fastmcp import FastMCP + +mcp = FastMCP( + "syndarix-filesystem", + description="Sandboxed file operations", +) + + +@mcp.tool() +async def read_file(project_id: str, path: str) -> dict: + """Read a file from the project workspace.""" + return {"status": "not_implemented", "project_id": project_id} + + +@mcp.tool() +async def write_file(project_id: str, path: str, content: str) -> dict: + """Write content to a file in the project workspace.""" + return {"status": "not_implemented", "project_id": project_id} + + +@mcp.tool() +async def list_directory(project_id: str, path: str = ".") -> dict: + """List contents of a directory.""" + return {"status": "not_implemented", "project_id": project_id} + + +@mcp.tool() +async def delete_file(project_id: str, path: str) -> dict: + """Delete a file from the project workspace.""" + return {"status": "not_implemented", "project_id": project_id} + + +if __name__ == "__main__": + mcp.run() diff --git a/mcp-servers/git/pyproject.toml b/mcp-servers/git/pyproject.toml new file mode 100644 index 0000000..f0953a4 --- /dev/null +++ b/mcp-servers/git/pyproject.toml @@ -0,0 +1,24 @@ +[project] +name = "syndarix-mcp-git" +version = "0.1.0" +description = "Syndarix Git MCP Server - Git operations and PR management" +requires-python = ">=3.12" +dependencies = [ + "fastmcp>=0.1.0", + "gitpython>=3.1.0", + "httpx>=0.27.0", + "redis>=5.0.0", + "pydantic>=2.0.0", + "pydantic-settings>=2.0.0", +] + +[project.optional-dependencies] +dev = [ + "pytest>=8.0.0", + "pytest-asyncio>=0.23.0", + "ruff>=0.8.0", +] + +[tool.ruff] +target-version = "py312" +line-length = 88 diff --git a/mcp-servers/git/server.py b/mcp-servers/git/server.py new file mode 100644 index 0000000..6f99275 --- /dev/null +++ b/mcp-servers/git/server.py @@ -0,0 +1,66 @@ +""" +Syndarix Git MCP Server. + +Provides Git operations with: +- Repository management (clone, pull, push) +- Branch management +- Commit operations +- PR creation via Gitea/GitHub/GitLab APIs + +Per ADR-009: Git Integration. +""" + +import os + +from fastmcp import FastMCP + +mcp = FastMCP( + "syndarix-git", + description="Git operations and PR management", +) + + +@mcp.tool() +async def clone_repo(project_id: str, repo_url: str, branch: str = "main") -> dict: + """Clone a repository for a project.""" + return {"status": "not_implemented", "project_id": project_id} + + +@mcp.tool() +async def create_branch(project_id: str, branch_name: str, from_ref: str = "main") -> dict: + """Create a new branch.""" + return {"status": "not_implemented", "project_id": project_id} + + +@mcp.tool() +async def commit(project_id: str, message: str, files: list[str] | None = None) -> dict: + """Commit changes to the repository.""" + return {"status": "not_implemented", "project_id": project_id} + + +@mcp.tool() +async def push(project_id: str, branch: str, force: bool = False) -> dict: + """Push changes to remote.""" + return {"status": "not_implemented", "project_id": project_id} + + +@mcp.tool() +async def create_pr( + project_id: str, + title: str, + body: str, + head: str, + base: str = "main", +) -> dict: + """Create a pull request.""" + return {"status": "not_implemented", "project_id": project_id} + + +@mcp.tool() +async def get_diff(project_id: str, ref1: str = "HEAD", ref2: str | None = None) -> dict: + """Get diff between refs.""" + return {"status": "not_implemented", "project_id": project_id} + + +if __name__ == "__main__": + mcp.run() diff --git a/mcp-servers/issues/pyproject.toml b/mcp-servers/issues/pyproject.toml new file mode 100644 index 0000000..4bde989 --- /dev/null +++ b/mcp-servers/issues/pyproject.toml @@ -0,0 +1,23 @@ +[project] +name = "syndarix-mcp-issues" +version = "0.1.0" +description = "Syndarix Issues MCP Server - Issue tracker synchronization" +requires-python = ">=3.12" +dependencies = [ + "fastmcp>=0.1.0", + "httpx>=0.27.0", + "redis>=5.0.0", + "pydantic>=2.0.0", + "pydantic-settings>=2.0.0", +] + +[project.optional-dependencies] +dev = [ + "pytest>=8.0.0", + "pytest-asyncio>=0.23.0", + "ruff>=0.8.0", +] + +[tool.ruff] +target-version = "py312" +line-length = 88 diff --git a/mcp-servers/issues/server.py b/mcp-servers/issues/server.py new file mode 100644 index 0000000..9f235ea --- /dev/null +++ b/mcp-servers/issues/server.py @@ -0,0 +1,76 @@ +""" +Syndarix Issues MCP Server. + +Provides issue tracker operations with: +- Multi-provider support (Gitea, GitHub, GitLab) +- Bi-directional sync +- LWW conflict resolution + +Per ADR-011: Issue Synchronization. +""" + +import os + +from fastmcp import FastMCP + +mcp = FastMCP( + "syndarix-issues", + description="Issue tracker synchronization", +) + + +@mcp.tool() +async def list_issues( + project_id: str, + state: str = "open", + labels: list[str] | None = None, +) -> dict: + """List issues for a project.""" + return {"status": "not_implemented", "project_id": project_id} + + +@mcp.tool() +async def get_issue(project_id: str, issue_id: str) -> dict: + """Get a specific issue.""" + return {"status": "not_implemented", "project_id": project_id} + + +@mcp.tool() +async def create_issue( + project_id: str, + title: str, + body: str, + labels: list[str] | None = None, + assignees: list[str] | None = None, +) -> dict: + """Create a new issue.""" + return {"status": "not_implemented", "project_id": project_id} + + +@mcp.tool() +async def update_issue( + project_id: str, + issue_id: str, + title: str | None = None, + body: str | None = None, + state: str | None = None, + labels: list[str] | None = None, +) -> dict: + """Update an existing issue.""" + return {"status": "not_implemented", "project_id": project_id} + + +@mcp.tool() +async def add_comment(project_id: str, issue_id: str, body: str) -> dict: + """Add a comment to an issue.""" + return {"status": "not_implemented", "project_id": project_id} + + +@mcp.tool() +async def sync_issues(project_id: str, full: bool = False) -> dict: + """Trigger issue sync for a project.""" + return {"status": "not_implemented", "project_id": project_id} + + +if __name__ == "__main__": + mcp.run() diff --git a/mcp-servers/knowledge-base/pyproject.toml b/mcp-servers/knowledge-base/pyproject.toml new file mode 100644 index 0000000..c051e96 --- /dev/null +++ b/mcp-servers/knowledge-base/pyproject.toml @@ -0,0 +1,24 @@ +[project] +name = "syndarix-mcp-knowledge-base" +version = "0.1.0" +description = "Syndarix Knowledge Base MCP Server - RAG with pgvector for semantic search" +requires-python = ">=3.12" +dependencies = [ + "fastmcp>=0.1.0", + "asyncpg>=0.29.0", + "pgvector>=0.3.0", + "redis>=5.0.0", + "pydantic>=2.0.0", + "pydantic-settings>=2.0.0", +] + +[project.optional-dependencies] +dev = [ + "pytest>=8.0.0", + "pytest-asyncio>=0.23.0", + "ruff>=0.8.0", +] + +[tool.ruff] +target-version = "py312" +line-length = 88 diff --git a/mcp-servers/knowledge-base/server.py b/mcp-servers/knowledge-base/server.py new file mode 100644 index 0000000..87c3995 --- /dev/null +++ b/mcp-servers/knowledge-base/server.py @@ -0,0 +1,162 @@ +""" +Syndarix Knowledge Base MCP Server. + +Provides RAG capabilities with: +- pgvector for semantic search +- Per-project collection isolation +- Hybrid search (vector + keyword) +- Chunking strategies for code, markdown, and text + +Per ADR-008: Knowledge Base RAG Architecture. +""" + +import os + +from fastmcp import FastMCP + +# Create MCP server +mcp = FastMCP( + "syndarix-knowledge-base", + description="RAG with pgvector for semantic search", +) + +# Configuration +DATABASE_URL = os.getenv("DATABASE_URL") +REDIS_URL = os.getenv("REDIS_URL", "redis://localhost:6379/0") + + +@mcp.tool() +async def search_knowledge( + project_id: str, + query: str, + top_k: int = 10, + search_type: str = "hybrid", + filters: dict | None = None, +) -> dict: + """ + Search the project knowledge base. + + Args: + project_id: UUID of the project (scopes to project collection) + query: Search query text + top_k: Number of results to return + search_type: Search type (semantic, keyword, hybrid) + filters: Optional filters (file_type, path_prefix, etc.) + + Returns: + List of matching documents with scores + """ + # TODO: Implement pgvector search + # 1. Generate query embedding via LLM Gateway + # 2. Search project-scoped collection + # 3. Apply filters + # 4. Return results with scores + return { + "status": "not_implemented", + "project_id": project_id, + "query": query, + } + + +@mcp.tool() +async def ingest_document( + project_id: str, + content: str, + source_path: str, + doc_type: str = "text", + metadata: dict | None = None, +) -> dict: + """ + Ingest a document into the knowledge base. + + Args: + project_id: UUID of the project + content: Document content + source_path: Original file path for reference + doc_type: Document type (code, markdown, text) + metadata: Additional metadata + + Returns: + Ingestion result with chunk count + """ + # TODO: Implement document ingestion + # 1. Apply chunking strategy based on doc_type + # 2. Generate embeddings for chunks + # 3. Store in project collection + return { + "status": "not_implemented", + "project_id": project_id, + "source_path": source_path, + } + + +@mcp.tool() +async def ingest_repository( + project_id: str, + repo_path: str, + include_patterns: list[str] | None = None, + exclude_patterns: list[str] | None = None, +) -> dict: + """ + Ingest an entire repository into the knowledge base. + + Args: + project_id: UUID of the project + repo_path: Path to the repository + include_patterns: Glob patterns to include (e.g., ["*.py", "*.md"]) + exclude_patterns: Glob patterns to exclude (e.g., ["node_modules/*"]) + + Returns: + Ingestion summary with file and chunk counts + """ + # TODO: Implement repository ingestion + return { + "status": "not_implemented", + "project_id": project_id, + "repo_path": repo_path, + } + + +@mcp.tool() +async def delete_document( + project_id: str, + source_path: str, +) -> dict: + """ + Delete a document from the knowledge base. + + Args: + project_id: UUID of the project + source_path: Original file path + + Returns: + Deletion result + """ + # TODO: Implement document deletion + return { + "status": "not_implemented", + "project_id": project_id, + "source_path": source_path, + } + + +@mcp.tool() +async def get_collection_stats(project_id: str) -> dict: + """ + Get statistics for a project's knowledge base collection. + + Args: + project_id: UUID of the project + + Returns: + Collection statistics (document count, chunk count, etc.) + """ + # TODO: Implement collection stats + return { + "status": "not_implemented", + "project_id": project_id, + } + + +if __name__ == "__main__": + mcp.run() diff --git a/mcp-servers/llm-gateway/pyproject.toml b/mcp-servers/llm-gateway/pyproject.toml new file mode 100644 index 0000000..323c387 --- /dev/null +++ b/mcp-servers/llm-gateway/pyproject.toml @@ -0,0 +1,23 @@ +[project] +name = "syndarix-mcp-llm-gateway" +version = "0.1.0" +description = "Syndarix LLM Gateway MCP Server - Unified LLM access with failover and cost tracking" +requires-python = ">=3.12" +dependencies = [ + "fastmcp>=0.1.0", + "litellm>=1.50.0", + "redis>=5.0.0", + "pydantic>=2.0.0", + "pydantic-settings>=2.0.0", +] + +[project.optional-dependencies] +dev = [ + "pytest>=8.0.0", + "pytest-asyncio>=0.23.0", + "ruff>=0.8.0", +] + +[tool.ruff] +target-version = "py312" +line-length = 88 diff --git a/mcp-servers/llm-gateway/server.py b/mcp-servers/llm-gateway/server.py new file mode 100644 index 0000000..059e846 --- /dev/null +++ b/mcp-servers/llm-gateway/server.py @@ -0,0 +1,148 @@ +""" +Syndarix LLM Gateway MCP Server. + +Provides unified LLM access with: +- Multi-provider support (Claude, GPT, Gemini, Qwen, DeepSeek) +- Automatic failover chains +- Cost tracking via LiteLLM callbacks +- Model group routing (high-reasoning, code-generation, fast-response, cost-optimized) + +Per ADR-004: LLM Provider Abstraction. +""" + +import os + +from fastmcp import FastMCP + +# Create MCP server +mcp = FastMCP( + "syndarix-llm-gateway", + description="Unified LLM access with failover and cost tracking", +) + +# Configuration +REDIS_URL = os.getenv("REDIS_URL", "redis://localhost:6379/0") +DATABASE_URL = os.getenv("DATABASE_URL") + + +@mcp.tool() +async def chat_completion( + project_id: str, + agent_id: str, + messages: list[dict], + model_group: str = "high-reasoning", + max_tokens: int = 4096, + temperature: float = 0.7, +) -> dict: + """ + Generate a chat completion using the specified model group. + + Args: + project_id: UUID of the project (required for cost attribution) + agent_id: UUID of the agent instance making the request + messages: List of message dicts with 'role' and 'content' + model_group: Model routing group (high-reasoning, code-generation, fast-response, cost-optimized, self-hosted) + max_tokens: Maximum tokens to generate + temperature: Sampling temperature (0.0-2.0) + + Returns: + Completion response with content and usage statistics + """ + # TODO: Implement with LiteLLM + # 1. Map model_group to primary model + fallbacks + # 2. Check project budget before making request + # 3. Make completion request with failover + # 4. Log usage via callback + # 5. Return response + return { + "status": "not_implemented", + "project_id": project_id, + "agent_id": agent_id, + "model_group": model_group, + } + + +@mcp.tool() +async def get_embeddings( + project_id: str, + texts: list[str], + model: str = "text-embedding-3-small", +) -> dict: + """ + Generate embeddings for the given texts. + + Args: + project_id: UUID of the project (required for cost attribution) + texts: List of texts to embed + model: Embedding model to use + + Returns: + List of embedding vectors + """ + # TODO: Implement with LiteLLM embeddings + return { + "status": "not_implemented", + "project_id": project_id, + "text_count": len(texts), + } + + +@mcp.tool() +async def get_budget_status(project_id: str) -> dict: + """ + Get current budget status for a project. + + Args: + project_id: UUID of the project + + Returns: + Budget status with usage, limits, and percentage + """ + # TODO: Implement budget check from Redis + return { + "status": "not_implemented", + "project_id": project_id, + } + + +@mcp.tool() +async def list_available_models() -> dict: + """ + List all available models and their capabilities. + + Returns: + Dictionary of model groups and available models + """ + return { + "model_groups": { + "high-reasoning": { + "primary": "claude-opus-4-5", + "fallbacks": ["gpt-5.1-codex-max", "gemini-3-pro"], + "description": "Complex analysis, architecture decisions", + }, + "code-generation": { + "primary": "gpt-5.1-codex-max", + "fallbacks": ["claude-opus-4-5", "deepseek-v3.2"], + "description": "Code writing and refactoring", + }, + "fast-response": { + "primary": "gemini-3-flash", + "fallbacks": ["qwen3-235b", "deepseek-v3.2"], + "description": "Quick tasks, simple queries", + }, + "cost-optimized": { + "primary": "qwen3-235b", + "fallbacks": ["deepseek-v3.2"], + "description": "High-volume, non-critical tasks", + }, + "self-hosted": { + "primary": "deepseek-v3.2", + "fallbacks": ["qwen3-235b"], + "description": "Privacy-sensitive, air-gapped", + }, + } + } + + +if __name__ == "__main__": + mcp.run()