Contributing¶
Development setup¶
Running tests¶
The test suite uses:
pytest— unit and integration testshypothesis— property-based testspytest-bdd— Gherkin feature specs
All 159 tests run in under 2 seconds without any external services.
Test patterns¶
Unit test with MemoryLedgerStore¶
def test_my_responder():
store = MemoryLedgerStore("test-run")
world = Runtime(ledger=store, responders=[my_responder]).run([seed_event])
assert "expected-obj" in world.objects
BDD feature test¶
Feature files live in features/. Steps are in features/steps/.
# features/mykit.feature
Feature: My Kit
Scenario: Goal creates questions
Given a fresh run with the research kit
When I run the goal "Understand AI"
Then the world has at least 3 Question objects
Property-based test¶
from hypothesis import given, strategies as st
from kando.cache.llm import LLMCache
@given(st.dictionaries(st.text(), st.text()))
def test_cache_roundtrip(request):
cache = LLMCache()
cache.put(request, "response")
assert cache.get(request) == "response"
Adding a kit¶
- Create
kits/<name>/__init__.pyandkits/<name>/kit.py - Export
create_kit() -> list[Responder] - Optionally export
seed_from_goal(goal, run_id) -> list[KandoEvent] - Add tests in
tests/test_<name>_kit.py - Add documentation in
docs/kits/<name>.md - Add to
docs/kits/index.mdtable - Add to
mkdocs.ymlnav
See Writing a Kit for the full pattern.
Building the docs¶
Code style¶
- No type: ignore comments
- No bare
exceptclauses - Default to no comments — only add when the WHY is non-obvious
- No backwards-compatibility hacks for unused code — delete it
Commit messages¶
Follow the existing style:
Short summary (imperative, ≤72 chars)
Longer explanation of what changed and why (not what — the diff shows that).
Reference the design principle if relevant.
Co-Authored-By: ...
PR checklist¶
- [ ] Tests pass:
make test - [ ] New behaviour has tests
- [ ] Docs updated if public API changed
- [ ] No backwards-compatibility shims for removed code