Metadata-Version: 2.4
Name: roundhouse-sdd
Version: 2026.4.0
Summary: Spec-Driven Development engine for AI-assisted solo development
License: MIT
License-File: LICENSE
Author: Pierre Grothe
Requires-Python: >=3.14,<4.0
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.14
Requires-Dist: click (>=8.0,<9.0)
Requires-Dist: pluggy (>=1.6.0,<2.0.0)
Requires-Dist: pydantic (>=2.0,<3.0)
Requires-Dist: rich (>=13.0)
Requires-Dist: sqlite-vec (>=0.1)
Requires-Dist: textual (>=1.0)
Description-Content-Type: text/markdown

<div align="center">
  <img src="docs/roundhouse-lee.png" alt="Roundhouse Logo" width="200" />

  <h1>Roundhouse</h1>

  <p><strong>Spec-Driven Development engine for AI-assisted solo development.</strong></p>

  <p>
    [![CI](https://github.com/pierregrothe/roundhouse/actions/workflows/ci.yml/badge.svg)](https://github.com/pierregrothe/roundhouse/actions/workflows/ci.yml)
    [![PyPI](https://img.shields.io/pypi/v/roundhouse-sdd)](https://pypi.org/project/roundhouse-sdd/)
    <img src="https://img.shields.io/badge/python-3.14%2B-blue.svg" alt="Python 3.14+">
    <img src="https://img.shields.io/badge/license-MIT-orange.svg" alt="MIT License">
  </p>
</div>

Roundhouse is a standalone governance tool that replaces a full software team's
coordination layer -- PM, architect, QA, tech writer -- for developers working
with AI coding assistants. It solves the "two-week vacation" problem:
persistent project memory, clear next actions, and enforced architectural
coherence across sessions.

```
$ roundhouse status

Project: MyProject
Active Phase: Core Services [====>        ] 33%
Next Module:  auth-service (Phase: Core Services)
Progress:     2/6 modules complete
Blockers:     none

$ roundhouse next

Next: auth-service
Phase: Core Services (active)
Feature: User Authentication (P1)
Action: Create spec with 'roundhouse spec new --feature 2'
```

---

## Table of Contents

- [Why Roundhouse](#why-roundhouse)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Core Concepts](#core-concepts)
- [CLI Reference](#cli-reference)
- [TUI (Terminal UI)](#tui-terminal-ui)
- [Using as a Library](#using-as-a-library)
- [AI Integration](#ai-integration)
- [Architecture](#architecture)
- [Policy Enforcement](#policy-enforcement)
- [Configuration](#configuration)
- [Development](#development)
- [License](#license)

---

## Why Roundhouse

Without governance, AI coding assistants generate plausible but incoherent
systems across conversations. Every new session starts from zero context.
Architectural decisions get re-debated. Features drift from specs. The
codebase grows but nobody tracks what was built, why, or what comes next.

Roundhouse provides **the memory and the rules**. The AI provides **the
intelligence**.

**What it tracks:**
- Features (what to build) and their specs (how to build it)
- Modules (code units), phases (sequencing), milestones (delivery checkpoints)
- Architecture Decision Records (why it's built this way)
- Policies (enforcement rules derived from ADRs)
- Research briefs (what we investigated)
- Sessions (where we left off)

**What it computes:**
- "What's next?" -- topological sort over phase dependencies
- "Where was I?" -- last session context with time-since and diff
- "What rules apply?" -- three-tier policy resolution (constitutional > scoped > global)
- Quality gates for the spec pipeline (specify > clarify > plan > tasks > implement)
- Completion percentages across milestones, phases, and modules

---

## Installation

### Requirements

- Python 3.14+
- pip

### Install from PyPI

```bash
pip install roundhouse-sdd
roundhouse status            # Works after pip install
```

### Install from source (development)

```bash
git clone https://github.com/pierregrothe/roundhouse.git
cd roundhouse
pip install -e ".[dev]"
roundhouse status              # CLI dashboard
python -m roundhouse status    # Alternative (debugger-friendly)
```

> **Note:** Activate the virtual environment before running commands.
> After `pip install`, the bare `roundhouse` command is available.

---

## Quick Start

### 1. Initialize a project

```bash
cd /path/to/your/project
roundhouse init --scope myproject
```

This creates a `.roundhouse/` directory with:
- `config.toml` -- project configuration
- `roundhouse.db` -- SQLite database (commit this to git)

### 2. Add features

```bash
roundhouse feature add "User Authentication" -d "Login, registration, password reset" -p P1
roundhouse feature add "REST API Layer" -d "Public API endpoints for all services" -p P0
roundhouse feature add "Analytics Dashboard" -d "Usage metrics and reporting" -p P2
```

### 3. Create architecture decisions

```bash
roundhouse adr add "Use Protocol-based design" \
  --context "Need flexible service interfaces" \
  --decision "All services expose Protocol classes (PEP 544)"
```

### 4. Set up your roadmap

```bash
roundhouse milestone add "MVP"
roundhouse phase add "Foundation" --milestone 1
roundhouse phase add "Core Services" --milestone 1
roundhouse module add "data-models" --phase 1 --scope myproject
roundhouse module add "auth-service" --phase 2 --scope myproject
```

### 5. Check status

```bash
roundhouse status          # Full dashboard
roundhouse next            # Next actionable module
roundhouse resume          # Context from last session
```

### 6. Create a spec and start building

```bash
roundhouse spec new --feature 1 --tier T2
roundhouse spec advance 1              # Move through pipeline phases
roundhouse spec advance 1 --force      # Bypass quality gate if needed
```

### 7. Save your session

```bash
roundhouse session save --summary "Implemented auth module, 3 tests passing"
```

---

## Core Concepts

### Entities

Roundhouse tracks 10 entity types organized in three layers:

**Governance Layer** (can be global or scoped to specific projects):
- **ADR** -- Architecture Decision Record. The rationale behind a decision.
- **Policy** -- Enforcement rule derived from an ADR. Machine-checkable.
- **Research** -- Investigation brief documenting technical exploration.

**Planning Layer** (always scoped to one project):
- **Feature** -- What to build. Has priority (P0-P3) and lifecycle status.
- **Module** -- Code organizational unit. Maps to a package or directory.
- **Phase** -- Sequenced container of work. Modules belong to phases.
- **Milestone** -- Delivery checkpoint. Groups phases into releases.

**Execution Layer** (inherited scope):
- **Spec** -- Formal requirements for a feature. 1:1 with feature.
- **Task** -- Discrete implementation unit within a spec.
- **Session** -- Work context snapshot for continuity.

### Spec Pipeline

Every feature goes through a five-phase pipeline:

```
specify --> clarify --> plan --> tasks --> implement
```

Each transition has a quality gate:

| Transition | Gate |
|-----------|------|
| specify -> clarify | Minimum number of user stories (tier-dependent) |
| clarify -> plan | Spec maturity >= S3 (Reviewed) |
| plan -> tasks | Plan content exists |
| tasks -> implement | At least 1 task defined |

Use `--force` to bypass gates when AI is unavailable or for rapid prototyping.
Bypassed specs are tagged `quality:bypassed` for audit.

### Complexity Tiers

Specs are classified by complexity, which determines quality gate thresholds:

| Tier | Scope | Example |
|------|-------|---------|
| T1 | Data models | Pydantic models, schemas |
| T2 | Single service | One service with protocol + implementation |
| T3 | Multi-component | Multiple services coordinating |
| T4 | Full system | End-to-end feature across all layers |

### Scopes (Monorepo Support)

Scopes partition entities for monorepo or multi-project use. Each scope
maps to filesystem paths.

- **Scoped entities** (module, phase, milestone, session) belong to one scope.
- **Multi-scope entities** (ADR, policy, research, feature) can be global
  (apply to all scopes) or assigned to specific scopes.
- **Global** = no scope entries. A constitutional ADR like "ASCII-only"
  applies everywhere.

### Policy Resolution

When checking which policies apply to a scope, Roundhouse resolves conflicts:

1. **Constitutional policies** always win (regardless of scope)
2. **Scope-specific policies** take precedence over global
3. **Global policies** are the fallback
4. Within the same tier, lower `priority` number wins
5. Duplicate slugs are deduplicated (first seen wins)

---

## CLI Reference

> All examples below use the bare `roundhouse` command. Activate the
> virtual environment first, or install via `pip install roundhouse-sdd`.

### Global Options

```
--db TEXT         Path to roundhouse.db (overrides auto-discovery)
-s, --scope TEXT  Active scope slug (overrides config default)
--help            Show help for any command
```

### Project Setup

```bash
roundhouse init                     # Initialize new project
roundhouse init --scope myproject   # Initialize with named scope
```

### Status and Navigation

```bash
roundhouse status                   # Full project dashboard
roundhouse next                     # Next actionable module
roundhouse resume                   # Last session context
```

### Features

```bash
roundhouse feature list                          # List all features
roundhouse feature list --status accepted        # Filter by status
roundhouse feature list -f json                  # JSON output
roundhouse feature add "Title" -d "Desc" -p P1   # Add feature
roundhouse feature show 1                        # Show details
```

### Specs and Pipeline

```bash
roundhouse spec new --feature 1 --tier T2   # Create spec for feature
roundhouse spec show 1                      # Show spec with pipeline status
roundhouse spec advance 1                   # Advance to next phase
roundhouse spec advance 1 --force           # Bypass quality gate
```

### Tasks

```bash
roundhouse task list --spec 1    # List tasks for a spec
roundhouse task start 1          # Mark task in-progress
roundhouse task done 1           # Mark task complete
```

### Architecture Decision Records

```bash
roundhouse adr list                          # List ADRs
roundhouse adr list --status accepted        # Filter by status
roundhouse adr add "Title" --context "Why" --decision "What"
roundhouse adr show 1                        # Show with policies + research
```

### Policies

```bash
roundhouse policy list                       # List active policies
roundhouse policy list --enforcement hook    # Filter by enforcement type
roundhouse policy show protocol-design       # Show by slug or ID
```

### Research

```bash
roundhouse research list                     # List research briefs
roundhouse research add "Survey topic"       # Create new brief
roundhouse research show 1                   # Show details
```

### Modules, Phases, Milestones

```bash
roundhouse module list                       # List modules
roundhouse module list --status planned      # Filter by status
roundhouse module show 1                     # Show details

roundhouse phase list                        # List phases
roundhouse phase show 1                      # Show with completion

roundhouse milestone list                    # List milestones
roundhouse milestone show 1                  # Show with phases
```

### Sessions

```bash
roundhouse session save -s "Summary of work"   # Save current session
roundhouse session list                        # List past sessions
```

### Scopes

```bash
roundhouse scope list                  # List all scopes
roundhouse scope set myproject         # Set default scope
```

### Search

```bash
roundhouse search "authentication"              # Search all entities
roundhouse search "protocol" --type adr         # Filter by entity type
```

### Background Tasks

```bash
roundhouse queue status              # Show pending/done/failed counts
roundhouse queue process             # Process deferred tasks
roundhouse queue process --batch 50  # Process in larger batches
```

### Output Formats

All list commands support `-f` / `--format` with three options:

```bash
roundhouse feature list -f table   # ASCII table (default)
roundhouse feature list -f json    # JSON
roundhouse feature list -f plain   # Pipe-separated values
```

---

## TUI (Terminal UI)

Launch the interactive terminal UI:

```bash
roundhouse tui
```

### Screens

| Key | Screen | Purpose |
|-----|--------|---------|
| 1 | Dashboard | Current focus, progress, next module, blockers |
| 2 | Roadmap | Milestone/phase/module tree with progress bars |
| 3 | Pipeline | Active spec progression and task checklist |
| 4 | Governance | ADR list with policies |
| 5 | Research | Research briefs with maturity levels |

### Keyboard Navigation

| Key | Action |
|-----|--------|
| Alt+1-6 | Switch tab/screen |
| Ctrl+P | Command palette |
| e | Edit selected item |
| d | Delete selected item |
| s | Advance status of selected item |
| c | Create new item |
| 1-N | Filter by status |
| / | Search |
| ? | Help |
| S | Switch scope |
| j/k or arrows | Navigate lists |
| Enter | Drill into selected item |
| Esc | Go back |
| q | Quit |

### Context Panel

The right sidebar shows details of the currently selected entity:
fields, status, related entities, and tags. It updates automatically
as you navigate.

---

## Using as a Library

Roundhouse is designed to be consumed as a Python library by AI tool plugins
(Claude Code, Gemini CLI, etc.) or any Python application.

### Basic Usage

```python
from roundhouse.core.db import connect, run_migrations
from roundhouse.core.results import Ok, Err
from roundhouse.repositories.features import FeatureRepository
from roundhouse.repositories.links import LinkRepository
from roundhouse.repositories.milestones import MilestoneRepository
from roundhouse.repositories.modules import ModuleRepository
from roundhouse.repositories.phases import PhaseRepository
from roundhouse.services.roadmap import RoadmapService

# Connect to the project database
conn = connect("/path/to/project/.roundhouse/roundhouse.db")

# Build repositories
repos = {
    "modules": ModuleRepository(conn=conn),
    "phases": PhaseRepository(conn=conn),
    "milestones": MilestoneRepository(conn=conn),
}
links = LinkRepository(conn=conn)

# Use services
roadmap = RoadmapService(conn=conn, repos=repos, links=links)

result = roadmap.compute_next(scope_id=1)
match result:
    case Ok(data):
        if data is not None:
            print(f"Next: {data['module']['name']}")
            print(f"Phase: {data['phase']['title']}")
        else:
            print("Nothing actionable -- all caught up.")
    case Err(msg):
        print(f"Error: {msg}")

conn.close()
```

### Service Layer

All business logic lives in the service layer. Services accept repositories
via constructor injection and return `ServiceResult[T]` (which is
`Ok[T] | Err[str]`).

| Service | Purpose |
|---------|---------|
| `DashboardService` | Composite "where am I?" view |
| `RoadmapService` | Phase sequencing, "what's next?", completion |
| `PipelineService` | Spec state machine with quality gates |
| `GovernanceService` | ADR lifecycle, policy resolution |
| `SessionService` | Session lifecycle, resume context |
| `ResearchService` | Research brief management |
| `SearchService` | Full-text search (FTS5) |
| `TaskQueueService` | Deferred background task processing |
| `InsightsService` | Project metrics (time-in-status, throughput) |
| `EnforcementService` | Policy enforcement orchestration (pluggy dispatch) |
| `EmbeddingService` | Staleness detection for vector embeddings |

### Result Type

All service methods return `ServiceResult[T]`, a Rust-inspired Result type:

```python
from roundhouse.core.results import Ok, Err, ServiceResult

# Construction
success: ServiceResult[dict] = Ok({"id": 1, "title": "Done"})
failure: ServiceResult[dict] = Err("Feature not found")

# Pattern matching
match result:
    case Ok(value):
        process(value)
    case Err(message):
        handle_error(message)

# Chaining
result = (
    service.get_feature(1)
    .and_then(lambda f: service.create_spec(f["id"], "T2"))
    .map(lambda s: s["id"])
)

# Safe access
value = result.unwrap()          # Raises if Err
value = result.unwrap_or(None)   # Returns default if Err
```

---

## AI Integration

Roundhouse has **zero AI SDK dependencies**. AI features use CLI subprocess
calls to whatever tool the user already has installed.

### Three Modes

| Mode | How | When |
|------|-----|------|
| **Plugin** | AI tool imports roundhouse as library | Primary use. Claude Code or Gemini CLI provides the intelligence. |
| **CLI subprocess** | TUI shells out to `claude`/`gemini` | Secondary. For AI features in standalone TUI. |
| **Manual** | No AI, user writes all content | Always works. CRUD, status, navigation, pipeline -- all functional. |

### Configuration

Set the AI tool in `.roundhouse/config.toml`:

```toml
[ai]
tool = "claude"   # or "gemini" or "none"
```

### LLM Protocol

For plugin developers, Roundhouse defines an `LLMProtocol` that any AI adapter
can satisfy:

```python
from roundhouse.ai.protocols import LLMProtocol
from roundhouse.ai.cli_adapter import CLIAdapter
from roundhouse.ai.null_adapter import NullAdapter

# CLI adapter (shells out to claude/gemini)
adapter = CLIAdapter(tool="claude")

# Null adapter (manual mode)
adapter = NullAdapter()

# Custom adapter (for plugins)
class MyAdapter:
    def generate(self, prompt, context=None):
        return Ok("generated content")
    def embed(self, text):
        return Ok([0.1, 0.2, ...])
```

### What Needs AI vs. What Doesn't

| Category | Features | AI Needed? |
|----------|----------|------------|
| Pure logic | CRUD, status, navigation, progress, search, pipeline state machine | No |
| Enhanced | ADR drafting, spec generation, research synthesis, quality judgment | Optional |
| Dependent | Codebase-aware specs, code review against spec, multi-agent orchestration | Plugin only |

---

## Architecture

### Layer Diagram

```
Consumers:      TUI  |  CLI  |  Plugin (Phase 2)
                 |       |          |
                 v       v          v
API Surface:  +--------------------------------------------+
              |           Service Layer                    |
              | dashboard / roadmap / pipeline / governance |
              +--------------------------------------------+
                        |                    ^
                        v                    |
Data Layer:    Repositories + SQLite    AI Protocol
                                     (CLI subprocess)
```

### Design Patterns

| Pattern | Application |
|---------|-------------|
| Protocol-based design (PEP 544) | All inter-layer contracts |
| Dependency injection | Constructor injection, Protocol types |
| ServiceResult[T] | Business errors as values, never exceptions |
| Repository pattern | One per entity, thin SQL + Pydantic |
| Event bus (sync + deferred) | Critical path (inline) + side effects (queued) |
| Table-per-entity-type | Typed SQLite tables with CHECK constraints |

### Database

SQLite with WAL mode. 18 tables (19 with optional sqlite-vec):
- 10 entity tables (features, specs, tasks, modules, phases, milestones, adrs, policies, research, sessions)
- 1 infrastructure (scopes)
- 3 relationship tables (entity_links, entity_scopes, entity_tags)
- 1 audit (entity_history)
- 2 background (embedding_metadata, task_queue)
- 1 search (search_index -- FTS5 virtual table)
- 1 optional (entity_embeddings -- vec0, requires sqlite-vec extension)

The database lives at `.roundhouse/roundhouse.db` and should be committed to git
(it IS the project governance state).

### Event Engine

The EventBus supports two execution paths:

- **Critical (sync)**: Data integrity handlers (cascade deletes, audit logging,
  quality gate recomputation). Must finish before the service method returns.
- **Deferred (async)**: Enhancement handlers (FTS5 indexing, embedding generation,
  policy compliance checks). Enqueued to `task_queue` for background processing.

### Python 3.14 Features Used

| Feature | Use |
|---------|-----|
| Template strings (PEP 750) | SQL injection prevention via t-strings |
| Deferred annotations (PEP 649) | No forward-ref pain in Protocol-heavy code |
| StrEnum | Type-safe entity statuses throughout |
| match/case | Result matching, command dispatch, event handling |
| TypeIs | Type narrowing for ServiceResult.is_ok() |
| graphlib.TopologicalSorter | Phase dependency resolution |

---

## Policy Enforcement

Roundhouse enforces architectural decisions via a database-driven policy
engine. Policies are stored in SQLite (not config files), resolved
per-scope, and dispatched via [pluggy](https://github.com/pytest-dev/pluggy).

### How It Works

```
ADR (why) -> Policy (what to enforce) -> Check class (how to check)
                    |
                    v
         roundhouse enforce file1.py file2.py
                    |
                    v
         GovernanceService.resolve_policies(scope)
                    |
                    v
         pluggy CheckEngine dispatches to registered checks
                    |
                    v
         Violations grouped: hook (block) | soft (warn) | agent (AI-only)
```

### Enforcement Tiers

| Tier | Behavior | Example |
|------|----------|---------|
| `hook` | Blocks commit (exit 1) | ASCII-only, no type:ignore |
| `soft` | Warns but allows (exit 0) | Missing docstrings, test naming |
| `ratchet` | Blocks if count increased | Complexity, legacy patterns |
| `agent` | AI-enforced only (CLAUDE.md) | Protocol design, Result pattern |
| `manual` | Human review | Architecture decisions |

### Default Policies (seeded on `roundhouse init`)

8 ADRs and 20 derived policies are seeded automatically:

- **Constitutional** (hook, priority 10): ASCII-only, UTC timezone, file headers
- **Code quality** (hook, priority 50): McCabe <= 10, params <= 5, no magic numbers, absolute imports, no mocks, no type:ignore
- **Soft checks** (soft, priority 100): Google docstrings, test naming
- **Agent-only** (agent): Protocol design, Ok/Err pattern, constructor injection

### Adding a New Enforced Rule

```bash
# 1. Create the ADR
roundhouse adr add "No Print Statements" \
  --context "Print pollutes stdout" \
  --decision "Use logging module instead"

# 2. Create a policy linked to the ADR
#    (via roundhouse policy add or direct DB insert)

# 3. Create the check class
cat > src/roundhouse/core/checks/no_print_check.py << 'EOF'
from roundhouse.core.enforcement import CheckContext, Violation, hookimpl

class NoPrintCheck:
    RULE_ID = "no-print"

    @hookimpl
    def check_file(self, ctx: CheckContext) -> list[Violation]:
        try:
            return self._check(ctx)
        except Exception as exc:
            return [Violation(self.RULE_ID, ctx.filepath, 0, str(exc), "warning")]

    def _check(self, ctx):
        violations = []
        for lineno, line in enumerate(ctx.content.splitlines(), 1):
            if "print(" in line and not line.strip().startswith("#"):
                violations.append(Violation(
                    self.RULE_ID, ctx.filepath, lineno,
                    "Use logging instead of print()", "error",
                ))
        return violations
EOF

# 4. Register in core/checks/__init__.py BUILTIN_CHECKS dict

# 5. Done. roundhouse enforce picks it up from the DB.
```

### Pre-commit Integration

A single hook runs all policy checks:

```yaml
# .pre-commit-config.yaml
- repo: local
  hooks:
    - id: roundhouse-enforce
      name: Roundhouse policy enforcement
      language: script
      entry: .hooks/enforce.sh
      types: [python]
```

The `.hooks/enforce.sh` shim resolves the `.venv/` Python 3.14
to avoid system Python (3.12) incompatibility with GUI git clients.

### Export Rules for AI Agents

```bash
roundhouse enforce --export claude-md
```

Generates markdown from the live DB for embedding in `.claude/rules/`:

```markdown
## Policy Rules (auto-generated from Roundhouse DB)

### HOOK (blocks commit)
- **ascii-only** (P10, constitutional): No unicode/emoji -- ASCII only
- **no-type-ignore** (P50): No type: ignore except import-not-found
...
```

---

## Configuration

### Project Config

`.roundhouse/config.toml`:

```toml
[project]
name = "My Project"
default_scope = "default"

[ai]
tool = "none"    # "claude", "gemini", or "none"

[tui]
theme = "default"
```

### Project Root Discovery

Roundhouse automatically finds the project root by climbing the directory tree
looking for `.roundhouse/config.toml` (like git finds `.git/`). You can run
`roundhouse` from any subdirectory.

Override order:
1. `--db` CLI flag
2. `ROUNDHOUSE_DB` environment variable
3. Auto-discovery via `find_project_root()`

### Database Location

`.roundhouse/roundhouse.db` -- add to git. Add to `.gitattributes`:

```
*.db binary
```

---

## Development

### Setup

```bash
git clone https://github.com/pierregrothe/roundhouse.git
cd roundhouse
poetry install
pre-commit install
pytest tests/
```

### Running

```bash
roundhouse status                                    # CLI dashboard
roundhouse next                                      # Next actionable module
roundhouse tui                                       # TUI
python -m roundhouse status                          # Alternative (debugger-friendly)
textual run --dev roundhouse.tui.app:RoundhouseApp   # TUI with live CSS reload
```

### Testing

```bash
pytest tests/              # All tests (573 tests, ~40s)
pytest tests/unit/         # Unit tests only (fast)
pytest tests/integration/  # Integration tests (CLI + TUI)
pytest -m slow             # Wheel install test (~30s)
```

### Code Quality

```bash
ruff check src/ tests/     # Lint
black src/ tests/          # Format
mypy src/                  # Type check
```

### Project Structure

```
src/roundhouse/
  core/             # Foundation: DB, models, results, events, constants
  repositories/     # SQL + Pydantic, one per entity type
  services/         # Business logic and computed views
  ai/               # Optional AI integration (CLI subprocess)
  cli/              # Click CLI commands
  tui/              # Textual TUI screens and widgets
```

### Test Structure

```
tests/
  unit/
    core/           # Models, results, events, decorators
    repositories/   # SQL operations (in-memory SQLite)
    services/       # Business logic (real DB, no mocks)
    ai/             # Adapter tests (subprocess mocked)
  integration/
    cli/            # Click CliRunner tests
    tui/            # Textual pilot tests (async)
    db/             # Schema migration tests
```

### Contributing

1. Fork the repository
2. Create a feature branch (`git checkout -b feature/my-feature`)
3. Write tests first (TDD)
4. Implement the feature
5. Run the full test suite (`pytest`)
6. Submit a pull request

---

## License

MIT License. Copyright (c) 2026 Pierre Grothe.

