Mirrored from CONTRIBUTING.md. Edit there.
Contributing to coracle
Welcome! This project is agent-friendly — issues are written so that humans and coding agents (Claude Code, opencode, codex, Cursor, etc.) can pick them up cold and submit a working pull request.
TL;DR for coding agents
- Pick an open issue labeled
status:ready(no unresolved dependencies). - Read the issue body — every issue includes Context, Files to touch, Acceptance Criteria, and Definition of Done.
- Read
docs/PLAN.mdfor the architecture. - Clone, branch, code, test, PR.
- Use the branch name pattern:
<issue-number>-<short-slug>(e.g.12-ram-monitor). - PR title pattern:
[#<issue>] <type>: <short summary>(e.g.[#12] feat: psutil RAM watchdog). - PR body must include
Closes #<issue-number>so the issue auto-closes on merge. - Keep PRs small and focused on one issue.
Workflow
# 1. Pick an issue (assume #12)
gh issue view 12
# 2. Branch
git checkout -b 12-ram-monitor
# 3. Code + tests
# ... make your changes ...
# 4. Run checks (once tooling lands in Phase 1)
ruff check .
ruff format --check .
pytest
# 5. Commit, push, PR
git add -A
git commit -m "[#12] feat: psutil RAM watchdog with soft/hard caps"
git push -u origin 12-ram-monitor
gh pr create --fill --body "Closes #12"
Issue labels — quick reference
Phase (which milestone this belongs to):
phase:1-foundations · phase:2-providers · phase:3-pipeline · phase:4-tools · phase:5-interfaces · phase:6-status · phase:7-hardening
Type (what kind of work):
type:feat · type:test · type:docs · type:chore · type:research · type:bug
Area (which subsystem):
area:core · area:models · area:tools · area:interfaces · area:prompts · area:config
Priority:
priority:p0-blocker · priority:p1-high · priority:p2-normal · priority:p3-low
Status:
status:ready (no blockers, pick me up!) · status:blocked (waiting on a dependency) · status:in-progress
Special:
good-first-issue · help-wanted · agent-friendly · epic
Code style
- Python 3.11+.
- Format with
ruff format(PEP 8, line length 100). - Lint with
ruff check. - Type hints on all public functions; check with
mypyin strict mode for new modules where possible. - Docstrings: short, useful — no boilerplate. Document non-obvious behavior, not signatures.
- Tests use
pytest. Aim for behavior-level tests, not implementation-bound.
Project structure
See docs/PLAN.md. In short:
coracle/
├── core/ # scheduler, state, pipeline, ram_monitor, classifier
├── models/ # ollama_local, big_ai/, narrator
├── tools/ # fs, shell, web, browser, git, registry
├── interfaces/ # openai_compat, mcp_server, http_api, cli
├── prompts/ # versioned prompt templates
└── tests/
Testing rules
- Unit tests for pure logic — no model calls, no network.
- Integration tests that need Ollama: mark with
@pytest.mark.ollamaand skip by default in CI. - Integration tests that need API keys: mark with
@pytest.mark.liveand skip by default. - Mock all big-AI providers via
litellmmock backends in unit tests. - Coverage gate:
pytest --cov=coracle --cov-fail-under=95is enforced in CI. PRs that drop coverage below 95% will fail. Use# pragma: no coveronly for genuinely-untestable branches (e.g. real subprocess fork paths).
Signed commits (mandatory)
The main branch enforces required_signatures via a repository ruleset. Every commit must be GPG- or SSH-signed, otherwise push and merge are blocked.
One-time setup:
# Option A: GPG
gpg --full-generate-key # ed25519 or rsa4096
gpg --list-secret-keys --keyid-format=long # copy KEYID
git config --global user.signingkey <KEYID>
git config --global commit.gpgsign true
git config --global tag.gpgsign true
gpg --armor --export <KEYID> # paste at https://github.com/settings/gpg/new
# Option B: SSH (simpler, uses existing ~/.ssh/id_ed25519)
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git config --global commit.gpgsign true
# upload the .pub at https://github.com/settings/ssh/new (key type = "Signing Key")
Verify:
git log --show-signature -1
gh api /repos/skgandikota/coracle/commits/<sha> --jq '.commit.verification'
# expect: verified=true, reason=valid
Bots (GitHub Apps) sign automatically with GitHub's web-flow signature when committing via the API. No setup needed for the strict reviewer's squash-merge.
Definition of Done (applies to every issue)
A PR is mergeable when:
- Code implements the Acceptance Criteria in the issue.
- Tests for the new behavior exist and pass locally (
pytest). ruff checkandruff format --checkpass.- Coverage stays at or above 95% (
--cov-fail-under=95in CI). - Every commit on the branch is signed (
verified=trueon GitHub). - Public APIs have type hints.
- Docs/
docs/PLAN.mdupdated only if the change deviates from the plan — otherwise leave the plan alone. - PR body says
Closes #<issue-number>.
Architectural rules of the road
These are non-negotiable for any change:
- Never load two 7B models simultaneously. Always go through
core.scheduler. - Every coder step is a checkpoint — write progress to SQLite before yielding the slot.
- Status queries must not require an LLM by default — read from SQLite first.
- All long-running work is a job with an ID. APIs return
job_idimmediately; clients stream/poll. - Provider fallback is automatic — no caller should hardcode a provider.
- Browser drivers are separate subprocesses — never in-process with the main app.
- One external model name:
coracle. The classifier picks the pipeline, not the user.
If your change conflicts with one of these, open a discussion issue before coding.
Questions?
Open a Question issue or comment on the issue you're working on. We'll respond.