Contributing to looplet¶
Thanks for your interest in improving looplet! This document lays
out how to set up a dev environment, the conventions we follow, and how
to submit changes.
Development setup¶
looplet uses uv for dependency
management. If you don't have it yet:
Then from the repo root:
make install # uv sync --all-extras (matches CI)
make check # everything CI runs: lint + format + pyright + pytest
make test # just the tests (~2s, 1055 tests)
make install-hooks # one-time: install a pre-push git hook that runs `make check`
The rule is simple: if make check passes locally, CI passes.
Run it before every push, or let the pre-push hook do it for you.
Branching & commits¶
- Create a feature branch off
main. - Write small, focused commits. We aim for commits that tell a story; squash-merges are fine on the PR side.
- Include a test for any behavior change; bug fixes should come with a regression test.
Coding conventions¶
- Python: target 3.11+; use modern syntax (
X | Y,match,dataclasses,typing.Protocol). - Domain-agnostic core: the harness must not assume what the agent does. Domain-specific helpers belong in the user's code, not here.
- Fail closed: permissions, cancellation, and parse recovery must default to the safe path. If in doubt, deny / cancel / re-prompt.
- Sync ↔ async parity: any behavior added to
composable_loopmust have the equivalent inasync_composable_loop, and vice-versa. Add tests for both paths. - Avoid bare
except: catch the narrowest exception you can. - No new runtime dependencies without discussion — the core runtime
depends only on the standard library. Optional extras are
fine under
[project.optional-dependencies]. - Public API surface — if you add a public symbol, export it from
looplet/__init__.py, document it with a docstring, and add a test.
Testing¶
- Unit tests live under
tests/, mirroring the module layout ofsrc/looplet/. - Mark fast tests with
@pytest.mark.smoke(module-levelpytestmarkis fine) and slow / network-bound tests with@pytest.mark.integrationor@pytest.mark.slow. - Tests should not require network access by default. Mock the LLM
backend via the
LLMBackendprotocol. - Keep individual tests under 1 second where possible. If a test
takes longer, mark it
slow.
Pull request checklist¶
Before opening a PR, please verify:
-
make checkpasses (lint + format + pyright + 1055 tests). - New public API has docstrings and tests.
-
CHANGELOG.mdhas an entry under## Unreleaseddescribing your change (unless it's a docs-only or internal refactor with no user-visible effect). - Sync and async loops stay in parity (if applicable).
Reporting bugs¶
Open an issue on GitHub with:
- What you expected to happen.
- What actually happened (stack trace, log output).
- A minimal reproduction — ideally a single
pytesttest case. - Your Python version and
loopletversion.
Security issues¶
Please do not open a public issue for vulnerabilities; see SECURITY.md for the private disclosure channel.
License¶
By contributing, you agree that your contributions will be licensed under the Apache License 2.0, the same as the project.