From a37b59f29a3f0f5fa2993e6075654f11225dc731 Mon Sep 17 00:00:00 2001 From: cryptooda Date: Wed, 31 Dec 2025 01:31:54 +0700 Subject: [PATCH] Add vibe-kanban --- .DS_Store | Bin 14340 -> 14340 bytes .cursor/.DS_Store | Bin 6148 -> 6148 bytes .cursor/commands/start-dev-env.md | 287 ++++++++++++++++++ .gitignore | 11 + docs/ENV_FILE_SETUP.md | 125 ++++++++ docs/INSTALL_VIBE_KANBAN_AND_DEV_MANAGER.md | 283 +++++++++++++++++ docs/TASK_ENVIRONMENTS_SETUP.md | 177 +++++++++++ docs/VIBE_KANBAN_DEV_SERVER_SETUP.md | 89 ++++++ docs/VIBE_KANBAN_PROJECT_SETTINGS.md | 125 ++++++++ docs/VIBE_KANBAN_QUICK_START.md | 99 ++++++ docs/VIBE_KANBAN_SETUP_SUMMARY.md | 73 +++++ package.json | 12 + scripts/copy-database-for-task.sh | 124 ++++++++ scripts/create-task-compose.sh | 82 +++++ scripts/start-api-and-workers.sh | 109 +++++++ scripts/start-dev-env.sh | 38 +++ scripts/start-task-docker.sh | 189 ++++++++++++ scripts/stop-task-docker.sh | 82 +++++ scripts/vibe-dev-server.sh | 58 ++++ src/.DS_Store | Bin 20484 -> 20484 bytes src/Managing.ABI.GmxV2/.DS_Store | Bin 0 -> 8196 bytes src/Managing.Api/.DS_Store | Bin 0 -> 8196 bytes src/Managing.Api/Managing.Api.csproj | 1 + src/Managing.Api/Program.cs | 40 +++ .../.DS_Store | Bin 0 -> 6148 bytes src/Managing.Application.Tests/.DS_Store | Bin 6148 -> 6148 bytes src/Managing.Application/.DS_Store | Bin 0 -> 10244 bytes src/Managing.Bootstrap/.DS_Store | Bin 0 -> 6148 bytes src/Managing.Common/.DS_Store | Bin 0 -> 6148 bytes src/Managing.Core/.DS_Store | Bin 0 -> 6148 bytes src/Managing.Domain.Tests/.DS_Store | Bin 0 -> 6148 bytes src/Managing.Domain/.DS_Store | Bin 0 -> 10244 bytes .../.DS_Store | Bin 0 -> 6148 bytes .../.DS_Store | Bin 0 -> 6148 bytes .../.DS_Store | Bin 0 -> 6148 bytes src/Managing.Infrastructure.Storage/.DS_Store | Bin 0 -> 6148 bytes src/Managing.Infrastructure.Web3/.DS_Store | Bin 0 -> 8196 bytes src/Managing.Nswag/.DS_Store | Bin 6148 -> 6148 bytes src/Managing.Tools.ABI/.DS_Store | Bin 0 -> 8196 bytes src/Managing.Workers.Tests/.DS_Store | Bin 0 -> 6148 bytes src/Managing.Workers/.DS_Store | Bin 0 -> 6148 bytes 41 files changed, 2004 insertions(+) create mode 100644 .cursor/commands/start-dev-env.md create mode 100644 docs/ENV_FILE_SETUP.md create mode 100644 docs/INSTALL_VIBE_KANBAN_AND_DEV_MANAGER.md create mode 100644 docs/TASK_ENVIRONMENTS_SETUP.md create mode 100644 docs/VIBE_KANBAN_DEV_SERVER_SETUP.md create mode 100644 docs/VIBE_KANBAN_PROJECT_SETTINGS.md create mode 100644 docs/VIBE_KANBAN_QUICK_START.md create mode 100644 docs/VIBE_KANBAN_SETUP_SUMMARY.md create mode 100644 package.json create mode 100755 scripts/copy-database-for-task.sh create mode 100755 scripts/create-task-compose.sh create mode 100755 scripts/start-api-and-workers.sh create mode 100755 scripts/start-dev-env.sh create mode 100755 scripts/start-task-docker.sh create mode 100755 scripts/stop-task-docker.sh create mode 100755 scripts/vibe-dev-server.sh create mode 100644 src/Managing.ABI.GmxV2/.DS_Store create mode 100644 src/Managing.Api/.DS_Store create mode 100644 src/Managing.Application.Abstractions/.DS_Store create mode 100644 src/Managing.Application/.DS_Store create mode 100644 src/Managing.Bootstrap/.DS_Store create mode 100644 src/Managing.Common/.DS_Store create mode 100644 src/Managing.Core/.DS_Store create mode 100644 src/Managing.Domain.Tests/.DS_Store create mode 100644 src/Managing.Domain/.DS_Store create mode 100644 src/Managing.Infrastructure.Database/.DS_Store create mode 100644 src/Managing.Infrastructure.Exchanges/.DS_Store create mode 100644 src/Managing.Infrastructure.Messengers/.DS_Store create mode 100644 src/Managing.Infrastructure.Storage/.DS_Store create mode 100644 src/Managing.Infrastructure.Web3/.DS_Store create mode 100644 src/Managing.Tools.ABI/.DS_Store create mode 100644 src/Managing.Workers.Tests/.DS_Store create mode 100644 src/Managing.Workers/.DS_Store diff --git a/.DS_Store b/.DS_Store index b7122d7c6c77dc718ddcec24dcda411489b1aac2..c2b4164d6a008858dc5863a8f059cb0203d5f1ac 100644 GIT binary patch delta 673 zcmZoEXepTB&*(ETAZGG0bwOr!2EC03y!ja=Cr*%?{6$@8;snEq6Qw6>2>ej%3SeMh zU}q?1NM=*Y|* zwtepA%OYHCOj{i`-2St&|dWu|Z<)80fV``dgr>Fp9rYI^h zF*8hVSKJV1BcKPggoQzmAsuLW39`k7%Rg#qG#z(Dl}~{?44ZsGhGB4Wer^F!4+Ber z!Q`n*-|BgQhL-^iPhv=A&}GPGNMy(ZvVmkyIzll61LJR?9-L~C9j3g9|2R9uVR+QT z9BRtIL5v1umoqR3Y;ITfWsY6s3-){pLq0HeP-5kdWrzz8EO6lRFgqDIu*suZ@nN!| edgW#&iQ7z&xI4kJncd(U%Vt-VekPh*EDZo(p0JGo delta 377 zcmZoEXepTB&*(8RAZBuefau19Ui^&W6DP<_?hyE)rgn&dfq|W&m?4>=h#`}qfT4t; zI5*$LB`GIA2`Izy%jo&ithC9?1Qpnz%rkDy*!6;Ea+ zd%wwj>Jn`JUlRnc$xmLRE(K$rQI}y1nEX<`a^eKti4&zKYY2#JPLsIKgz!_$W_E*b OEStBgUS}l57$E?tEP6cv diff --git a/.cursor/.DS_Store b/.cursor/.DS_Store index f56d4302b51f8d69eb119b60380f7d9506b581b3..6750df938c0b8e85d13d862b4f2c50c93b612f7f 100644 GIT binary patch delta 49 zcmZoMXffEJ$HWx$Z?XZC0tb(>%|^DS= 18 (or Bun) +- Docker installed and running +- PostgreSQL client (psql) installed +- Main database running on localhost:5432 + +## Part 1: Install dev-manager-mcp + +dev-manager-mcp is a daemon that manages multiple dev servers in parallel, allocating unique ports to avoid collisions. + +### Installation + +**Option 1: Use via npx (Recommended - No Installation Needed)** + +No installation required! Just use `npx`: + +```bash +# Start the daemon +npx -y dev-manager-mcp daemon +``` + +**Option 2: Install Globally** + +```bash +npm install -g dev-manager-mcp +# or +bun install -g dev-manager-mcp +``` + +### Start the Daemon + +Open a terminal and keep it running: + +```bash +npx -y dev-manager-mcp daemon +``` + +You should see output indicating the daemon is running. Keep this terminal open. + +### Verify Installation + +In another terminal, test the MCP connection: + +```bash +# Check if daemon is accessible +npx dev-manager-mcp status +``` + +## Part 2: Install Vibe Kanban + +Vibe Kanban is a task management system that integrates with coding agents and can automatically start dev environments. + +### Installation + +**Option 1: Use via npx (Recommended - No Installation Needed)** + +```bash +# Just run it - no installation needed +npx vibe-kanban +``` + +**Option 2: Install Globally** + +```bash +npm install -g vibe-kanban +# or +bun install -g vibe-kanban +``` + +### First Run + +1. **Start Vibe Kanban:** + +```bash +npx vibe-kanban +``` + +2. **Authenticate with your coding agent:** + - Vibe Kanban will prompt you to authenticate + - Follow the instructions for your agent (Claude, Codex, etc.) + +3. **Access the UI:** + - Vibe Kanban will start a web server + - Open the URL shown in the terminal (usually http://localhost:3000) + +### Configure MCP Integration + +1. **Open Vibe Kanban Settings:** + - In the Vibe Kanban UI, go to Settings + - Find "MCP Servers" or "Agent Configuration" + +2. **Add dev-manager-mcp:** + ```json + { + "mcpServers": { + "dev-manager": { + "command": "npx", + "args": ["dev-manager-mcp", "stdio"] + } + } + } + ``` + +3. **Configure QA Automation:** + - In Settings, find "QA" or "Testing" section + - Enable "Auto-start dev environments" + - Set script path: `scripts/start-task-docker.sh` + - Set health check URL: `http://localhost:{port}/health` + +## Part 3: Configure for Your Project + +### Create Vibe Kanban Configuration + +**Recommended: At Projects level** (to manage all projects): + +Create a `.vibe-kanban` directory in your Projects folder: + +```bash +cd /Users/oda/Desktop/Projects +mkdir -p .vibe-kanban +``` + +Create `/Users/oda/Desktop/Projects/.vibe-kanban/config.json`: + +```json +{ + "projectRoot": "/Users/oda/Desktop/Projects", + "mcpServers": { + "dev-manager": { + "command": "npx", + "args": ["dev-manager-mcp", "stdio"] + } + }, + "qa": { + "enabled": true, + "autoStartDevEnv": true, + "devEnvScript": "managing-apps/scripts/start-task-docker.sh", + "healthCheckUrl": "http://localhost:{port}/health", + "dashboardUrl": "http://localhost:{port}" + }, + "tasks": { + "statuses": { + "ready-for-qa": { + "autoStartDevEnv": true + } + } + } +} +``` + +**Note**: The `devEnvScript` path is relative to the Projects folder. For managing-apps, it's `managing-apps/scripts/start-task-docker.sh`. For other projects, configure project-specific scripts in Vibe Kanban's project settings. + +### Update Your MCP Configuration + +If you're using Cursor or another editor with MCP support, add to your MCP config (usually `~/.cursor/mcp.json` or similar): + +```json +{ + "mcpServers": { + "dev-manager": { + "command": "npx", + "args": ["dev-manager-mcp", "stdio"] + } + } +} +``` + +## Part 4: Usage Workflow + +### For Development (Agent) + +1. **Make code changes** +2. **Start test environment:** + ```bash + cd /Users/oda/Desktop/Projects/managing-apps + bash scripts/start-dev-env.sh DEV-A3X9 + ``` +3. **Test your changes** at the provided URLs +4. **Stop when done:** + ```bash + bash scripts/stop-task-docker.sh DEV-A3X9 + ``` + +### For QA (Vibe Kanban) + +1. **Move task to "Ready for QA" status** +2. **Vibe Kanban automatically:** + - Starts a Docker environment + - Copies the database + - Provides test URLs +3. **Test the task** +4. **Move to "Done" or "Needs Changes"** +5. **Vibe Kanban automatically stops the environment** + +### Manual Management + +**Start an environment:** +```bash +cd /Users/oda/Desktop/Projects/managing-apps +bash scripts/start-task-docker.sh TASK-123 0 +``` + +**Check status:** +```bash +npx dev-manager-mcp status +``` + +**View logs:** +```bash +docker logs managing-api-TASK-123 +``` + +**Stop an environment:** +```bash +bash scripts/stop-task-docker.sh TASK-123 +``` + +## Troubleshooting + +### dev-manager-mcp Issues + +**Daemon not starting:** +- Check Node.js version: `node --version` (needs >= 18) +- Try: `npx -y dev-manager-mcp daemon --verbose` + +**Cannot connect to daemon:** +- Make sure daemon is running in another terminal +- Check if port is already in use +- Restart the daemon + +### Vibe Kanban Issues + +**Cannot start:** +- Check Node.js version: `node --version` (needs >= 18) +- Try: `npx vibe-kanban --verbose` + +**MCP not working:** +- Verify dev-manager-mcp daemon is running +- Check MCP configuration in Vibe Kanban settings +- Restart Vibe Kanban + +**Auto-start not working:** +- Check script path in configuration +- Verify script is executable: `chmod +x scripts/start-task-docker.sh` +- Check Vibe Kanban logs + +### Docker Issues + +**Port conflicts:** +- Use different port offset: `bash scripts/start-task-docker.sh TASK-123 10` +- Check what's using ports: `lsof -i :5000` + +**Database copy fails:** +- Verify main database is running: `docker ps | grep postgres` +- Check PostgreSQL client: `which psql` +- Verify connection: `PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -d managing -c '\q'` + +## Next Steps + +1. ✅ Install dev-manager-mcp (via npx) +2. ✅ Install Vibe Kanban (via npx) +3. ✅ Start dev-manager-mcp daemon +4. ✅ Start Vibe Kanban +5. ✅ Configure MCP integration +6. ✅ Test with a sample task + +## Resources + +- [Vibe Kanban GitHub](https://github.com/BloopAI/vibe-kanban) +- [Vibe Kanban Documentation](https://www.vibekanban.com/vibe-guide) +- [dev-manager-mcp GitHub](https://github.com/BloopAI/dev-manager-mcp) +- [MCP Documentation](https://modelcontextprotocol.io/) + +## Support + +- Vibe Kanban: [GitHub Discussions](https://github.com/BloopAI/vibe-kanban/discussions) +- dev-manager-mcp: [GitHub Issues](https://github.com/BloopAI/dev-manager-mcp/issues) + diff --git a/docs/TASK_ENVIRONMENTS_SETUP.md b/docs/TASK_ENVIRONMENTS_SETUP.md new file mode 100644 index 00000000..ae4c475c --- /dev/null +++ b/docs/TASK_ENVIRONMENTS_SETUP.md @@ -0,0 +1,177 @@ +# Task Environments Setup with Docker Compose + +This document explains how to use Docker Compose to create isolated test environments for each development task. + +## Overview + +Each task gets its own isolated Docker Compose environment with: +- ✅ Isolated PostgreSQL database (copy of main database) +- ✅ Isolated Redis instance +- ✅ API and Workers containers +- ✅ Uses main InfluxDB instance (shared) +- ✅ Unique ports per task to avoid conflicts + +## Quick Start + +### Start a Test Environment + +```bash +# Simple way (auto-generates task ID) +bash scripts/start-dev-env.sh + +# With specific task ID +bash scripts/start-dev-env.sh TASK-123 + +# With specific task ID and port offset +bash scripts/start-dev-env.sh TASK-123 10 +``` + +### Stop a Test Environment + +```bash +bash scripts/stop-task-docker.sh TASK-123 +``` + +## Scripts + +### `scripts/start-task-docker.sh` +Main script that: +1. Creates task-specific Docker Compose file +2. Starts PostgreSQL and Redis +3. Copies database from main repo +4. Starts API and Workers + +**Usage:** +```bash +bash scripts/start-task-docker.sh +``` + +### `scripts/stop-task-docker.sh` +Stops and cleans up a task environment. + +**Usage:** +```bash +bash scripts/stop-task-docker.sh +``` + +### `scripts/copy-database-for-task.sh` +Copies database from main repo to task-specific PostgreSQL instance. + +**Usage:** +```bash +bash scripts/copy-database-for-task.sh +``` + +### `scripts/create-task-compose.sh` +Generates a Docker Compose file for a specific task. + +**Usage:** +```bash +bash scripts/create-task-compose.sh +``` + +### `scripts/start-dev-env.sh` +Simple wrapper for dev agents to start environments. + +**Usage:** +```bash +bash scripts/start-dev-env.sh [TASK_ID] [PORT_OFFSET] +``` + +## Port Allocation + +Default ports (offset 0): +- PostgreSQL: 5433 +- API: 5000 +- Redis: 6379 +- InfluxDB: 8086 (uses main instance) + +With offset 10: +- PostgreSQL: 5442 +- API: 5010 +- Redis: 6389 +- InfluxDB: 8086 (uses main instance) + +## Database Setup + +Each task environment: +- Gets a fresh copy of the main database +- Has isolated databases: `managing_{task_id}` and `orleans_{task_id}` +- Changes don't affect the main database +- Can be reset by stopping and restarting + +## Integration with Vibe Kanban + +When a task moves to "Ready for QA": +1. Vibe Kanban calls `scripts/start-task-docker.sh` +2. Environment is created with database copy +3. Test URLs are provided +4. When done, Vibe Kanban calls `scripts/stop-task-docker.sh` + +## Integration with dev-manager-mcp + +dev-manager-mcp can manage multiple environments: +- Start: `npx dev-manager-mcp start --command "bash scripts/start-task-docker.sh TASK-123 0"` +- Status: `npx dev-manager-mcp status` +- Stop: `npx dev-manager-mcp stop --session-key ` + +## Troubleshooting + +### Port Conflicts +Use a different port offset: +```bash +bash scripts/start-task-docker.sh TASK-123 10 +``` + +### Database Copy Fails +1. Verify main database is running: `docker ps | grep postgres` +2. Check connection: `PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -d managing -c '\q'` +3. Ensure PostgreSQL client is installed: `which psql` + +### Services Don't Start +Check logs: +```bash +docker logs managing-api-TASK-123 +docker logs managing-workers-TASK-123 +``` + +### Clean Up All Task Environments +```bash +# List all task containers +docker ps -a | grep -E "postgres-|managing-api-|managing-workers-|redis-" + +# Stop and remove all task containers +docker ps -a | grep -E "postgres-|managing-api-|managing-workers-|redis-" | awk '{print $1}' | xargs docker rm -f + +# Remove all task volumes +docker volume ls | grep -E "postgresdata_|redis_data_" | awk '{print $2}' | xargs docker volume rm +``` + +## Best Practices + +1. **Use descriptive task IDs**: `TASK-123`, `FEATURE-456`, `BUGFIX-789` +2. **Stop environments when done**: Frees up resources +3. **Use port offsets for parallel testing**: Test multiple tasks simultaneously +4. **Check port availability**: Before starting, verify ports aren't in use +5. **Monitor resource usage**: Each environment uses memory and CPU + +## Architecture + +``` +Main Environment (localhost:5432) +├── PostgreSQL (main database) +└── InfluxDB (shared) + +Task Environment (offset ports) +├── PostgreSQL (isolated, copied from main) +├── Redis (isolated) +├── API Container (connects to task PostgreSQL, main InfluxDB) +└── Workers Container (connects to task PostgreSQL, main InfluxDB) +``` + +## Next Steps + +1. Install Vibe Kanban: See `docs/INSTALL_VIBE_KANBAN_AND_DEV_MANAGER.md` +2. Install dev-manager-mcp: See `docs/INSTALL_VIBE_KANBAN_AND_DEV_MANAGER.md` +3. Configure agent command: See `.cursor/commands/start-dev-env.md` + diff --git a/docs/VIBE_KANBAN_DEV_SERVER_SETUP.md b/docs/VIBE_KANBAN_DEV_SERVER_SETUP.md new file mode 100644 index 00000000..60388cc4 --- /dev/null +++ b/docs/VIBE_KANBAN_DEV_SERVER_SETUP.md @@ -0,0 +1,89 @@ +# Vibe Kanban Dev Server Script Configuration + +## The Problem + +Vibe Kanban runs the dev server script from a different working directory than expected, causing "No such file or directory" errors. + +## Solution: Use Absolute Path + +In the Vibe Kanban dev server script field, use the **absolute path** to the wrapper script: + +```bash +bash /Users/oda/Desktop/Projects/managing-apps/scripts/vibe-dev-server.sh +``` + +## Alternative: If Relative Path is Required + +If Vibe Kanban requires a relative path and you know it runs from `/Users/oda/Desktop`, use: + +```bash +bash Projects/managing-apps/scripts/vibe-dev-server.sh +``` + +## What the Wrapper Script Does + +The `vibe-dev-server.sh` wrapper script: + +1. ✅ Uses absolute paths internally +2. ✅ Changes to the correct project directory +3. ✅ Handles task ID parameters +4. ✅ Works regardless of Vibe Kanban's working directory +5. ✅ Provides debug output to help troubleshoot + +## Testing the Script + +You can test the script manually: + +```bash +# From any directory +bash /Users/oda/Desktop/Projects/managing-apps/scripts/vibe-dev-server.sh TEST-001 0 +``` + +## Debug Output + +The script includes debug output that shows: +- Current working directory +- Script path being used +- Task ID and port offset + +This helps identify if Vibe Kanban is running from an unexpected directory. + +## Troubleshooting + +### Error: "Script not found" + +1. Verify the script exists: + ```bash + ls -la /Users/oda/Desktop/Projects/managing-apps/scripts/vibe-dev-server.sh + ``` + +2. Check permissions: + ```bash + chmod +x /Users/oda/Desktop/Projects/managing-apps/scripts/vibe-dev-server.sh + ``` + +3. Try running it directly: + ```bash + bash /Users/oda/Desktop/Projects/managing-apps/scripts/vibe-dev-server.sh TEST-001 + ``` + +### Error: "Cannot change to project root" + +- Verify the project root exists: `/Users/oda/Desktop/Projects/managing-apps` +- Check directory permissions + +## Configuration in Vibe Kanban + +**Dev Server Script Field:** +``` +bash /Users/oda/Desktop/Projects/managing-apps/scripts/vibe-dev-server.sh +``` + +**Health Check URL:** +``` +http://localhost:{port}/health +``` + +**Port Detection:** +Vibe Kanban should detect the port from the script output or you may need to configure it manually. + diff --git a/docs/VIBE_KANBAN_PROJECT_SETTINGS.md b/docs/VIBE_KANBAN_PROJECT_SETTINGS.md new file mode 100644 index 00000000..eb0c830a --- /dev/null +++ b/docs/VIBE_KANBAN_PROJECT_SETTINGS.md @@ -0,0 +1,125 @@ +# Vibe Kanban Project Settings Configuration + +## Settings URL +http://127.0.0.1:63100/settings/projects?projectId=1a4fdbff-8b23-49d5-9953-2476846cbcc2 + +## Configuration Steps + +### 1. MCP Servers Configuration + +In the **MCP Servers** section, add or verify: + +**Server Name:** `dev-manager` + +**Configuration:** +```json +{ + "command": "npx", + "args": ["dev-manager-mcp", "stdio"] +} +``` + +This enables Vibe Kanban to use dev-manager-mcp for managing multiple dev server instances. + +### 2. QA / Testing Configuration + +In the **QA** or **Testing** section, configure: + +**Enable QA Automation:** ✅ Checked + +**Dev Environment Script:** +``` +managing-apps/scripts/vibe-dev-server.sh +``` + +**Or use absolute path:** +``` +/Users/oda/Desktop/Projects/managing-apps/scripts/vibe-dev-server.sh +``` + +**Note:** This path is relative to `/Users/oda/Desktop/Projects` (the Projects folder root) + +**Health Check URL:** +``` +http://localhost:{port}/health +``` + +**Dashboard URL (optional):** +``` +http://localhost:{port} +``` + +### 3. Task Status Configuration + +Configure which task statuses should auto-start dev environments: + +**Status:** `ready-for-qa` + +**Auto-start dev environment:** ✅ Enabled + +This means when a task moves to "Ready for QA" status, Vibe Kanban will automatically: +1. Call `managing-apps/scripts/start-task-docker.sh` with the task ID +2. Wait for the environment to be ready +3. Provide the test URLs +4. Stop the environment when the task is completed + +### 4. Project Root + +**Project Root Path:** +``` +/Users/oda/Desktop/Projects/managing-apps +``` + +This should be automatically detected from the `.vibe-kanban/config.json` file location. + +## Complete Configuration Summary + +Here's what should be configured: + +### MCP Servers +- ✅ `dev-manager` → `npx dev-manager-mcp stdio` + +### QA Settings +- ✅ Auto-start dev environments: **Enabled** +- ✅ Script: `managing-apps/scripts/start-task-docker.sh` +- ✅ Health check: `http://localhost:{port}/health` +- ✅ Dashboard: `http://localhost:{port}` + +### Task Statuses +- ✅ `ready-for-qa` → Auto-start dev environment: **Enabled** + +## Verification + +After configuration, test by: + +1. **Create a test task** in managing-apps project +2. **Move it to "Ready for QA"** status +3. **Verify** that Vibe Kanban automatically: + - Starts a Docker environment + - Copies the database + - Provides test URLs + - Shows the environment status + +## Troubleshooting + +### Script Not Found +- Verify the script path is relative to Projects folder: `managing-apps/scripts/start-task-docker.sh` +- Check that the script is executable: `chmod +x managing-apps/scripts/start-task-docker.sh` + +### MCP Server Not Working +- Ensure dev-manager-mcp daemon is running: `npm run dev-manager:start` (in Projects folder) +- Check MCP server configuration matches exactly + +### Environment Not Starting +- Check Docker is running +- Verify main database is accessible at localhost:5432 +- Check script logs in Vibe Kanban + +## Script Path Reference + +Since Vibe Kanban runs from `/Users/oda/Desktop/Projects`, all script paths should be relative to that: + +- ✅ `managing-apps/scripts/start-task-docker.sh` +- ✅ `managing-apps/scripts/stop-task-docker.sh` +- ✅ `managing-apps/scripts/copy-database-for-task.sh` + diff --git a/docs/VIBE_KANBAN_QUICK_START.md b/docs/VIBE_KANBAN_QUICK_START.md new file mode 100644 index 00000000..b1b7147d --- /dev/null +++ b/docs/VIBE_KANBAN_QUICK_START.md @@ -0,0 +1,99 @@ +# Vibe Kanban Quick Start + +Quick reference for using Vibe Kanban with managing-apps. + +## Installation + +No installation needed! Vibe Kanban runs via `npx`. + +## Starting Vibe Kanban + +**From Projects folder** (recommended - manages all projects): + +```bash +cd /Users/oda/Desktop/Projects +npm run vibe-kanban +``` + +Or directly: + +```bash +cd /Users/oda/Desktop/Projects +npx vibe-kanban +``` + +**Alternative: From managing-apps folder** (project-specific): + +```bash +cd /Users/oda/Desktop/Projects/managing-apps +npx vibe-kanban +``` + +## First Time Setup + +1. **Start Vibe Kanban:** + ```bash + npm run vibe-kanban + ``` + +2. **Complete setup dialogs:** + - Configure your coding agent (Claude, Codex, etc.) + - Set editor preferences + - Configure GitHub integration (optional) + +3. **Access the UI:** + - Vibe Kanban will print a URL in the terminal + - Usually: http://localhost:3000 (or random port) + - Automatically opens in your default browser + +## Configuration + +Project-specific configuration is in `.vibe-kanban/config.json`: + +- **MCP Servers**: dev-manager-mcp integration +- **QA Automation**: Auto-start dev environments +- **Task Statuses**: Configure when to auto-start environments + +## Using with Dev Environments + +When a task moves to "Ready for QA": + +1. Vibe Kanban automatically calls `scripts/start-task-docker.sh` +2. Creates isolated Docker environment +3. Copies database from main repo +4. Provides test URLs +5. When done, automatically stops the environment + +## Commands + +```bash +# Start Vibe Kanban +npm run vibe-kanban + +# Start dev-manager-mcp daemon (in separate terminal) +npm run dev-manager:start + +# Check dev-manager status +npm run dev-manager:status + +# Start dev environment manually +npm run dev-env:start + +# Stop dev environment +npm run dev-env:stop TASK-123 +``` + +## Fixed Port + +To use a fixed port: + +```bash +PORT=8080 npm run vibe-kanban +``` + +## Resources + +- [Official Documentation](https://www.vibekanban.com/docs/getting-started) +- [GitHub Repository](https://github.com/BloopAI/vibe-kanban) +- [MCP Integration Guide](docs/INSTALL_VIBE_KANBAN_AND_DEV_MANAGER.md) + diff --git a/docs/VIBE_KANBAN_SETUP_SUMMARY.md b/docs/VIBE_KANBAN_SETUP_SUMMARY.md new file mode 100644 index 00000000..d189fb60 --- /dev/null +++ b/docs/VIBE_KANBAN_SETUP_SUMMARY.md @@ -0,0 +1,73 @@ +# Vibe Kanban Setup Summary + +## ✅ Setup Complete! + +Vibe Kanban is configured at the **Projects level** to manage multiple projects (managing-apps, kaigen-web, gmx-interface, etc.). + +## File Locations + +- **Config**: `/Users/oda/Desktop/Projects/.vibe-kanban/config.json` +- **Package.json**: `/Users/oda/Desktop/Projects/package.json` +- **Run from**: `/Users/oda/Desktop/Projects` + +## Quick Start + +### Start Vibe Kanban (from Projects folder) + +```bash +cd /Users/oda/Desktop/Projects +npm run vibe-kanban +``` + +This will: +- Auto-discover all projects in `/Users/oda/Desktop/Projects` +- Show managing-apps, kaigen-web, gmx-interface, etc. +- Allow you to manage tasks across all projects + +### Start dev-manager-mcp (in separate terminal) + +```bash +cd /Users/oda/Desktop/Projects +npm run dev-manager:start +``` + +## Benefits of Projects-Level Setup + +✅ **Access all projects** from one Vibe Kanban instance +✅ **Centralized configuration** for MCP servers +✅ **Cross-project task management** +✅ **Unified QA workflow** across projects +✅ **Auto-discovery** of all git projects +✅ **Project-specific dev environments** - Each project can have its own dev environment setup + +## Project-Specific Scripts + +For managing-apps specific tasks, scripts are in the project: + +```bash +cd /Users/oda/Desktop/Projects/managing-apps +npm run dev-env:start # Start dev environment +npm run dev-env:stop # Stop dev environment +``` + +## Configuration + +The Projects-level config references project-specific scripts: + +```json +{ + "projectRoot": "/Users/oda/Desktop/Projects", + "devEnvScript": "managing-apps/scripts/start-task-docker.sh" +} +``` + +When Vibe Kanban starts a dev environment for a managing-apps task, it uses the script path relative to the Projects folder. + +For other projects, you can configure project-specific dev environment scripts in Vibe Kanban's project settings. + +## Next Steps + +1. ✅ Vibe Kanban config created at Projects level +2. ✅ Package.json created with convenience scripts +3. ✅ Auto-discovery enabled for all projects +4. 🚀 **Start Vibe Kanban**: `cd /Users/oda/Desktop/Projects && npm run vibe-kanban` diff --git a/package.json b/package.json new file mode 100644 index 00000000..ad383486 --- /dev/null +++ b/package.json @@ -0,0 +1,12 @@ +{ + "name": "managing-apps", + "version": "1.0.0", + "private": true, + "description": "Managing Apps Monorepo", + "scripts": { + "dev-env:start": "bash scripts/start-dev-env.sh", + "dev-env:stop": "bash scripts/stop-task-docker.sh" + }, + "workspaces": [] +} + diff --git a/scripts/copy-database-for-task.sh b/scripts/copy-database-for-task.sh new file mode 100755 index 00000000..7eeeead0 --- /dev/null +++ b/scripts/copy-database-for-task.sh @@ -0,0 +1,124 @@ +#!/bin/bash +# scripts/copy-database-for-task.sh +# Copies database from main repo to task-specific PostgreSQL instance + +TASK_ID=$1 +SOURCE_HOST=${2:-"localhost"} +SOURCE_PORT=${3:-"5432"} +TARGET_HOST=${4:-"localhost"} +TARGET_PORT=${5:-"5433"} + +SOURCE_DB="managing" +# Convert to lowercase (compatible with bash 3.2+) +TARGET_DB="managing_$(echo "$TASK_ID" | tr '[:upper:]' '[:lower:]')" +ORLEANS_SOURCE_DB="orleans" +ORLEANS_TARGET_DB="orleans_$(echo "$TASK_ID" | tr '[:upper:]' '[:lower:]')" + +DB_USER="postgres" +DB_PASSWORD="postgres" + +set -e # Exit on error + +echo "📦 Copying database for task: $TASK_ID" +echo " Source: $SOURCE_HOST:$SOURCE_PORT" +echo " Target: $TARGET_HOST:$TARGET_PORT" + +# Wait for target PostgreSQL to be ready +echo "⏳ Waiting for target PostgreSQL..." +for i in {1..60}; do + if PGPASSWORD=$DB_PASSWORD psql -h $TARGET_HOST -p $TARGET_PORT -U $DB_USER -d postgres -c '\q' 2>/dev/null; then + echo "✅ Target PostgreSQL is ready" + break + fi + if [ $i -eq 60 ]; then + echo "❌ Target PostgreSQL not ready after 60 attempts" + exit 1 + fi + sleep 1 +done + +# Verify source database is accessible +echo "🔍 Verifying source database..." +if ! PGPASSWORD=$DB_PASSWORD psql -h $SOURCE_HOST -p $SOURCE_PORT -U $DB_USER -d postgres -c '\q' 2>/dev/null; then + echo "❌ Cannot connect to source database at $SOURCE_HOST:$SOURCE_PORT" + exit 1 +fi + +# Create target databases (drop if exists for fresh copy) +echo "🗑️ Dropping existing target databases if they exist..." +PGPASSWORD=$DB_PASSWORD psql -h $TARGET_HOST -p $TARGET_PORT -U $DB_USER -d postgres -c "DROP DATABASE IF EXISTS \"$TARGET_DB\";" 2>/dev/null || true +PGPASSWORD=$DB_PASSWORD psql -h $TARGET_HOST -p $TARGET_PORT -U $DB_USER -d postgres -c "DROP DATABASE IF EXISTS \"$ORLEANS_TARGET_DB\";" 2>/dev/null || true + +echo "📝 Creating target databases..." +PGPASSWORD=$DB_PASSWORD psql -h $TARGET_HOST -p $TARGET_PORT -U $DB_USER -d postgres -c "CREATE DATABASE \"$TARGET_DB\";" +PGPASSWORD=$DB_PASSWORD psql -h $TARGET_HOST -p $TARGET_PORT -U $DB_USER -d postgres -c "CREATE DATABASE \"$ORLEANS_TARGET_DB\";" + +# Create temporary dump files +TEMP_DIR=$(mktemp -d) +MANAGING_DUMP="$TEMP_DIR/managing_${TASK_ID}.dump" +ORLEANS_DUMP="$TEMP_DIR/orleans_${TASK_ID}.dump" + +# Dump source databases +echo "📤 Dumping source database: $SOURCE_DB..." +PGPASSWORD=$DB_PASSWORD pg_dump -h $SOURCE_HOST -p $SOURCE_PORT -U $DB_USER -Fc "$SOURCE_DB" > "$MANAGING_DUMP" + +if [ ! -s "$MANAGING_DUMP" ]; then + echo "❌ Failed to dump source database $SOURCE_DB" + rm -rf "$TEMP_DIR" + exit 1 +fi + +echo "📤 Dumping Orleans database: $ORLEANS_SOURCE_DB..." +PGPASSWORD=$DB_PASSWORD pg_dump -h $SOURCE_HOST -p $SOURCE_PORT -U $DB_USER -Fc "$ORLEANS_SOURCE_DB" > "$ORLEANS_DUMP" 2>/dev/null || { + echo "⚠️ Orleans database not found, skipping..." + ORLEANS_DUMP="" +} + +# Restore to target databases +echo "📥 Restoring to target database: $TARGET_DB..." +PGPASSWORD=$DB_PASSWORD pg_restore -h $TARGET_HOST -p $TARGET_PORT -U $DB_USER -d "$TARGET_DB" --no-owner --no-acl --clean --if-exists "$MANAGING_DUMP" + +if [ $? -eq 0 ]; then + echo "✅ Successfully restored $TARGET_DB" +else + echo "❌ Failed to restore $TARGET_DB" + rm -rf "$TEMP_DIR" + exit 1 +fi + +if [ -n "$ORLEANS_DUMP" ] && [ -s "$ORLEANS_DUMP" ]; then + echo "📥 Restoring Orleans database: $ORLEANS_TARGET_DB..." + PGPASSWORD=$DB_PASSWORD pg_restore -h $TARGET_HOST -p $TARGET_PORT -U $DB_USER -d "$ORLEANS_TARGET_DB" --no-owner --no-acl --clean --if-exists "$ORLEANS_DUMP" + + if [ $? -eq 0 ]; then + echo "✅ Successfully restored $ORLEANS_TARGET_DB" + + # Clean Orleans membership tables to avoid conflicts with old silos + echo "🧹 Cleaning Orleans membership tables (removing old silo entries)..." + PGPASSWORD=$DB_PASSWORD psql -h $TARGET_HOST -p $TARGET_PORT -U $DB_USER -d "$ORLEANS_TARGET_DB" < /dev/null && pwd )" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" +COMPOSE_DIR="$PROJECT_ROOT/src/Managing.Docker" +COMPOSE_FILE="$COMPOSE_DIR/docker-compose.task-${TASK_ID}.yml" + +# Escape function for Docker Compose environment variables +escape_env() { + echo "$1" | sed 's/\\/\\\\/g' | sed 's/\$/\\$/g' | sed 's/"/\\"/g' +} + +cat > "$COMPOSE_FILE" << EOF +name: task-${TASK_ID_LOWER} + +services: + postgres-${TASK_ID}: + image: postgres:17.5 + container_name: postgres-${TASK_ID} + volumes: + - postgresdata_${TASK_ID}:/var/lib/postgresql/data + ports: + - "${POSTGRES_PORT}:5432" + restart: unless-stopped + networks: + - task-${TASK_ID}-network + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=postgres + + redis-${TASK_ID}: + image: redis:8.0.3 + container_name: redis-${TASK_ID} + ports: + - "${REDIS_PORT}:6379" + volumes: + - redis_data_${TASK_ID}:/data + networks: + - task-${TASK_ID}-network + restart: unless-stopped + environment: + - REDIS_PASSWORD= + +volumes: + postgresdata_${TASK_ID}: + redis_data_${TASK_ID}: + +networks: + task-${TASK_ID}-network: + driver: bridge +EOF + +echo "✅ Created $COMPOSE_FILE" +echo " PostgreSQL: localhost:$POSTGRES_PORT" +echo " Redis: localhost:$REDIS_PORT" +echo " API will run via dotnet run on port: $API_PORT" +echo " Orleans Silo: localhost:$ORLEANS_SILO_PORT" +echo " Orleans Gateway: localhost:$ORLEANS_GATEWAY_PORT" +echo " InfluxDB: Using main instance at localhost:8086" +echo " Task Slot: $TASK_SLOT" + diff --git a/scripts/start-api-and-workers.sh b/scripts/start-api-and-workers.sh new file mode 100755 index 00000000..26854cf6 --- /dev/null +++ b/scripts/start-api-and-workers.sh @@ -0,0 +1,109 @@ +#!/bin/bash +# scripts/start-api-and-workers.sh +# Starts API and Workers using dotnet run (not Docker) +# This script is called by start-task-docker.sh after database is ready +# IMPORTANT: This script runs from the current working directory (Vibe Kanban worktree) + +TASK_ID=$1 +PORT_OFFSET=${2:-0} + +# Use Vibe Kanban worktree if available, otherwise use current directory +# This ensures we're running from the worktree, not the main repo +if [ -n "$VIBE_WORKTREE_ROOT" ] && [ -d "$VIBE_WORKTREE_ROOT/src/Managing.Api" ]; then + PROJECT_ROOT="$VIBE_WORKTREE_ROOT" + echo "📁 Using Vibe Kanban worktree: $PROJECT_ROOT" +else + PROJECT_ROOT="$(pwd)" + echo "📁 Using current directory: $PROJECT_ROOT" +fi + +SCRIPT_DIR="$PROJECT_ROOT/scripts" + +POSTGRES_PORT=$((5432 + PORT_OFFSET)) +API_PORT=$((5000 + PORT_OFFSET)) +REDIS_PORT=$((6379 + PORT_OFFSET)) +ORLEANS_SILO_PORT=$((11111 + PORT_OFFSET)) +ORLEANS_GATEWAY_PORT=$((30000 + PORT_OFFSET)) + +# Convert to lowercase (compatible with bash 3.2+) +DB_NAME="managing_$(echo "$TASK_ID" | tr '[:upper:]' '[:lower:]')" +ORLEANS_DB_NAME="orleans_$(echo "$TASK_ID" | tr '[:upper:]' '[:lower:]')" + +# Calculate unique task slot based on port offset (for Orleans clustering) +TASK_SLOT=$((PORT_OFFSET / 10 + 1)) + +# PID files for process management +PID_DIR="$PROJECT_ROOT/.task-pids" +mkdir -p "$PID_DIR" +API_PID_FILE="$PID_DIR/api-${TASK_ID}.pid" +WORKERS_PID_FILE="$PID_DIR/workers-${TASK_ID}.pid" + +# Set environment variables for API +export ASPNETCORE_ENVIRONMENT=Development +export ASPNETCORE_URLS="http://localhost:${API_PORT}" +export RUN_ORLEANS_GRAINS=true +export SILO_ROLE=Trading +export TASK_SLOT=${TASK_SLOT} +export PostgreSql__ConnectionString="Host=localhost;Port=${POSTGRES_PORT};Database=${DB_NAME};Username=postgres;Password=postgres" +export PostgreSql__Orleans="Host=localhost;Port=${POSTGRES_PORT};Database=${ORLEANS_DB_NAME};Username=postgres;Password=postgres" +export InfluxDb__Url="http://localhost:8086/" +export InfluxDb__Token="Fw2FPL2OwTzDHzSbR2Sd5xs0EKQYy00Q-hYKYAhr9cC1_q5YySONpxuf_Ck0PTjyUiF13xXmi__bu_pXH-H9zA==" +export Jwt__Secret="2ed5f490-b6c1-4cad-8824-840c911f1fe6" +export Privy__AppSecret="63Chz2z5M8TgR5qc8dznSLRAGTHTyPU4cjdQobrBF1Cx5tszZpTuFgyrRd7hZ2k6HpwDz3GEwQZzsCqHb8Z311bF" +export AdminUsers="did:privy:cm7vxs99f0007blcl8cmzv74t;did:privy:cmhp5jqs2014kl60cbunp57jh" +export AUTHORIZED_ADDRESSES="0x932167388dD9aad41149b3cA23eBD489E2E2DD78;0x84e3E147c4e94716151181F25538aBf337Eca49f;0xeaf2a9a5864e3Cc37E85dDC287Ed0c90d76b2420" +export ENABLE_COPY_TRADING_VALIDATION=false +export KAIGEN_CREDITS_ENABLED=false +export KAIGEN_SECRET_KEY="KaigenXCowchain" +export Flagsmith__ApiKey="ser.ShJJJMtWYS9fwuzd83ejwR" +export Discord__ApplicationId="966075382002516031" +export Discord__PublicKey="63028f6bb740cd5d26ae0340b582dee2075624011b28757436255fc002ca8a7c" +export Discord__TokenId="OTY2MDc1MzgyMDAyNTE2MDMx.Yl8dzw.xpeIAaMwGrwTNY4r9JYv0ebzb-U" +export N8n__WebhookUrl="https://n8n.kai.managing.live/webhook/fa9308b6-983b-42ec-b085-71599d655951" +export N8n__IndicatorRequestWebhookUrl="https://n8n.kai.managing.live/webhook/3aa07b66-1e64-46a7-8618-af300914cb11" +export N8n__Username="managing-api" +export N8n__Password="T259836*PdiV2@%!eR%Qf4" +export Sentry__Dsn="https://fe12add48c56419bbdfa86227c188e7a@glitch.kai.managing.live/1" + +# Verify we're in the right directory (should have src/Managing.Api) +if [ ! -d "$PROJECT_ROOT/src/Managing.Api" ]; then + echo "❌ Error: src/Managing.Api not found in current directory: $PROJECT_ROOT" + echo "💡 Make sure you're running from the project root (or Vibe Kanban worktree)" + exit 1 +fi + +echo "🚀 Starting API on port $API_PORT..." +echo "📁 Running from: $PROJECT_ROOT" +cd "$PROJECT_ROOT/src/Managing.Api" +dotnet run > "$PID_DIR/api-${TASK_ID}.log" 2>&1 & +API_PID=$! +echo $API_PID > "$API_PID_FILE" +echo "✅ API started (PID: $API_PID) from worktree: $PROJECT_ROOT" + +# Wait a bit for API to start +sleep 3 + +echo "🚀 Starting Workers..." +cd "$PROJECT_ROOT/src/Managing.Workers" +# Set workers environment variables (separate from API) +ASPNETCORE_ENVIRONMENT=Development \ +PostgreSql__ConnectionString="Host=localhost;Port=${POSTGRES_PORT};Database=${DB_NAME};Username=postgres;Password=postgres" \ +InfluxDb__Url="http://localhost:8086/" \ +InfluxDb__Token="Fw2FPL2OwTzDHzSbR2Sd5xs0EKQYy00Q-hYKYAhr9cC1_q5YySONpxuf_Ck0PTjyUiF13xXmi__bu_pXH-H9zA==" \ +KAIGEN_SECRET_KEY="KaigenXCowchain" \ +Flagsmith__ApiKey="ser.ShJJJMtWYS9fwuzd83ejwR" \ +dotnet run > "$PID_DIR/workers-${TASK_ID}.log" 2>&1 & +WORKERS_PID=$! +echo $WORKERS_PID > "$WORKERS_PID_FILE" +echo "✅ Workers started (PID: $WORKERS_PID) from worktree: $PROJECT_ROOT" + +echo "" +echo "✅ API and Workers started!" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "📊 API: http://localhost:$API_PORT" +echo "📋 API PID: $API_PID" +echo "📋 Workers PID: $WORKERS_PID" +echo "📋 Logs: $PID_DIR/api-${TASK_ID}.log" +echo "📋 Logs: $PID_DIR/workers-${TASK_ID}.log" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + diff --git a/scripts/start-dev-env.sh b/scripts/start-dev-env.sh new file mode 100755 index 00000000..13df8df4 --- /dev/null +++ b/scripts/start-dev-env.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# scripts/start-dev-env.sh +# Simple wrapper for dev agent to start Docker Compose task environments + +TASK_ID=${1:-"DEV-$(date +%Y%m%d-%H%M%S)"} +PORT_OFFSET=${2:-0} + +echo "🚀 Starting Docker dev environment..." +echo "📋 Task ID: $TASK_ID" +echo "🔌 Port Offset: $PORT_OFFSET" +echo "" + +# Get script directory +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" + +# Check prerequisites +echo "🔍 Checking prerequisites..." + +# Check main database +if ! PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -d managing -c '\q' 2>/dev/null; then + echo "❌ Main database not accessible at localhost:5432" + echo "💡 Starting main database..." + cd "$SCRIPT_DIR/../src/Managing.Docker" + docker-compose -f docker-compose.yml -f docker-compose.local.yml up -d postgres + echo "⏳ Waiting for database to start..." + sleep 15 +fi + +# Check Docker +if ! docker ps >/dev/null 2>&1; then + echo "❌ Docker is not running" + exit 1 +fi + +# Start task environment +echo "🚀 Starting task environment..." +bash "$SCRIPT_DIR/start-task-docker.sh" "$TASK_ID" "$PORT_OFFSET" + diff --git a/scripts/start-task-docker.sh b/scripts/start-task-docker.sh new file mode 100755 index 00000000..5d3973ca --- /dev/null +++ b/scripts/start-task-docker.sh @@ -0,0 +1,189 @@ +#!/bin/bash +# scripts/start-task-docker.sh +# Starts a Docker Compose environment for a specific task with database copy + +TASK_ID=$1 +PORT_OFFSET=${2:-0} + +# Determine project root +# If called from main repo, use current directory +# If called from worktree wrapper, we should be in main repo already +if [ -d "$(pwd)/scripts" ] && [ -f "$(pwd)/scripts/start-api-and-workers.sh" ]; then + # We're in the main repo + PROJECT_ROOT="$(pwd)" + echo "📁 Using main repository: $PROJECT_ROOT" +else + # Try to find main repo + MAIN_REPO="/Users/oda/Desktop/Projects/managing-apps" + if [ -d "$MAIN_REPO/scripts" ]; then + PROJECT_ROOT="$MAIN_REPO" + echo "📁 Using main repository: $PROJECT_ROOT" + else + echo "❌ Error: Cannot find main repository with scripts" + exit 1 + fi +fi + +SCRIPT_DIR="$PROJECT_ROOT/scripts" + +# Auto-detect port offset if 0 is provided (to avoid conflicts with main database) +if [ "$PORT_OFFSET" = "0" ]; then + echo "🔍 Auto-detecting available port offset (to avoid conflicts with main database)..." + # Find an available port offset (start from 1, check up to 100) + PORT_OFFSET_FOUND=0 + for offset in $(seq 1 100); do + POSTGRES_TEST=$((5432 + offset)) + REDIS_TEST=$((6379 + offset)) + API_TEST=$((5000 + offset)) + ORLEANS_SILO_TEST=$((11111 + offset)) + ORLEANS_GATEWAY_TEST=$((30000 + offset)) + + # Check if ports are available (try multiple methods for compatibility) + POSTGRES_FREE=true + REDIS_FREE=true + API_FREE=true + ORLEANS_SILO_FREE=true + ORLEANS_GATEWAY_FREE=true + + # Method 1: lsof (macOS/Linux) + if command -v lsof >/dev/null 2>&1; then + if lsof -Pi :$POSTGRES_TEST -sTCP:LISTEN -t >/dev/null 2>&1; then + POSTGRES_FREE=false + fi + if lsof -Pi :$REDIS_TEST -sTCP:LISTEN -t >/dev/null 2>&1; then + REDIS_FREE=false + fi + if lsof -Pi :$API_TEST -sTCP:LISTEN -t >/dev/null 2>&1; then + API_FREE=false + fi + if lsof -Pi :$ORLEANS_SILO_TEST -sTCP:LISTEN -t >/dev/null 2>&1; then + ORLEANS_SILO_FREE=false + fi + if lsof -Pi :$ORLEANS_GATEWAY_TEST -sTCP:LISTEN -t >/dev/null 2>&1; then + ORLEANS_GATEWAY_FREE=false + fi + # Method 2: netstat (fallback) + elif command -v netstat >/dev/null 2>&1; then + if netstat -an | grep -q ":$POSTGRES_TEST.*LISTEN"; then + POSTGRES_FREE=false + fi + if netstat -an | grep -q ":$REDIS_TEST.*LISTEN"; then + REDIS_FREE=false + fi + if netstat -an | grep -q ":$API_TEST.*LISTEN"; then + API_FREE=false + fi + fi + + # If all ports are free, use this offset + if [ "$POSTGRES_FREE" = "true" ] && [ "$REDIS_FREE" = "true" ] && [ "$API_FREE" = "true" ] && [ "$ORLEANS_SILO_FREE" = "true" ] && [ "$ORLEANS_GATEWAY_FREE" = "true" ]; then + PORT_OFFSET=$offset + PORT_OFFSET_FOUND=1 + echo "✅ Found available port offset: $PORT_OFFSET" + echo " PostgreSQL: $POSTGRES_TEST" + echo " Redis: $REDIS_TEST" + echo " API: $API_TEST" + break + fi + done + + if [ "$PORT_OFFSET_FOUND" = "0" ]; then + echo "❌ Could not find available port offset (checked offsets 1-100)" + echo "💡 Try manually specifying a port offset: bash $0 $TASK_ID 10" + exit 1 + fi +fi + +POSTGRES_PORT=$((5432 + PORT_OFFSET)) +API_PORT=$((5000 + PORT_OFFSET)) +REDIS_PORT=$((6379 + PORT_OFFSET)) +# Convert to lowercase (compatible with bash 3.2+) +DB_NAME="managing_$(echo "$TASK_ID" | tr '[:upper:]' '[:lower:]')" +ORLEANS_DB_NAME="orleans_$(echo "$TASK_ID" | tr '[:upper:]' '[:lower:]')" + +echo "🚀 Starting Docker environment for task: $TASK_ID" +echo "📊 Port offset: $PORT_OFFSET" +echo "📊 PostgreSQL: localhost:$POSTGRES_PORT" +echo "🔌 API: http://localhost:$API_PORT" +echo "💾 Redis: localhost:$REDIS_PORT" +echo "💾 Database: $DB_NAME" + +# Verify main database is accessible +echo "🔍 Verifying main database connection..." +if ! PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -d managing -c '\q' 2>/dev/null; then + echo "❌ Cannot connect to main database at localhost:5432" + echo "💡 Starting main database..." + cd "$PROJECT_ROOT/src/Managing.Docker" + # Use docker compose (newer) or docker-compose (older) + if command -v docker &> /dev/null && docker compose version &> /dev/null; then + docker compose -f docker-compose.yml -f docker-compose.local.yml up -d postgres + else + docker-compose -f docker-compose.yml -f docker-compose.local.yml up -d postgres + fi + echo "⏳ Waiting for database to start..." + sleep 15 +fi + +# Create compose file +echo "📝 Creating Docker Compose file..." +bash "$SCRIPT_DIR/create-task-compose.sh" "$TASK_ID" "$PORT_OFFSET" +COMPOSE_FILE="$PROJECT_ROOT/src/Managing.Docker/docker-compose.task-${TASK_ID}.yml" + +# Start services (except API/Workers - we'll start them after DB copy) +echo "🐳 Starting PostgreSQL, Redis..." +cd "$PROJECT_ROOT/src/Managing.Docker" +# Use docker compose (newer) or docker-compose (older) +if command -v docker &> /dev/null && docker compose version &> /dev/null; then + docker compose -f "$COMPOSE_FILE" up -d postgres-${TASK_ID} redis-${TASK_ID} +else + docker-compose -f "$COMPOSE_FILE" up -d postgres-${TASK_ID} redis-${TASK_ID} +fi + +# Wait for PostgreSQL +echo "⏳ Waiting for PostgreSQL..." +for i in {1..60}; do + if PGPASSWORD=postgres psql -h localhost -p $POSTGRES_PORT -U postgres -d postgres -c '\q' 2>/dev/null; then + echo "✅ PostgreSQL is ready" + break + fi + if [ $i -eq 60 ]; then + echo "❌ PostgreSQL not ready after 60 attempts" + if command -v docker &> /dev/null && docker compose version &> /dev/null; then + docker compose -f "$COMPOSE_FILE" down + else + docker-compose -f "$COMPOSE_FILE" down + fi + exit 1 + fi + sleep 2 +done + +# Copy database +echo "📦 Copying database from main repo..." +bash "$SCRIPT_DIR/copy-database-for-task.sh" "$TASK_ID" "localhost" "5432" "localhost" "$POSTGRES_PORT" + +if [ $? -eq 0 ]; then + # Start API and Workers using dotnet run + echo "🚀 Starting API and Workers with dotnet run..." + bash "$SCRIPT_DIR/start-api-and-workers.sh" "$TASK_ID" "$PORT_OFFSET" + + echo "" + echo "✅ Environment ready!" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "📊 API: http://localhost:$API_PORT" + echo "💾 Database: $DB_NAME on port $POSTGRES_PORT" + echo "💾 Redis: localhost:$REDIS_PORT" + echo "🔧 To view API logs: tail -f .task-pids/api-${TASK_ID}.log" + echo "🔧 To view Workers logs: tail -f .task-pids/workers-${TASK_ID}.log" + echo "🔧 To stop: bash scripts/stop-task-docker.sh $TASK_ID" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +else + echo "❌ Database copy failed" + if command -v docker &> /dev/null && docker compose version &> /dev/null; then + docker compose -f "$COMPOSE_FILE" down + else + docker-compose -f "$COMPOSE_FILE" down + fi + exit 1 +fi + diff --git a/scripts/stop-task-docker.sh b/scripts/stop-task-docker.sh new file mode 100755 index 00000000..acda2b8d --- /dev/null +++ b/scripts/stop-task-docker.sh @@ -0,0 +1,82 @@ +#!/bin/bash +# scripts/stop-task-docker.sh +# Stops and cleans up a task-specific Docker Compose environment and dotnet processes + +TASK_ID=$1 + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" +COMPOSE_DIR="$PROJECT_ROOT/src/Managing.Docker" +COMPOSE_FILE="$COMPOSE_DIR/docker-compose.task-${TASK_ID}.yml" +PID_DIR="$PROJECT_ROOT/.task-pids" +API_PID_FILE="$PID_DIR/api-${TASK_ID}.pid" +WORKERS_PID_FILE="$PID_DIR/workers-${TASK_ID}.pid" + +if [ -z "$TASK_ID" ]; then + echo "❌ Usage: $0 " + exit 1 +fi + +echo "🛑 Stopping environment for task: $TASK_ID" + +# Stop dotnet processes (API and Workers) +if [ -f "$API_PID_FILE" ]; then + API_PID=$(cat "$API_PID_FILE") + if ps -p "$API_PID" > /dev/null 2>&1; then + echo "🛑 Stopping API (PID: $API_PID)..." + kill "$API_PID" 2>/dev/null || true + sleep 2 + # Force kill if still running + if ps -p "$API_PID" > /dev/null 2>&1; then + kill -9 "$API_PID" 2>/dev/null || true + fi + echo "✅ API stopped" + fi + rm -f "$API_PID_FILE" +fi + +if [ -f "$WORKERS_PID_FILE" ]; then + WORKERS_PID=$(cat "$WORKERS_PID_FILE") + if ps -p "$WORKERS_PID" > /dev/null 2>&1; then + echo "🛑 Stopping Workers (PID: $WORKERS_PID)..." + kill "$WORKERS_PID" 2>/dev/null || true + sleep 2 + # Force kill if still running + if ps -p "$WORKERS_PID" > /dev/null 2>&1; then + kill -9 "$WORKERS_PID" 2>/dev/null || true + fi + echo "✅ Workers stopped" + fi + rm -f "$WORKERS_PID_FILE" +fi + +# Clean up log files +rm -f "$PID_DIR/api-${TASK_ID}.log" "$PID_DIR/workers-${TASK_ID}.log" 2>/dev/null || true + +# Stop Docker services (PostgreSQL and Redis) +cd "$COMPOSE_DIR" + +if [ -f "$COMPOSE_FILE" ]; then + echo "🛑 Stopping Docker services..." + if command -v docker &> /dev/null && docker compose version &> /dev/null; then + docker compose -f "$COMPOSE_FILE" down -v + else + docker-compose -f "$COMPOSE_FILE" down -v + fi + rm -f "$COMPOSE_FILE" + echo "✅ Docker services stopped" +else + echo "⚠️ Compose file not found: $COMPOSE_FILE" + echo "💡 Trying to stop containers manually..." + + # Try to stop containers by name pattern + docker stop postgres-${TASK_ID} redis-${TASK_ID} 2>/dev/null || true + docker rm postgres-${TASK_ID} redis-${TASK_ID} 2>/dev/null || true + + # Remove volumes + docker volume rm postgresdata_${TASK_ID} redis_data_${TASK_ID} 2>/dev/null || true + + echo "✅ Docker cleanup attempted" +fi + +echo "✅ Environment stopped and cleaned up" diff --git a/scripts/vibe-dev-server.sh b/scripts/vibe-dev-server.sh new file mode 100755 index 00000000..fdefef48 --- /dev/null +++ b/scripts/vibe-dev-server.sh @@ -0,0 +1,58 @@ +#!/bin/bash +# scripts/vibe-dev-server.sh +# Minimal script for Vibe Kanban worktrees +# This script runs from the worktree and uses main repo scripts for Docker setup + +TASK_ID=${1:-"DEV-$(date +%Y%m%d-%H%M%S)"} +PORT_OFFSET=${2:-0} + +# Detect worktree root +WORKTREE_ROOT="$(pwd)" + +# Check if we're in a nested structure (Vibe Kanban worktree) +if [ -d "$WORKTREE_ROOT/managing-apps" ] && [ -d "$WORKTREE_ROOT/managing-apps/src/Managing.Api" ]; then + WORKTREE_PROJECT_ROOT="$WORKTREE_ROOT/managing-apps" +elif [ -d "$WORKTREE_ROOT/src/Managing.Api" ]; then + WORKTREE_PROJECT_ROOT="$WORKTREE_ROOT" +else + echo "❌ Cannot find project structure in worktree" + echo " Current directory: $WORKTREE_ROOT" + exit 1 +fi + +echo "📁 Worktree project root: $WORKTREE_PROJECT_ROOT" + +# Find main repository (try common locations) +MAIN_REPO_PATHS=( + "/Users/oda/Desktop/Projects/managing-apps" + "$(git -C "$WORKTREE_PROJECT_ROOT" rev-parse --show-toplevel 2>/dev/null || echo '')" + "$(dirname "$WORKTREE_ROOT" 2>/dev/null)/managing-apps" +) + +MAIN_REPO="" +for path in "${MAIN_REPO_PATHS[@]}"; do + if [ -n "$path" ] && [ -d "$path" ] && [ -d "$path/scripts" ] && [ -f "$path/scripts/start-task-docker.sh" ]; then + MAIN_REPO="$path" + break + fi +done + +if [ -z "$MAIN_REPO" ]; then + echo "❌ Cannot find main repository with scripts" + echo "💡 Tried:" + for path in "${MAIN_REPO_PATHS[@]}"; do + echo " - $path" + done + exit 1 +fi + +echo "📁 Main repository: $MAIN_REPO" +echo "🚀 Starting dev environment..." +echo " Task ID: $TASK_ID" +echo " Port offset: $PORT_OFFSET" + +# Export worktree path so main repo scripts know where to run dotnet from +export VIBE_WORKTREE_ROOT="$WORKTREE_PROJECT_ROOT" + +# Call main repo's start script +bash "$MAIN_REPO/scripts/start-task-docker.sh" "$TASK_ID" "$PORT_OFFSET" diff --git a/src/.DS_Store b/src/.DS_Store index 62c7156fad2229fc2ab3fac3bb1be505f993ad55..dc42a027a61fef5d76483b593dd68ced158f230c 100644 GIT binary patch delta 1157 zcmb7EUrbY19KQElJuT&03Ro_+6)$#eN-4Gf(hAf{=^qG6WXvrK4_Y8$Y(gl+2SYZI z22Iq20AJ$69u^W~{8LlG`(k|1Iv<#BnJk(`7qe{BCtV~nKA|JKx4ITEd)R&YzVCN` z=X~e;ot%kTc4C&DTW0CBd3-aUx=QwI)ofi1v&%)?fO!j(Vt*D&|Og@#Vf9FAbK?>w^-2X;_3PJ3(vJF3>&RDXk0~o zw1bhq3M4D_$QqNXlSTLQe9C0NXk5deDj$=bEreGU%(O-??>7tN6|dW7abAGJ#>6 zNxEYFnI3~_a;-}749Zon6I z4ZUzGsx)WAhTN}dyLr8&ben275swSwwT)6=?H`0YyV3@2{oBrIa)>ZhryVOV*`E`d(QtTD7TONxQObY7g=kWR2lq%CFw4NLUA}k8hU>!H|t=i zvjF4xC8T9%<>^%7UXv(Q?|#mb>;3YmJ8AEkKBt^SHr$F#m@m+exk-kBE7FQY^9cEN zT83??ifHJaWG*^q1dM zVk`>jWFVB8j+ic#wC|ZK&O7v4H2IZmk8t9`tCoJxq(IKMVob+DU&hi&XCmSoeV8UW zTXB$|lcXse3u^eQxXA0`_y#|ha*Ho`dK$TO4whUKvT~Ko-n!m3M*=9wbtIrk9jdqf z9B6C^$vzd2suZZ5&0(HlI%2s#`quN#&wN($<=bTBAFjM|iw zloDIY)Dp^JSnXTLqCR}EXW^2aWxCh4%8z-(AsLzT`Hj5=6GRk-QN(LmT~iK7LmajJ-0-fFkl<*cKb`Yvh0 z>8N#N;rtR7?h=+gS$s#ade_A2B?8wAz7vqwj|{{x-(^S4kS1oju2Cc$gdq4~7L?3} z&X;maT|#vN`f*oKQLWN=GI8C_i}RO0qex_(H0x?+(V7bN@tx9q%Mtak3A&0tAo;eG zmZNsrFXYcA2`)!gsgfD*JnNG;xO8;_E}z=)_7FVYQW(5J(mn%j-?FrZMz42cuyLdG z_~g#VYOhp4@OfeOu}qw|O584h=#uEA7r{XJ+@e-`&|7n}|eht5qec5K#$T z+46Y|8BO_BPqo0#NLYb~zk04u->umY?AEAV$IfbVS8N;%*A#>*os zzzY1A3aHNqiLPvDZDOqc=)j;$0N5g?b;EU8UBF6fLu(Ub;XxB771pE*TVe>4j(KV0 zLTeLaO*#o%d81L-gQ=e^#N%#L$@iW0d3NdR%jJ=!`r*~=~;G^%kl7Lb>YkI zk>bc$uOE+@CP#XFXD%DQ2wa=!4U91;+a6y~zOQ#pMY()$e^lPjUblQ1kz>BekseYg^oKgUaTj&rmO>K?e) zaGDid_2{a{Ps0~^aW40*HzV%MHC^6mu^uOB&H~hJ(j$*-@%u-RS&z$dWAEDBg{SuY z(0T6eX|K26rFU4A&f!?ioEd~^E-Loxe5}9+*kot016b03KdoV*Ykh>XRTNP zR^T62Kop}!RKo#nZJj!*s@N6K|%2%@!&x(NlirrL8vzm+WfGoCT>`bQ9)e9-aUF0 z#e<+%`xi((cydTA>HDM0ZkZ*&z;y1LA-Vhd zzTN6BR~DOLuWu5|&$d_h!g{^Y4I5Au%MWKaXRfT*CS|n#Fr(jbiTKx^rv~0Sc&w$D zXFj8{opHG~rZ#GimYHj7HepE5y7fx$VjPsF>8$n!jzx%FeA?K$?Rk}7J(R6Qb`(WntIzmgcmq0sK=dyl3{^9NA0kdXk6Vgdq zkJH@j_s}`eb-|eSlX8baIHGXbil54B&o|%e>n){9sIpZ)5BpZ8^B`Gbq7Ke^2j7}> zbJV+!UDV9fx{O~}-@J~lvwz#@6WZU=``q7vg7bJ0KDO}DSLP6ZK}2ou>ZE + diff --git a/src/Managing.Api/Program.cs b/src/Managing.Api/Program.cs index 5778f695..509ac754 100644 --- a/src/Managing.Api/Program.cs +++ b/src/Managing.Api/Program.cs @@ -29,6 +29,46 @@ using Serilog.Events; using Serilog.Sinks.Elasticsearch; using OpenApiSecurityRequirement = Microsoft.OpenApi.Models.OpenApiSecurityRequirement; using OpenApiSecurityScheme = NSwag.OpenApiSecurityScheme; +using DotNetEnv; + +// Optionally load .env file if it exists (primarily for Vibe Kanban worktrees) +// This is optional - if no .env file exists, the app will use system env vars and appsettings.json +// This must happen before WebApplication.CreateBuilder to ensure env vars are available +var enableEnvFile = Environment.GetEnvironmentVariable("ENABLE_ENV_FILE") != "false"; // Can be disabled via env var + +if (enableEnvFile) +{ + // Try multiple locations: current directory, project root, and solution root + var envFilePaths = new[] + { + Path.Combine(Directory.GetCurrentDirectory(), ".env"), // Current working directory + Path.Combine(AppContext.BaseDirectory, ".env"), // Executable directory + Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "..", "..", "..", ".env")), // Project root (from bin/Debug/net8.0) + Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), ".env")), // Current directory (absolute) + }; + + string? loadedEnvPath = null; + foreach (var envPath in envFilePaths) + { + if (File.Exists(envPath)) + { + try + { + Env.Load(envPath); + loadedEnvPath = envPath; + Console.WriteLine($"✅ Loaded .env file from: {envPath} (optional - for Vibe Kanban worktrees)"); + break; + } + catch (Exception ex) + { + Console.WriteLine($"⚠️ Failed to load .env file from {envPath}: {ex.Message}"); + } + } + } + + // Silently continue if no .env file found - this is expected in normal operation + // .env file is only needed for Vibe Kanban worktrees +} // Builder var builder = WebApplication.CreateBuilder(args); diff --git a/src/Managing.Application.Abstractions/.DS_Store b/src/Managing.Application.Abstractions/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..83b70428c2214790ed165d324daafe4660378e71 GIT binary patch literal 6148 zcmeHK&r2IY6n>;13cvtkq*(1uy*zdMUKm z(5q*I1bQuaFZvgF?Wy>^nZcdOxh+%h(1W?lmYuQ6ZSh&o+0`!W;lC%gh)f&Wbbes>Ghpl#Z1Z`$u~?{DhqM3qXT z9W^i$JpEoRA8!79YkQj`yxlEp)mK%d(FDDxnAW)_?KxFx>Bq3&uHFB9{rhTH)ppkC zL@9&37>5V-HIEMzQIlHK9_BHgC?1yI=CK^exvxithZB?X$cu4#Naj%hiw5mDN<2IN zl6vgg1Gz9=IyU;NJbU+9uT$^&FRoXj73{f-s(bhiJ_2K4YgmJmPorXOPG^IY)m}?+ z%3a%Ld7pTPw+NYcKsB(8=>TjuvV41Mcg5H|! zF*r4yUy({P!+x7j?eKE(qHdleYYm%AUW~(oB=dNv;ml?WCN=urE8rFI3fwBd-v^1t z7#d78s!sg}Gt~osM~F;zEOoMx9Q=Tt0-U zEX)l>sOnf>s&LXLhaUUhE8rDK6)5Q86rca^^6&p?f**MWyaJC-0a2{fDrIcToUNG+ w@>wg<>S$~nmuOTe=*)4f27DC1KvM>vNNkGWgCb@J|)E0c%w1ZvX%Q literal 0 HcmV?d00001 diff --git a/src/Managing.Application.Tests/.DS_Store b/src/Managing.Application.Tests/.DS_Store index 236922ac47938b7d3e002098795d48d4b7a69432..80a37075602058e890191882b897cb13399928fb 100644 GIT binary patch literal 6148 zcmeHK%}T>S5T3OGi}g_HK|zGPLN8+R5=%UKu_A~U`y;86G{ssy8axYv2k~({2zvDq zd=tOfU78JT^(IngVCUP+?EK`T+3gaMYL0t#qAC%UF&MoSs2Re39#gVpEo(rxd|-V7!hkUFe;MF!w?rMfpg|nD-|y2`?n%-x?8IpYmh$82bMr2G-*dgaAH2i9 zlQq(tgGV8?>6+SZMQW@cBj?2D*8JGGjd#1crsL16&hoo;sSzM`p8KYCHHgze1RM4( zynhM?E(_gke%5l2+sn>&zqWdB-(SZiY2L}Sx6sGdE0R)$j_905VBk>Wm}1OFh5Ed1 z?n<|xlhNDDL!$eclh^I<_tk}dO&6jUlL7wiL&_C{qJ;rrKp2=X!25%b!5CP~4C<`| zN?!qh9?V)W=eq>Q_!a|;nL&6U%7g+8KD=T|LQMx+v z`+7O4z@TVhKo}@8P%@8IKL7XU-~Wq2@+1rh0}I7~^1@cw#4Fjeb?W8#to1R@Fj#n9 mW>AMf+2dGG_$c1M&;p;&6JTI5GYAVr{s?FqLAjHu~68Ok%57Mg~5d(k)ebku`IYKFDE}Q9ViA8X98jn0I`8sfB{*4 tvml2U%Vq_RUgpj09Q+(W`U?VU)yhh0XZ5{5bk2G2&6t}=xKG|YZ~F1iKrZ>vdb%Ri8xfbIzva1{pKL7hx$Z=)J`3AmU<`?@^)W11)Ks-0jGddz$x%Q zD1c|SI?9(C>#j}#r+`ynP60JP_&Ak~S(`OhPaU}EB>-#*zSajmV;!LD_}0d(%^It# zqD`}U@N8AjE-^e)9p%1qhmBdAHP%!o&r~PRM)vFq#naJI&)4qc#f)`Vr+`x+tbkg( zS5hM-=?vEGeEpuLGksk(EghNu0aI<)+d{tmnM5Mlmr25>{6X8c?BKaqjfMR?7vw+C z%~`H1q;ha~;4ec%lm>l(cl(VfAI>>;Z|2>agPJqcR(~ePSIAFt?ND4xz|}>mD5kpC z!E(-1zxh_}>SoO&+Tbktd?ZIqaa2%T@5l5)o0RTfsgT!H9qq-LR_>|4Z2K~zJx*5G zQ}B6N#aE21>!GyBvhx$zm6|Q#9M4w_H(u=0+SqzLcDPi;8`1ev0zERJJSjc!6A|ai zc+AOFcQ;I5&@owgE-#|WMcmSHG>v>{(jyD^8qCqBM}y@&{>{v{E!CH7KCm|Uoxe;@ zeVj~(eFO)6P#h(+A0q`LT_{eaZ+IDx|Kskh_iG#M{oA@cc2v2HtH(nHH6stxIMt}o zeIN+D_%RSfcyX59qigyn{n2B1-J`#$!`Xjr zxj(Dpys@~x3#ljW%e*`l#pwe0D78Ksb&!AwXoT2gRTuuv*T+T#$i1_C1yo`?P`LR_4vaMtE?J zvD&Y*^IxDHu10<@!BgZT81DE4o|Y*v1@a}nOqOzv@zFP@9;S4ku=<=K+C#)Aofj3< zioEF2PwhTfyqO72sOmO2BD^@y_d|6DX4>q08ETJn750>TJ_2K$w_+>}Qg4Jt-qg3S z2j}{9?b)XF=9wC3hco5(5J zVnhhtN%phv`FzQfV&{m6=l82AQBFh|njp(yz{EXB9ob?bS@xJNuIg%=yl=++b&zKt zQAsy+w^?_e|KhA=s=6r3O16?WsfMd9mVJx+T#00}=*eHU5v4#RQl&!>I4TnG2x@g!aYB;eKA8eVwiWg4V zv42R*iKC+Tu7E4hS74;mT<-sKd@_SYem}%#u7E4>&lKQsu_)$vDZ5(_UQh1YfVM;v rlXZ;@U>Ns)0x*$tJkF(?TCL_i6ib$A0E~g?B5gDTq0|x^}_aJp-lSu}yF$E?dPe_*$FomGp3Fyw2H@u8Qmc%qudbo0Hv zU!0x3TD}}tH~V~tY%kw&WIi`nz!h)>Tme_0s{qby+W17#dsn~}a0R{<;QkQNh{>>3 z%v%S#Tmk?KxU*r*T7ogrFd4RrU|>N*ff^dD#0VM=f3$hYuvOG>2{|*?vCLn^OUT*b zk9oR;r0BgX;0p8=uo`{B^ZydR%wUn<5Ai2gz!mss3WTCulyiKPovjC-$Fnw~-JsDp pujK%Saqkj<2ks;1nN&VYzzFq*Yp@D($0kLOZnQRHvA0eHv$TS$sabo39C%Cb4y9tzsRX zRA8RnGzE5t;8~(PMn^K5qZ$y+W!!evI>Y9EelvDG+9}*y)Tt!(U3@>w-4DOtsf%W? zixNI%>|lis&~`EUp#9M6SF!dUUMfqpp!ILMw$1)K@htHH&e1h<+KcDAKm`y9c+^U|?qK+JpBayVkn&se`w+&gQ-THPD(0c9aCAE8;X+Z@P`skD$?kCuYgy;RlwZQd-(jHY<~ZD zll(WYfLGvODWHNlA5UOQ=4@@)9G|rzS^1g3cVrGT@__|F0m1xsV6I$Y81w R9+>|_KxFWpSKwC_cmww*)jR+I literal 0 HcmV?d00001 diff --git a/src/Managing.Domain.Tests/.DS_Store b/src/Managing.Domain.Tests/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..611789fc56ad744293fe337a35cedd58a55b94ce GIT binary patch literal 6148 zcmeHKyGjE=6g^{71dZSe6l}Jz7Houo#j0yzVHFYV%tPWMn~kqdaPb2y`~$HN`~)jI z|3dH&@&khB&Wv%^L(E@$pBDGC-pgC1VDi*m>*=*N5n4LBLjA1 zf~aJTxpFOu+cG+EXl))m1D=7u%Yf|N9IDtwtJ!e(Z;?Ct)e3sUG>E`y;+)SPbB+qHAF~1hIA@7ClEE!7> zb3~qJQ6|P{qls;-Q;*2zyGn-dzQ2-N>+}4++Bng*elstZji0a9hp!yDsbVklCP!y3 zSiiNn_3X}+#){|m_pANf{CcgKc;ok6^xuf=a7tmwpl>|`o&nE5mjU@c1XRJ$Vro!- zI@std05Q*DE$qu(LVN;?p~ci7Efi&3iN;mgD~2-e91rZg&|+%PxI@{?hq95Cy`d-_ zo$CjBI#g)Tx1IsdK$d}=c^r}Rf92!*f7Z!Ac?LWK|B3;XkIK;!OR{HcPjPbA2GlL8 ph|Eh3Y8N*4IMy9Gil?YrXbYr63@xSxIYRM&1T+o4@eKSb123HgzoY;F literal 0 HcmV?d00001 diff --git a/src/Managing.Domain/.DS_Store b/src/Managing.Domain/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5db5f68cc8ba6a6025cb4d2fcd41ea1a8076e1d3 GIT binary patch literal 10244 zcmeHMO-NKx6h6<6|f3e1*`(w zK>@t8xm49?YwuP8tAJI&Q-Ifp2rjl!*XFfVO9yUh3jkY=$Ex5n_5ms;;@YTd^V+IV z)Twt5jvMN@TMS2s!yjQdY}B=RZFM*~I-DFgv*Yei9F-k$5d|kFs;#|S1*`&o1$ggX zMKKz}UsmqlhqCDj4d2aE&WA~7>&G&WFNNlcE5@R`D9P=|GWN4VixgU)7QuBE~LUMSr`nhJQQ?!6v?!9a5P<^>+F4>lUi8I=zzXXKP zszJJ9^mpTnIM}-$$?;~mr=fPyoo6aeGVyzjdIMn-B{kv^I8@H0;r zFIHv^@*8<|JHyn65ypL$zz9pB)kSmd+7AbKFMlhq{(jpiD?)3 zjVf*#5hV|-S(~8N3R$AC5I2Q-#>oJC=Ny)vcF1UOdfgWQ9+k5n?`)AChh7ry^=#~ zr`Ij3v-SwC0bE=dm)BN>;HHk_VbyUw{^8^JR$Pp2W6K4f vqpr{9 literal 0 HcmV?d00001 diff --git a/src/Managing.Infrastructure.Database/.DS_Store b/src/Managing.Infrastructure.Database/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..88b6c1f5b115727da9792aeab16b1a4239405da9 GIT binary patch literal 6148 zcmeHKO=}cE5UqAsvaBLOL_~v(r$BBwcu)|=%|tOIAnYG7v(fcqcW2$WC=$uU-yuZs z;3bD#a#b&qKOue`%}I}X@>O-k?Pg|;UPPn|x?gWsRo9z0O!qbsnZ|HsmS~cQYG{nr zI=T{LKevJ%(wQlsku`?Yr`1k-w%N)G(P1Je5ES^=6yR@nf>K(h7TqJ~`|b9Hs(H0n zjOb=bl6JBbp4#Tl!nZT0cQ2Pkt^7t*|2FRy`_(>T8LEKK9qQSAL_LddKaV_a{o!7t zvEG*Yn%B)nb&FoF-qLffSEFmxqg&L$^FN}5Qm-=2y(^1xIh=p-Z0*BU;ZRu1W%H{z zj~BgRUUgc64s9CX?L5FJ154dqRh8+j>2Yx`zmq4PyneYM{7Tn!IUW@2@tnz-X9dhs zy6dSnfA;an<8ql9TsVI8slG4CbE_AxyT_n$~Ui5nP44>bB zY&f&oYDX-FJ}3|r2nzgEfcJ+8jWJftEy~t`PObpJDyGFSmc0lV@dPkd%q?ODW^5|Z zrW(Cs7@LmyNaJF~+@eh2f$b{w}=^7 P_#+@Pgf1xXR~7gH3Ty5{ literal 0 HcmV?d00001 diff --git a/src/Managing.Infrastructure.Exchanges/.DS_Store b/src/Managing.Infrastructure.Exchanges/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..f63d47c7d3843eb2446aeac58dd5958a9345558f GIT binary patch literal 6148 zcmeHKu}T9$5S`U45|tRl!b;A@TL0h@F9>2MSXpRHyeLU7r~yI2)7H|;&eBf7!Y>eO zzs1T*-^?!Fofl7SM05vs-(_~@X7(*NlO-Zm?KkF$%0yJaV01<>4G>=Ek&z*znFK0% z$1ZKqChgNUg&AwBunbrRej5Y)?T%4}>a>UNHu?Q_X|Em3uWW{$o=&>x=h=2b->4%fz9`($p9SL1h=&-cvNCq8k;U-e1tL+U&gsYVB= z(=Al%E_Tv7Q}N0-9PhshdNxa8RHL0O1C{~Hz#9WxA6yJZ&tRlcN(Uyn0stMT zMer=W8R)VC=oySOLIY9S6{ua6xnd~o4!vvaJcE%&?M_M}<2@#_GB*?@(V=(6oRp{0 z&XxhoK$?MJ{j<#dzxMI{Kka0HSq3Zve~JO+_$z)DTQa>hvpMdyF2*_r3)@8+#RZdT h$MV3fcnU)VYc4+kJ%f=(Xdw2FfY4wk%fOE^@CwhsxHbR) literal 0 HcmV?d00001 diff --git a/src/Managing.Infrastructure.Messengers/.DS_Store b/src/Managing.Infrastructure.Messengers/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c470363fd08c09a4265691fc04525393e74930c6 GIT binary patch literal 6148 zcmeHKOHRWu5FNLbD54UD6-!^CHwaNsw@AG}l}0L{rl~;Pfe4&{JFsWR8CY`xBo-Wi z3jl9CR^t%L5)hh^#?P6L$9{=on}|%j%mze#BI-gJTbpRU5cab+q~$F=py4qFqe+o3 zob|jBt%kqI0KdC7rF2a5*))8A@QdX-=kG2^R)_=KweR`g|`k%(hi)tS0qiXXp{M}>y1sFJ~&0~9cS9!wv z!>i$L@7k~5<%M;d-deq#8?L9K3@8K2z;82vJ)5PwC8(`3pbRJjD+c)gV4;kW$5PP! zI?%W)0I&nI6ZGAg3TW8?j69Ztut1EY0wvY>D~6GD*sYI?JeGozPR3QnIKHy+HxxP1 z!ERkRnMhDuWk4CIGtidDKJWhr>+k>dBz;l_l!1T6faxToB*v2b-r86k@3j^>hO%&6 mDY!~O$8E)k<*j%R>I8Pn9bn|K6odt$2LVTeHp;+{GVlTP=4I#r literal 0 HcmV?d00001 diff --git a/src/Managing.Infrastructure.Storage/.DS_Store b/src/Managing.Infrastructure.Storage/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..3b221f2fd6d98c8c25498a7e1197d3035e880c63 GIT binary patch literal 6148 zcmeHKOHRWu5FOJjA{C*E6-!^CHwaOBf?fcHqVj2QH!NU7#GVxw;3(|41DAj!@a6+a z)QBZQXhyQ1Gtc8mUR94xM4`M{&5342l%p{Q9*h{fN2xuV%w*s-=F8L6Y{h$P++PQN z_X*W>LD!pg|NY+{JElohRc}%aPkwflmG|q{<379kf!&_>R=s;c81f}#yd314KEHQN zKi|{G;&A`L@=08ix_rCrAm0K1u5PY?E8q&a0D;eiDW1!`!pD@M?8_@m7$3|mDFry!ZJj%EJ3 zyaYS(hA7i16pG%v0tUqnF1lJmQ{(5vf8@yd0cBF w+6fvP&ue)A!&pi&P)ac#cpo_uQu)YZ@P%Qk$g8kl!hwDe5J9|i1%5$+PY@qLJOBUy literal 0 HcmV?d00001 diff --git a/src/Managing.Infrastructure.Web3/.DS_Store b/src/Managing.Infrastructure.Web3/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c896a06571611923c15fd7b96d7de1c193a662e0 GIT binary patch literal 8196 zcmeHMyKWOf6usj-IGH1;0Rn zM28TMPl!ZApy2TVRMZp*iHZhs?##f>c-IRE30cY=Y38oxo;!1VX1wD&CL&eZZmtk5 z5K$hL?TMpkQVRRICQ8osEW#?p6ZL7G8g!esC`zEELlh7NL;+Di6c7a_K>?iET=HYi zedCo@6c7atr2_nZ2vFIE)((x;uMRXi1%RDKw=Q@_9-w0aYeQ>?#_CXvX|e}pLzPW2 zlnIAFU^r}O?a){gPRfLnvNJ22p(s5&;sOmP6&fq8C?ExKt-z40C~HczjtZS zZmm=sQKx6Za{Vl9C#qEH?Whh+zImZ`@6FolVm7|{SNPth%O$|jGzHdM)b&`tEFHui zm(!J{Gv(cu=49hKQOqFe_2xVH!t>2h8TT4pN2gJR-ld~l9&3&3w{|u(kCgFTPT5G0 zpLuB>p;g)eyA5z0=sTFi8qV#4VJgn$`1QrJ_opstj$^Q~a=*i-@SLTq(6I@g?a@8< zCca}9vS#pn?J#Oyv^a8 zr>f?B2YefN@^}5r{&(iGNrN&X1JO%xCX{!sxn zU8z<|7{un*iQzcc4p3{TTo^YrR)?Tr2>0`E7q-9tFvN3U`$B7n#=?X0-!B62D?!eG KExj~{Sb-n8Bw2g_ literal 0 HcmV?d00001 diff --git a/src/Managing.Nswag/.DS_Store b/src/Managing.Nswag/.DS_Store index 635e842ecc594cf74e5f93d8eacc661b265ab7f4..49d884e47b222eec40091089de751edc124c7342 100644 GIT binary patch delta 288 zcmZoMXfc@J&nUPtU^g?P;AS2cLB{%=bi?4}{M-Tt5O8@g8AviSBr#+%#N;W&(*$)2R2JbBOj#7Cur~k=W#D26U?>9GnGPfq8FDA7taNq=G6O7llVQJ|2;15;imxY0}Ws zK!h)uJDA0#0-eM>pj(N>~DP!)@ zhm+#XhvLkNcPPqb$N9B$CzX1XQ4|mbstRaKHK;?6X?<-q+`oU{E-jg9w>xX5gPG=+ zubZvctKa5AYj=RP_b52)r)7j8-vVXyD$3W``CVGVe4A&oXD6@j`+P1gGiAQ2HOklc z+q?(Q>6cj!5FX$5183_eez+{yVX z$lb>)GtCAh>-W*+k*FyJmGab zd{k5q-L>_c1sHmPHT)9Y&^oFyw1IE90#P-|*1KW;VJ-Wgi&_Te2rD^kOjJi=7bBgh zy$b67%HQ^o=je}uXLOE`SDjD9L-h`L^w&>KU1A=EJ>+p=?AF1WwLAi!a<$g^#5}I^ z>jT~cQcDS#dz9zD(?JGN;HU~T{0XM*{(rvy_y41&k$6!+6gb8TsFC(ky9I*$Y^_jD vFr(3z(QUJSxknd*!MfOaw;cx-e;DFevn^%JJ;H(}KLj`#WDo`ZsRDlhLZ}pf literal 0 HcmV?d00001 diff --git a/src/Managing.Workers.Tests/.DS_Store b/src/Managing.Workers.Tests/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..d3609f75d5a37fd190de7bc4af2018dc72db3606 GIT binary patch literal 6148 zcmeHKu}T9$5S=v#24fMhiHL9?phXHn8#&`y*onypm>5ZvBo~M&C5OF@A0d8&g{{Bf zZ>ZQ<`DS)W_DG_gh|a*y+nd?h*?Dj`w?t$r!)BSNNJM!I#$X9*hOnQ$Lp$ck_PY=_Ya9=p+qT@{fl%`=i#=p6_jb z;qAA*U3($ID4>|?bV+qTBb7dOeV?E6_F?D!sxCRlvE5{nb(Y`HORHQa>P%4SMJDUo z*7n5X=X`!?uPk4?Iwj7}IPJ~kTaP$jfogO{15|n}IHV5dgG_#2H+Q9fp1Y&hjkl4U zXU@L<`MzJBIj=p1>i@+6dNxbGU{SR)pbRJjV+Q#95MnS!4pWQr>41_e05E`A1as-N zz>p2V$YE*`7KpK-KpSe@6~owY*h9B2a+q4Q;bbH;_HmhwyP+7#4tpre$wU@aD+9_v zmVumoEOP%pn1BDz2I-SBpbY#e222oF;|fZ0y>+TM?zJJt2?h(VOD#$WlxxQ_;Z|J2 a5P>h`2{3Y)T7(6nKLSF7DrMkD8TbSbuZ6Mz literal 0 HcmV?d00001 diff --git a/src/Managing.Workers/.DS_Store b/src/Managing.Workers/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..61b061a8ab78195faa110171a4fc02e9bd95ea92 GIT binary patch literal 6148 zcmeHKy-ve05I(mVQs_`Y2NtAAJV95c(1snU8w;pEDxii${0vM)JOSb%cooEgkQjLf zo`LV|6LFLlwn{~JlKt6tK7aNXC60;6^lv9Uq7D&-D2$C3ss+YzE;Vb2rwuebM{hXJ z(ww~k`f6*S06)7Xjp&>%=QIEL4R*^&nkC6-o{iuM?><_C``OEZAD#RX&Ck49!$+in zF9YL+&qv$Gdu7Dud;3ba+7H5K^U|#3t4Do4>b^7I1|88AICGi;Z?M-XU02x2beE0u z*YfoFy#IP)*RpU7Azbh0y8cZ=u(YbF^v2Q8JCWDEaMA@E}e{J#yrAo z37AzdX1JfS?D}z?5z)BVP2E-X=egFUf literal 0 HcmV?d00001