Imported from M-o-a-T/moat (
AGENTS.md). Install upstream withnpx skills add M-o-a-T/moat. Copyright stays with the author.
Repository Guidelines for MoaT
This file isn't just for agents …
Issue tracking
-
Use 'beads' for tracking.
- 'bd list --label foo --ready --json': list issues
- 'bd show --json ID': examine single issue
- 'bd create --priority P --title TEXT --description TEXT --notes TEXT --type TYPE --labels foo,bar': create new issue
- 'bd dep add ID-task ID-blocker': add relationship
- 'bd update ID --parent ID --set-labels foo,bar --priority P --status S --title … --type …'
- 'bd close --reason STRING'
-
Conventions:
- labels: we use "common", "doc", or "moat.xx.yy" for specific subsystems
- status: open, in_progress, blocked, deferred, closed
- prio: 0…4, 0:highest
- type: bug|feature|task|epic|chore
The purpose of issues is to remember things to do. Thus, DO NOT create issues for one-off changes that you'd immediately close.
bd cannot run in a sandbox.
Project Structure & Modules
- This is a monorepository. All code lives in
moat/.- Code is CPython 13+ compatible
- exception: code in
moat/micro/_embedruns on a version of MicroPython 1.25+, enhanced with taskgroups - This also applies to all code which imports from
moat.lib.micro(but not to moat.lib.micro itself) - Python 3.11 compatible syntax must be used in those parts.
- moat.web uses Ludic, thus requires Python 3.14.
- exception: code in
- Each Python package named e.g.
moat.X.Ycontains- code in
moat/X/Y/**.py docs/moat-X-Yfor documentationpackaging/moat-X-Yforpyproject.tomland Debian packagingtests/moat_X_Yfor testingexamples/moat-X-Y
- code in
- Tests use
pytest. Required modules are listed in the globalpyproject.tomland are supposed to be installed on the host system. - We use semantic versioning for submodules, except for major version zero.
- Run
./mt src tag -s moat.X.Y -mto request a new minor version; use-Mfor new major versions. - Patch versions are allocated automatically when building.
- Run
- Shared code between CPython and MicroPython:
- Must use
moat.lib.compatto mask implementation differences. - Assume that any code that imports
moat.lib.compatmust work on both. - the MicroPython part of MoaT is in
moat/micro/_embed/lib. It may use relative symlinks to refer to code in the main area.
- Must use
- Code is CPython 13+ compatible
- Build output should be created in, or moved to, the
dist/folder. packaging/**/srcis auto-populated and excluded via.gitignore.
Python patterns
-
MoaT uses anyio for async code. Never import from asyncio.
-
NEVER busy-loop. NEVER delay to get something to work (except in testcases).
-
A BaseException (that's not an Exception) MUST be re-raised. This includes
anyio.get_cancelled_exc_class(). -
In
moat.libandmoat.micro, do not use syntax that doesn't work with MicroPython. Specifically:(foo,bar,*baz)list expansionwith (x,y)- def foo(bar,/) positional-only arguments
- Python 3.12+ syntax for generic types
isinstance(obj, type1 | type2)-- useisinstance(obj, (type1 type2))- multiple inheritance (syntax works but is ignored)
- micropython doesn't have anyio, but we do not directly import from asyncio either. Always use the compatibility code in moat.micro.compat.
-
Prefer to import from moat.lib.XX, moat.link.XX, or moat.YY modules, not from submodules. Exception:
TYPE_CHECKINGblocks.
Typing
- MoaT does its type checking with "ty".
- Use "ty check --output-format github" if you need to fix typing errors.
- Files need to be typed comprehensively, i.e. all variables, arguments and return types.
- DO NOT type:ignore comments, use the "Any" type, or add casts. UNLESS (a) you see an actual error from "ty", and (b) you THOUGHT HARD and determined that the error CANNOT be fixed some another way.
- Do not type-check data explicitly. That's what
tyis for. If that's not possible, duck typing (or the failure thereof) will raise aTypeError. - Do not range-check function parameters. It is sufficient to describe valid ranges in the docstring.
- DO NOT replace "def foo() -> Awaitable[Bar]: return asyncfn()" with an async
def. The correct type is
CoroutineType[Any,Any,Bar]. - After a module typechecks, add its files to the tool.ty.src.include list in pyproject.toml.
Build and Test
- pre-commit enforces testing, formatting and typechecking. DO NOT run formatters or type checkers on your own, except when you're fixing an error.
- YAML files may contain Path objects, marked with
!P. The pre-commit YAML checker understands this. - When testing, always write the test output to a temporary file so you can analyze it more easily. Running the same test multiple times is inefficient.
Coding Style
- Standard Python, 4-space indents, formatted by
ruff format. ruff checkclean. Seepyproject.tomlfor global exceptions.- ignore pylint, pyright or isort comments. Remove them if you're changing the line anyway.
- Keep functions reasonably small.
- Do not repeat yourself. Use subclassing.
- Follow existing practice when naming. Be concise.
- New modules must pass
ty check. - Functions and variables shall be typed concisely.
Documentation
- Every module, class, public variable and function must be documented.
- Docstrings are written in RestructuredText, with Google-style markup for arguments, return values etc..
- Types are specified in the function declaration, not in the docstring.
- Legacy code might use something different. Don't copy legacy styles! Always use / convert to Google style and proper object references for new or updated code, or when instructed to fix documentation.
- All other documentation is written using Markdown (Myst). Only use RestructuredText syntax or blocks when Myst doesn't support a feature.
- Don't duplicate basic information: each package's
README.mdcontains markers for a synopsis (included indocs/index.md) and a main part (included indocs/moat-XXX-YYY/index.md). The synopsis does not contain headers. The main part is assumed to be under a level 1 header. It must not itself contain a Level 1 header itself. - Do not create enumerations like "Key features" or similar.
- Do not mention implementation details in docstrings.
- Use references, not literals.
Testing Guidelines
- Tests should focus on exercising a module's API and its actual purpose.
- 100% coverage is a goal to aspire to, but not the main focus of our tests.
- Don't repeat tests or assertions.
- DO NOT use "head", "tail", or "rg" / "grep" on test output. Instead, redirect to a temp file and post-process that.
Commit & Pull Requests
- One commit per logical change.
- Mention the affected module only if a change also affects other modules.
- Every commit should test cleanly. pre-commit runs module-specific tests. Manually test other modules before committing if they might be affected.
- Include documentation updates with the main commit. Do not commit docs separately.
- DO NOT include agent information, a verbose description of the change, etc., in commit messages. Do not repeat information that's obvious when looking at the diff.
- DO NOT use "--rebase" when merging or pulling.
- DO NOT use "--no-verify" when committing.
- If you encounter a pre-existing failure, temporarily stash your changes and run a sub-agent to fix the problem.
Agent‑Specific Notes
- You MUST follow these guidelines for any code changes in this repository.
- Do not introduce unrelated tooling or broad refactors unless specifically asked to do so.
- Context compaction: You MUST re-read this document after compacting.
Completion
After editing and updating/closing issues, you MUST complete ALL steps below.
Work is NOT complete until git push succeeds.
Workflow
- File issues for remaining work - Create issues for anything that needs follow-up.
- "git commit" runs quality gates automatically. If errors are reported, fix and resubmit.
- Commit all work. Reference the issue(s) you worked on, if any, in the first line. Example: "Fix moat-abc: wrangled the zumblicator" Add a short explanation of the change if warranted, but DO NOT mention implementation details, esp. not if they are obvious when reading the diff.
- Update issue status (if you're working on one): Close finished work, update in-progress items. Include the commit ID. Example: "Fixed in COMMIT_ID_PREFIX". Don't add information to the bug that's also in the commit's text.
- Push to remote:
- run
git push intern HEAD:main - If there are conflicts,
- git pull --no-edit
- resolve merge conflicts, if any
- retry
git push - repeat until successful
- run
However, if a git push/pull command fails with a permission error, STOP: the problem is a missing SSH key. The user needs to re-add the key before you can continue.
Beads Issue Tracker
This project uses bd (beads) for issue tracking. Run bd prime to see full workflow context and commands.
Quick Reference
bd ready # Find available work
bd show <id> # View issue details
bd update <id> --claim # Claim work
bd close <id> # Complete work
Rules
- Use
bdfor ALL task tracking — do NOT use TodoWrite, TaskCreate, or markdown TODO lists - Run
bd primefor detailed command reference and session close protocol - Use
bd rememberfor persistent knowledge — do NOT use MEMORY.md files
Session Completion
When ending a work session, you MUST complete ALL steps below. Work is NOT complete until git push succeeds.
MANDATORY WORKFLOW:
- File issues for remaining work - Create issues for anything that needs follow-up
- Run quality gates (if code changed) - Tests, linters, builds
- Update issue status - Close finished work, update in-progress items
- PUSH TO REMOTE - This is MANDATORY:
git pull --rebase bd dolt push git push git status # MUST show "up to date with origin" - Clean up - Clear stashes, prune remote branches
- Verify - All changes committed AND pushed
- Hand off - Provide context for next session
CRITICAL RULES:
- Work is NOT complete until
git pushsucceeds - NEVER stop before pushing - that leaves work stranded locally
- NEVER say "ready to push when you are" - YOU must push
- If push fails, resolve and retry until it succeeds