Contributing to ChainWeaver
July 22, 2026 · View on GitHub
Thank you for your interest in contributing to ChainWeaver! This guide covers everything you need to get started, whether you are a human contributor or an AI agent.
For AI contributors: also read AGENTS.md (the stable global contract) and docs/agent-context/, which contain agent-specific conventions. Durable subsystem rules live in path-scoped AGENTS.md files indexed in AGENTS.md § 11 — read every one covering the paths you touch. .github/copilot-instructions.md is a thin wrapper that points to the same sources.
Table of Contents
- Dev environment setup
- Your first contribution
- Pre-commit hooks
- Running tests
- Code style
- PR process
- Reporting issues
Dev environment setup
# Clone the repository
git clone https://github.com/dgenio/ChainWeaver.git
cd ChainWeaver
# Create a virtual environment
python -m venv .venv
# Windows
.venv\Scripts\activate
# Linux/macOS
# source .venv/bin/activate
# Install with dev dependencies (editable mode)
pip install -e ".[dev]"
Python 3.10 or later is required.
Your first contribution
New here? Start with a curated, well-scoped task rather than a sprawling one.
Look for these labels on open issues:
| Label | Who it's for | What it means |
|---|---|---|
good-first-issue | First-time human contributors | Scoped, low-context, with clear acceptance criteria. |
good-first-ai-issue | AI agents (Copilot, Claude Code, …) | Same bar, plus enough file/path detail in the body for an agent to act without repo-wide spelunking. |
A task qualifies for either label when it is scoped (one logical change), low-context (no deep architectural background required), and ships with clear acceptance criteria. Docs fixes, an example or test for an existing behavior, and small CLI/output polish are typical starting points.
Your first change, step by step:
- Read
AGENTS.md, the path-scopedAGENTS.mdfor the area you're touching (index inAGENTS.md§ 11), and the per-file-type guidance in.github/instructions/. - Make the smallest correct change for the issue — resist bundling adjacent
fixes (open a follow-up issue instead; see
workflows.md§ Out-of-scope discoveries). - Run the four validation commands (see Running tests) until they pass locally.
- Open a PR following the PR process; fill in every template section.
Maintainers curate the labelled pool — if you spot a task that looks first-issue sized, mention it on the issue rather than self-assigning a label.
Pre-commit hooks
ChainWeaver ships a .pre-commit-config.yaml that
mirrors three of the four validation commands documented in
AGENTS.md §7 — ruff check,
ruff format --check, and mypy — plus a few hygiene hooks, secret
scanning, and GitHub Actions linting. pytest is not a hook: it is
excluded to keep commit speed reasonable, so run it manually before pushing
or rely on CI. Set the hooks up once per clone:
# One-time install (after `pip install -e ".[dev]"`)
pip install pre-commit
pre-commit install
After installation, the hooks run automatically on every git commit. You
can also run them against the whole tree (recommended after a rebase):
pre-commit run --all-files
The three Python hooks use language: system and invoke the canonical
commands verbatim — same scope (chainweaver/ tests/ examples/), same flags
— so a clean local run matches a clean CI run. If a hook fails, fix the
underlying issue and re-stage; do not bypass it with --no-verify.
Hook versions are pinned in .pre-commit-config.yaml. Bumping a hook is a
deliberate change: update the pin in the same PR that benefits from it.
Secret scanning
detect-secrets runs as part of
the hooks and is gated by a committed baseline at
.secrets.baseline. If you legitimately add a
secret-shaped string (e.g. a new test fixture), update the baseline:
detect-secrets scan --baseline .secrets.baseline
detect-secrets audit .secrets.baseline
Do not suppress the hook with --no-verify. Fix the underlying issue
or update the baseline with an audit trail.
Running tests
Run the full test suite:
python -m pytest tests/ -v
Run all four validation commands before every commit:
ruff check chainweaver/ tests/ examples/
ruff format --check chainweaver/ tests/ examples/
python -m mypy chainweaver/ tests/
python -m pytest tests/ -v
CI runs lint + format + mypy on Python 3.10, and tests across Python 3.10–3.14.
Code style
- Type annotations are required on all function signatures.
- Pydantic
BaseModelfor all data schemas (tool I/O,Flow,FlowStep). from __future__ import annotationsat the top of every module.- Lean runtime core (
deepdiff,packaging,pydantic,tenacity,typer). Add new runtime dependencies judiciously — only when they deliver clear value and are well-maintained. Always updatepyproject.toml[project.dependencies]. - All public symbols must be exported in
chainweaver/__init__.py__all__. - All exceptions must inherit from
ChainWeaverError. - Ruff is the linter and formatter — run
ruff checkandruff format --checkbefore committing.
Dependency-constraint policy
ChainWeaver is a library, so its install requirements constrain dependencies as loosely as correctness allows (exact pins and speculative caps belong in applications and lockfiles, not here):
- Lower bounds only (
>=) on every runtime dependency and extra, set to the lowest version the test suite actually passes on — never an exact pin (==). - No speculative upper-bound caps (
<X). Any retained cap must carry an inline comment citing the specific incompatibility that justifies it. - The floors are proven, not guessed: the
floor-depsCI job installs the minimums viauv pip install --resolution lowest-directand runs the full suite on Python 3.10, and a weeklylatest-depsjob runs against the newest (incl. pre-release) versions on Python 3.14 so a breaking upstream release is caught early. Note that--resolution lowest-directpins each directly declared dependency to its floor; where a heavier extra's transitive requirement lifts one above its declared floor (currentlypydantic, which the framework extras in[dev]pull to>=2.12), that floor is verified in a standalone run rather than by the combined.[dev]floor job. If you raise a dependency floor, run the floor job locally first:uv pip install --resolution lowest-direct -e ".[dev]" && pytest tests/ --no-cov.
Vocabulary
Use the canonical terms consistently in code, docs, and PR descriptions:
| Use | Never use |
|---|---|
| flow | chain, pipeline |
| tool | function, action (when referring to a Tool instance) |
Automated check. scripts/check_vocabulary.py
flags pipeline/pipelines used as a flow-synonym in Markdown prose and
Python docstrings/comments, and runs as a pre-commit hook and in CI. Genuine
non-flow uses of the word (e.g. "JSON pipeline", "review pipeline") are
exempted in .vocabulary-allowlist.txt; add an
entry there with care rather than reaching for an LLM-friendly synonym.
Why not auto-check "chain"? It is a legitimate domain noun here —
ChainAnalyzer.find_chains() returns chains (candidate tool sequences), and
the builder offers fluent method chaining. Auto-banning it would force a
sprawling allowlist that masks real misuse, so using "chain" as a synonym
for a flow remains a human-review item: reviewers should still catch it.
PR process
- One primary issue per PR. A PR that implements one issue's feature, adds its tests, and updates its docs is one logical change. Prefer one issue per PR — smaller PRs review faster, conflict less, and keep
maingreen. If a PR must touch several issues because the work is genuinely coupled, say why in the PR description. - Declare the issues this PR closes in the PR template's Issues closed by this PR field (e.g.
Closes #123), and link related-but-not-closed issues under Related Issues. The closing field is the source of truth when the branch name cannot carry the issue number. - All tests must pass before requesting review.
- Branch naming. Manually created branches use
{type}/{issue_number}-{short-description}(types:feat,fix,docs,test,refactor; e.g.feat/55-add-pr-template). Tool-generated branches (e.g. theclaude/<task>branches the AI-agent workflow produces) are accepted as-is — they often can't embed an issue number — provided the PR declares its closing issue(s) per step 2. Seeworkflows.md§ Branch naming for the canonical rule. - Commit messages follow Conventional Commits:
feat: add timeout guardrails to tool execution fix: correct input mapping for literal constants docs: update architecture map after log_utils rename - Fill in all sections of the PR template (Summary, Changes, Testing, Related Issues, Checklist).
- Do not include secrets, API keys, credentials, or PII in code, logs, or tests.
Reporting issues
Use the GitHub issue forms:
- Bug report — unexpected behavior, errors, or incorrect output.
- Feature request — new capabilities or enhancements.
Provide as much context as possible: Python version, ChainWeaver version, a minimal reproduction, and the full traceback where relevant.
For the full set of agent-oriented conventions, invariants, and architecture decisions, see AGENTS.md and docs/agent-context/.