Skip to content

Contributing

Setup

git clone https://github.com/gregology/developer.git
cd developer
uv sync

Install pre-commit hooks:

uv run pre-commit install

This runs ruff, mypy, and trailing whitespace checks on every commit.

Code quality

All checks need to pass. CI runs them on every push.

uv run ruff check src/ tests/                        # lint
uv run ruff format src/ tests/                       # format
uv run mypy                                           # type check (strict mode)
uv run pytest                                         # test + coverage (minimum enforced by pytest-cov)
uv run bandit -r src/ -q -c pyproject.toml            # security
uv run vulture src/ --min-confidence 80               # dead code
uv run complexipy src/ --max-complexity-allowed 15    # cognitive complexity
uv run radon cc src/ -a -nc                           # cyclomatic complexity

Conventions

  • Python 3.11+, type annotations on all function signatures
  • mypy strict mode. Use dict[str, Any] not bare dict.
  • Click for the CLI. Each command module exports a Click command or group.
  • Config goes in developer.yaml (copy from example.developer.yaml). The RepoConfig dataclass is the in-code representation.
  • Architectural decisions go in DECISIONS.md with context, rationale, and revisit triggers.

Adding a new repo

Add a block to your developer.yaml (copied from example.developer.yaml). See Configuration.

Adding a new audit type

  1. Create src/developer/templates/audit/<name>.md.j2 -- include _labels.md.j2 and _personality.md.j2, use {{ max_findings }} for the limit
  2. Add a Click subcommand in src/developer/commands/audit.py that calls run_audit() with the template name

Adding a new resolve stage

  1. Create src/developer/templates/resolve/<name>.md.j2
  2. Add a Stage entry to STAGES in src/developer/commands/resolve.py
  3. Wire routing by updating an existing stage's route function to point to the new stage

Adding a new pipeline

Bigger lift, but the pattern is well-established:

  1. Create a command file in src/developer/commands/
  2. Define a STAGES dict with your stages
  3. Write route functions for branching logic
  4. Write pre/post hooks for any Python operations (git, GitHub API)
  5. Create Pydantic models in src/developer/models/ for structured outputs
  6. Create Jinja2 templates in src/developer/templates/<pipeline>/
  7. Register the Click command in cli.py
  8. Add a POST endpoint in src/developer/api/routes.py with a _run_* service function and a request model in api/models.py

API conventions

The API lives in src/developer/api/. It mirrors the CLI — same pipelines, same building blocks — but returns structured JSON instead of terminal output.

  • Routes go in api/routes.py. Each pipeline endpoint has a corresponding _run_* service function that replicates the Click command body.
  • Request/response models go in api/models.py.
  • Task execution uses api/tasks.py. Service functions run in daemon threads via submit_task() and log progress with task.log_message().
  • Don't modify existing Click commands to support the API. Write separate service functions that use the same underlying building blocks.