## Context

The tool system currently supports:
- ToolTypes with compose templates and basic metadata
- ToolConfigs as simple key-value pairs (env vars or files)
- Instance creation via compose rendering
- Basic flat-list UI at `/tool-configs`

Users need a much richer system for defining, configuring, and running development tools.

## Goals / Non-Goals

**Goals:**
- Support both Docker Compose and Dockerfile for tool definitions
- Add readiness probes with configurable commands and timeouts
- Create reusable config file collections ("folders") mountable as volumes
- Add rich tool config fields (port, start_command, working_directory, volumes, env vars)
- Build a unified "Tool Workshop" UI for all tool management
- Support per-project overrides on config folders
- Maintain backward compatibility with existing built-in tool types

**Non-Goals:**
- Docker image registry management (assume local builds or public images)
- Real-time collaborative tool editing
- Tool marketplace/sharing between users
- Advanced orchestration (Kubernetes, Swarm)
- Config folder versioning/Git integration

## Architecture

### Data Model

```
┌─────────────────────────────────────────────────────────────────┐
│                        TOOL WORKSHOP                             │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌──────────────┐     ┌──────────────┐     ┌──────────────┐     │
│  │   ToolType   │────▶│  ToolConfig  │◀────│ ConfigFolder │     │
│  │  (Blueprint) │     │  (Settings)  │     │  (Files)     │     │
│  └──────────────┘     └──────────────┘     └──────────────┘     │
│         │                    │                    │             │
│         │                    │                    │             │
│         ▼                    ▼                    ▼             │
│  ┌──────────────────────────────────────────────────────┐      │
│  │                   ToolInstance                        │      │
│  │              (Runtime + Volumes)                      │      │
│  └──────────────────────────────────────────────────────┘      │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘
```

### ToolType Model

```python
class ToolType:
    # Existing fields
    name: str                          # unique identifier
    display_name: str
    description: str | None
    category: str
    interfaces: list[str]              # ["web", "terminal"]
    default_port: int
    required_variables: list[str]
    is_builtin: bool
    
    # New fields
    definition_type: str               # "compose" | "dockerfile"
    compose_template: str | None       # YAML template (if definition_type == "compose")
    dockerfile_template: str | None    # Dockerfile content (if definition_type == "dockerfile")
    build_context: dict | None         # {"files": {"path": "content"}} for dockerfile builds
    readiness_probe: dict | None       # {"command": "...", "timeout": 30, "interval": 2}
```

**Decision**: Store both compose and dockerfile, use `definition_type` to determine which to use. This allows easy switching and migration.

### ToolConfig Model

```python
class ToolConfig:
    # Existing fields
    user_id: UUID
    tool_type_id: UUID
    project_id: UUID | None            # null = global config
    key: str
    value: str
    config_type: str                   # "env" | "file"
    file_path: str | None
    
    # New fields
    port_override: int | None          # Override tool type default port
    start_command: str | None          # Override container start command
    working_directory: str | None      # Working directory inside container
    environment_variables: dict | None # JSON {"KEY": "value", ...}
    volumes: list[dict] | None         # JSON [{"source": "...", "target": "...", "type": "..."}]
```

**Decision**: Store env vars and volumes as JSONB for flexibility. Port as integer with validation.

### ConfigFolder Model (NEW)

```python
class ConfigFolder:
    id: UUID
    user_id: UUID
    name: str                          # e.g., "my-dotfiles", "vscode-settings"
    description: str | None
    mount_path: str                    # Default mount path in container (e.g., "/home/user/.config")
    files: dict                        # JSON {"relative/path": "content", ...}
    project_overrides: dict | None     # JSON {project_id: {"mount_path": "...", "files": {...}}}
    is_active: bool                    # Quick toggle
    created_at, updated_at
```

**Decision**: Files stored as JSONB with relative paths as keys. This is simple and sufficient for config files (not binary assets).

### Volume Mount Resolution

When creating an instance, volumes are resolved in this priority order:

```
1. ToolConfig.volumes (explicit per-config mounts)
2. ConfigFolder mounts (user's active config folders)
3. ToolType default volumes (from compose/dockerfile)
```

Config folder files are written to the instance directory under `volumes/<folder_name>/` and mounted from there.

### Readiness Probe System

```python
class ReadinessProbe:
    command: str                       # e.g., "curl -f http://localhost:8080/health"
    timeout: int                       # seconds (default: 30)
    interval: int                      # seconds between checks (default: 2)
    retries: int                       # max attempts (default: timeout/interval)
```

**Execution Flow**:
1. Start container
2. Wait for container to be running
3. Execute probe command inside container via `docker exec`
4. If success → mark instance as "running"
5. If timeout → mark instance as "failed" with probe output in logs

**Decision**: Probes run inside the container using `docker exec`. This works for both network-based probes (curl) and command-based probes (binary version checks).

### Instance Creation Flow

