RUL-020 — Async/sync contract — an async def must always be awaited

Ruling

"If a function is async def, every call to it must be awaited (or scheduled via asyncio.create_task/gather/ensure_future). Calling it bare discards the coroutine — the work never happens and no exception is raised." (docs/sync-vs-async.md TL;DR). This is the correctness rule the seed list's "async-by-default" label refers to; no separate verbatim ruling text for a stylistic "prefer async for new code" preference was found in the accessible memory export — stated plainly rather than assumed.

Evidence

Enforcement

Verification

scripts/check_async_await.py runs Pyright over src/ + tests/ and fails on reportUnusedCoroutine (a bare async_fn() whose result is discarded) plus operations on a bare CoroutineType, deliberately excluding the redis-py Awaitable[T] | T stub-noise false positives on sync clients.