python-roborock
AGENTS.md245 starsChanged todayApache-2.0View on GitHub
This document serves as the authoritative, single source of truth for engineering conventions, architectural standards, and automated code reviews across all contributors and coding agents.
We split this AGENTS.md into the rules it gives an agent
12 rules. About 0 are common, 3 are distinctive, and 9 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
9
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 49
Keep protocol families (V1 JSON-RPC, B01 Tuya DPS, A01 Tuya DPS) strictly isolated.
- Very specific: line 58
Enum Fallback Resilience: All enums representing device status, firmware modes, error codes, and wire protocol integer codes MUST inherit …
- Very specific: line 60
Avoid Forward References &
TYPE_CHECKING: Avoid stringified forward references ("ClassName") and if typing.TYPE_CHECKING: guards wherever … - Very specific: line 61
Explicit Parameters: Do not mark arguments or dataclass fields as Optional[...] or default them to None if they are always required by the …
- Distinctive: line 66
Version Isolation: Keep V1, B01, and A01 parser pipelines strictly isolated.
- Very specific: line 75
Hierarchy Rooting: All custom exceptions MUST inherit from roborock.exceptions.RoborockException.
- Very specific: line 81
Test Mirroring & Colocation: Place and maintain unit tests in the matching mirror path under tests/ (e.g.
- Very specific: line 82
Avoid One-Off Test Files: Do not create fragmented, single-bug test files (such as tests/test_battery_low_voltage_fix.py).
- Distinctive: line 87
Scoping & Sizing: Keep pull requests focused on a single logical change or subsystem where possible (e.g.
- Very specific: line 89
Commitlint: Commit messages and PR titles MUST follow Conventional Commits (feat:, fix:, refactor:, chore:, docs:).
- Very specific: line 91
Pytest: All unit tests must pass (uv run pytest).
- Very specific: line 92
Logical Placement: Place domain constants and enums in the module where they are consumed or in roborock.data.code_mappings.
≈ “Common” is an estimate: at least 1 in 5 of the 36,368 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Repository Engineering Guidelines: python-roborock
Overview & Scope
python-roborock is an asynchronous (asyncio) device integration library supporting multi-protocol Roborock vacuum and home appliances (V1 JSON-RPC over AES, B01 Tuya DPS for Q7/Q10, and A01 Tuya DPS for Dyad/Zeo). While Home Assistant Core is a primary downstream consumer, python-roborock is an independent client library whose public abstractions must remain general-purpose and consumer-agnostic.
This document serves as the authoritative, single source of truth for engineering conventions, architectural standards, and automated code reviews across all contributors and coding agents.
Environment & Tooling Standards
- Target: Python 3.11+, Hatchling build backend,
uvpackage manager. - Linters & Formatters: Ruff (line length 120), Mypy (
check_untyped_defs = true), Codespell. - Testing: pytest (
pytest-asyncio).
Key Developer Commands
# Environment setup
uv venv && uv sync
# Run tests
uv run pytest
uv run pytest tests/devices/traits/v1/test_status.py
uv run pytest tests/protocols/test_v1_protocol.py
# Lint and typecheck
uv run pre-commit run --all-files
# or directly:
uv run ruff check roborock tests
uv run mypy roborock testsCore Architectural Hierarchy & Review Priorities
Evaluate every change against the repository's three core layers in strict priority order:
- Priority 1: Public Trait APIs & Consumer Contracts (Highest Priority)
- Clean, stable user-facing abstractions decoupled from wire protocol details, Tuya DPS keys, encryption keys, or transport sockets.
- Strongly typed with concrete models subclassing
RoborockBase; never expose raw protocol dictionaries orAnyon public boundaries.
- Priority 2: Data Lifecycle & State Management
- Simple, linear data flow. Keep side effects visible: helper functions MUST be pure transformations that compute and return values rather than mutating object state as a side effect.
- Exhaustive lifecycle teardown: all listeners, background tasks, and channels cleanly unhooked in
RoborockDevice.close(). - Concurrency: 1:1 request/response matching across async push channels uses
asyncio.Futurecorrelated by protocol request/sequence ID (request_idfor V1 RPC,msg_idfor B01/Tuya). - Transform data in render pipelines; never mutate cached telemetry state or raw packets for presentation effects.
- Priority 3: Wire Protocol Parsers, Codecs & Cryptography
- Encapsulate cryptography (AES, MD5), protocol framing, and raw sockets to
roborock.protocolsandroborock.devices.transport/roborock.devices.rpc. - Keep protocol families (V1 JSON-RPC, B01 Tuya DPS, A01 Tuya DPS) strictly isolated; never conflate schemas across families.
- Enforce enum fallback resilience (
RoborockEnumwith lowercaseunknown = -1orRoborockModeEnum.from_code_optional()); never crash on unexpected firmware codes.
- Encapsulate cryptography (AES, MD5), protocol framing, and raw sockets to
Detailed Engineering Conventions
1. Typing & Data Models
- Subclass
RoborockBase: Define structured domain and wire data models as@dataclasssubclassingRoborockBase(from_dict,as_dict). AvoidTypedDictor loose dicts. (Binary protocol packets, transport message envelopes, and map layers are exempt). The existing frozenQ10RoborockPointcoordinate value is also exempt: it must retain immutability and hashability, and Python disallows frozen dataclass inheritance from the non-frozenRoborockBase. This exception does not extend to other domain models. - Enum Fallback Resilience: All enums representing device status, firmware modes, error codes, and wire protocol integer codes MUST inherit from
RoborockEnum(defining a lowercaseunknown = -1or0member) orRoborockModeEnum(usingfrom_code_optional()). Internal enums not decoding unknown firmware codes remain standardEnum/StrEnum. - Strongly Type What You Know; Contain
Anyto the Wire: Public trait APIs, method signatures, properties, and domain models MUST declare concrete types.Anyis accepted only where the underlying wire protocol is dynamic or polymorphic (Tuya DPS maps, low-level RPC dispatch, serialization helpers, evolving cloud schemas). - Avoid Forward References &
TYPE_CHECKING: Avoid stringified forward references ("ClassName") andif typing.TYPE_CHECKING:guards wherever possible. They typically indicate circular dependencies or coupling that should be refactored by extracting shared models. - Explicit Parameters: Do not mark arguments or dataclass fields as
Optional[...]or default them toNoneif they are always required by the protocol or caller. - Trust Type Annotations: Prohibit defensive runtime
isinstancechecks on statically typed parameters in business and trait logic. (Dynamic wire payload unpacking and type narrowing infrom_dictor RPC deserializers is legitimate and expected).
2. Protocol & Device Communications
- Channel Trait Boundary: Traits receive only an abstract communication channel (e.g.,
Channel,RpcChannel). Never pass device local keys, security tokens, IP addresses, or transport sockets intoTraitinstances. - Version Isolation: Keep V1, B01, and A01 parser pipelines strictly isolated. Do not bleed Tuya DPS decoding logic into V1 or vice versa.
3. Trait Design & Client Integration
- Compound Capability & Feature Gating: Capability and trait availability MUST be gated by protocol version (
device.pv == "1.0"orDeviceVersion.V1), appropriate category (RoborockCategory.VACUUM,WET_DRY_VAC, orWASHING_MACHINE), and device feature flags (device.features). - Linear State Flow: Methods that parse responses or transform telemetry must return values to make state assignments explicit at the call site. Avoid multi-layered helper cascades.
- Consumer Agnosticism: Design traits around cohesive, general-purpose consumer concepts (
CleanHistoryTrait,DockTrait,ConsumableTrait), not low-level firmware registers or raw Tuya DPS numbers. - Diagnostic Safety & Privacy: Exclude sensitive user information (Wi-Fi SSIDs, passwords, cloud tokens, encryption keys) from device diagnostics and logs.
4. Error Handling & Exceptions
- Hierarchy Rooting: All custom exceptions MUST inherit from
roborock.exceptions.RoborockException. - Specific Exception Narrowing: Catch only specific, expected exception classes (
RoborockTimeout,RoborockConnectionException,json.JSONDecodeError). Catching broadExceptionis permitted only in teardown/cleanup handlers (e.g.device.py) to guarantee resources are unsubscribed before re-raising or logging. - Context-Rich Parsing Exceptions: Wrap deserialization, decoding, and schema mapping errors into
RoborockParsingExceptionwith rich context (trait_name,command,payload,inner_error). - Guard Clauses: Flatten nested conditional branches with early exit guard clauses (
if not condition: return).
5. Test Patterns & Fixtures
- Test Mirroring & Colocation: Place and maintain unit tests in the matching mirror path under
tests/(e.g.tests/devices/traits/v1/test_status.pyforroborock/devices/traits/v1/status.py;tests/map/test_b01_q10_map_parser.pyforroborock/map/b01_q10_map_parser.py). - Avoid One-Off Test Files: Do not create fragmented, single-bug test files (such as
tests/test_battery_low_voltage_fix.py). Integrate test cases into the module's corresponding test suite. - Fixture Reuse & Parametrization: Reuse shared fixtures (
fake_channel,message_builder,device_fixture) intests/and use table-driven@pytest.mark.parametrize. - Behavior-Driven Assertions: Assert on public trait methods, return values, and emitted channel commands—never on private object attributes (
_state).
6. PR Hygiene & Sizing
- Scoping & Sizing: Keep pull requests focused on a single logical change or subsystem where possible (e.g. parser module with tests in one PR, traits consuming it in a follow-up PR). Large PRs (>500–1,000 LOC) take longer to review and block releases.
- CI Requirements: PRs must pass automated CI (
.github/workflows/ci.yml):- Commitlint: Commit messages and PR titles MUST follow Conventional Commits (
feat:,fix:,refactor:,chore:,docs:). - Pre-commit: Ruff, Mypy (
check_untyped_defs = true), and Codespell must pass (uv run pre-commit run --all-files). - Pytest: All unit tests must pass (
uv run pytest).
- Commitlint: Commit messages and PR titles MUST follow Conventional Commits (
- Logical Placement: Place domain constants and enums in the module where they are consumed or in
roborock.data.code_mappings. Do not duplicate definitions across files.
Available Agent Skills
Portable agent skills following the Agent Skills specification are located under .agents/skills/:
- Code Review Skill (
.agents/skills/code-review/SKILL.md): A structured, interactive review workflow for evaluating pull requests and diffs against the repository's architectural hierarchy, typing rules, and testing standards. To invoke during interactive sessions, refer to .agents/skills/code-review/SKILL.md. - PR Triage Skill (
.agents/skills/pr-triage/SKILL.md): A repeatable workflow for syncing the workspace and classifying open pull requests into actionable review queues (initial reviews, re-reviews after author updates, ready-to-merge PRs, and waiting/draft items). Refer to .agents/skills/pr-triage/SKILL.md.
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 28,693 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository2 other files it gives its agents.
- code-reviewSkill
- pr-triageSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