```
1. Generate instance ID and directory
2. Resolve ToolConfig (global + project-specific)
3. Write config files:
   a. .env file (from env-type ToolConfigs)
   b. Config files (from file-type ToolConfigs)
   c. Config folder files (to volumes/<folder>/)
4. IF ToolType.definition_type == "dockerfile":
   a. Write Dockerfile + build context files
   b. Build image: docker build -t <instance_tag> .
   c. Generate compose from template using built image
5. IF ToolType.definition_type == "compose":
   a. Render compose template with variables
6. Write docker-compose.yml
7. docker compose up -d
8. Connect to backend network
9. IF readiness_probe defined:
   a. Execute probe with timeout
   b. Update status based on result
10. IF web interface:
    a. Create Cloudflare tunnel
    b. Update URL
```

## UI Design

### Tool Workshop Page (`/tool-workshop`)

```
┌─────────────────────────────────────────────────────────────────┐
│ Tool Workshop                                          [+ New]  │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌──────────────┐  ┌──────────────────────────────────────┐     │
│  │              │  │                                      │     │
│  │ MY TOOLS     │  │  [Tool Type Builder]                 │     │
│  │              │  │                                      │     │
│  │ ▼ Code Editor│  │  Name: [____________]                │     │
│  │   □ VS Code  │  │  Type: (•) Compose  ( ) Dockerfile │     │
│  │   □ Cursor   │  │                                      │     │
│  │              │  │  [Compose Template / Dockerfile]     │     │
│  │ ▼ AI Tools   │  │  ┌────────────────────────────────┐  │     │
│  │   □ OpenCode │  │  │ version: '3.8'                 │  │     │
│  │   □ Continue │  │  │ services:                      │  │     │
│  │              │  │  │   app:                         │  │     │
│  │ CONFIGS      │  │  │     image: ...                 │  │     │
│  │              │  │  │     ports:                     │  │     │
│  │ ▼ Global     │  │  │       - "{{PORT}}:8080"        │  │     │
│  │   □ dotfiles │  │  │     volumes:                   │  │     │
│  │   □ api-keys │  │  │       - ...                    │  │     │
│  │              │  │  └────────────────────────────────┘  │     │
│  │ ▼ Project X  │  │                                      │     │
│  │   □ overrides│  │  Readiness Probe:                    │     │
│  │              │  │  Command: [curl -f localhost:8080]   │     │
│  │              │  │  Timeout: [30] seconds               │     │
│  │              │  │                                      │     │
│  │              │  │  [Save Tool Type]                    │     │
│  │              │  │                                      │     │
│  └──────────────┘  └──────────────────────────────────────┘     │
│                                                                  │
│  Tabs: [Tool Types] [Configs] [Config Folders]                   │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘
```

**Navigation Structure**:
- Left sidebar: Hierarchical tree
  - Tool Types (expandable, shows instances count)
  - Config Folders (grouped by global/project)
- Right panel: Context-aware editor based on selection
- Tab bar: Switch between Tool Types / Configs / Config Folders views

### Config Editor

```
┌─────────────────────────────────────────────────────────────────┐
│ Edit Config: OpenCode API Keys                                  │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Basic Settings              │  Advanced Settings               │
│  ────────────────────────────┼────────────────────────────────  │
│  Key: [OPENAI_API_KEY]       │  Port Override: [_____]          │
│  Value: [sk-...        ]     │  Start Command: [_____]          │
│  Type: (•) Env  ( ) File     │  Working Dir: [/workspace]       │
│  File Path: [__________]     │                                  │
│                              │  Environment Variables:          │
│                              │  ┌──────────────────────────┐    │
│                              │  │ KEY        │ VALUE       │    │
│                              │  │ OPENAI_KEY │ sk-...      │    │
│                              │  │ MODEL      │ gpt-4       │    │
│                              │  └──────────────────────────┘    │
│                              │                                  │
│                              │  Volume Mounts:                  │
│                              │  ┌──────────────────────────┐    │
│                              │  │ SOURCE     │ TARGET      │    │
│                              │  │ dotfiles   │ ~/.config   │    │
│                              │  │ vscode-set │ ~/.vscode   │    │
│                              │  └──────────────────────────┘    │
│                              │                                  │
│  [Delete]  [Cancel] [Save]   │                                  │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘
```

### Config Folder Manager

```
┌─────────────────────────────────────────────────────────────────┐
│ Config Folder: my-dotfiles                                      │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Name: [my-dotfiles]                                            │
│  Description: [My personal dotfiles]                            │
│  Default Mount Path: [/home/user]                               │
│                                                                  │
│  Files:                                                          │
│  ┌──────────────────────────────────────────────────────┐       │
│  │ Path                    │ Size  │ Actions            │       │
│  │ .zshrc                  │ 2.1KB │ [Edit] [Delete]    │       │
│  │ .gitconfig              │ 412B  │ [Edit] [Delete]    │       │
│  │ .config/starship.toml   │ 1.8KB │ [Edit] [Delete]    │       │
│  └──────────────────────────────────────────────────────┘       │
│                                                                  │
│  [+ Add File]                                                    │
│                                                                  │
│  Project Overrides:                                              │
│  ┌──────────────────────────────────────────────────────┐       │
│  │ Project       │ Mount Path        │ Files Override   │       │
│  │ Project Alpha │ /home/dev         │ [3 files]        │       │
│  │ Project Beta  │ /workspace        │ [1 file]         │       │
│  └──────────────────────────────────────────────────────┘       │
│                                                                  │
│  [Add Override]  [Delete Folder]  [Save]                         │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘
```

## Decisions

1. **Dockerfile vs Compose**: Support both. `definition_type` field determines which path to use. Compose is the default for backward compatibility.

2. **Config Folder Storage**: Store files as JSONB keyed by relative path. This avoids file system complexity and works well for text-based config files. Limit: 10MB per folder.

3. **Readiness Probe Execution**: Use `docker exec` to run commands inside the container. This is the most flexible approach (works for HTTP checks, binary checks, file checks).

4. **Volume Resolution Order**: Config-level volumes override config-folder volumes, which override tool-type defaults. Last-write-wins for conflicts.

5. **UI Organization**: Single page with three tabs (Tool Types, Configs, Config Folders) and a left sidebar for navigation. This consolidates the current `/tool-configs` and `/tool-types` pages.

6. **Project Overrides**: ConfigFolders support per-project overrides for mount_path and files. This allows project-specific customizations while keeping the base collection reusable.

## Risks / Trade-offs

- **Dockerfile build times**: Building images on-demand is slow. Mitigation: Document that users should use pre-built images in compose for faster startup; dockerfile is for custom tools.
- **Config folder size limits**: JSONB has practical limits. Mitigation: 10MB limit per folder, enforced in API.
- **Readiness probe complexity**: Commands might hang or fail in unexpected ways. Mitigation: Strict timeout, clear error messages, probe logs stored on instance.
- **Migration complexity**: Existing tool types need `definition_type` set to "compose". Mitigation: Database default, seed function update.
- **UI complexity**: Three tabs with different editors could feel overwhelming. Mitigation: Progressive disclosure (hide advanced fields, collapsible sections).

## API Endpoints

### Tool Types
- `GET /tool-types` - List all (existing)
- `POST /tool-types` - Create with new fields
- `PUT /tool-types/{id}` - Update with new fields
- `GET /tool-types/{id}/validate` - Validate compose/dockerfile syntax

### Tool Configs
- `GET /tool-configs` - List with new fields
- `POST /tool-configs` - Create with new fields
- `PUT /tool-configs/{id}` - Update with new fields
- `GET /tool-configs/defaults/{tool_type_id}` - Get suggested defaults

### Config Folders (NEW)
- `GET /config-folders` - List user's folders
- `POST /config-folders` - Create folder
- `PUT /config-folders/{id}` - Update folder (files, mount_path)
- `DELETE /config-folders/{id}` - Delete folder
- `POST /config-folders/{id}/overrides` - Add project override
- `PUT /config-folders/{id}/overrides/{project_id}` - Update override
- `DELETE /config-folders/{id}/overrides/{project_id}` - Remove override

## Database Schema

### Migration: tool_types
```sql
ALTER TABLE tool_types 
ADD COLUMN definition_type VARCHAR(20) NOT NULL DEFAULT 'compose',
ADD COLUMN dockerfile_template TEXT,
ADD COLUMN build_context JSONB DEFAULT '{}',
ADD COLUMN readiness_probe JSONB;

-- Ensure consistency
ALTER TABLE tool_types 
ADD CONSTRAINT chk_definition_type 
CHECK (definition_type IN ('compose', 'dockerfile'));
```

### Migration: tool_configs
```sql
ALTER TABLE tool_configs
ADD COLUMN port_override INTEGER,
ADD COLUMN start_command TEXT,
ADD COLUMN working_directory TEXT,
ADD COLUMN environment_variables JSONB DEFAULT '{}',
ADD COLUMN volumes JSONB DEFAULT '[]';

ALTER TABLE tool_configs
ADD CONSTRAINT chk_port_range 
CHECK (port_override IS NULL OR (port_override >= 1 AND port_override <= 65535));
```

### New Table: config_folders
```sql
CREATE TABLE config_folders (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    name VARCHAR(255) NOT NULL,
    description TEXT,
    mount_path VARCHAR(1024) NOT NULL,
    files JSONB NOT NULL DEFAULT '{}',
    project_overrides JSONB DEFAULT '{}',
    is_active BOOLEAN NOT NULL DEFAULT true,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE(user_id, name)
);

CREATE INDEX idx_config_folders_user ON config_folders(user_id);
```
