diff --git a/.gitignore b/.gitignore index d7b126e..a19c1ca 100644 --- a/.gitignore +++ b/.gitignore @@ -6,10 +6,9 @@ ports/posix/build/ # macOS Finder metadata .DS_Store -# Personal LLM coding-assistant configs; see CONTRIBUTING.md. -CLAUDE.md +# Personal LLM coding-assistant configs; AGENTS.md and CLAUDE.md are tracked. +# See CONTRIBUTING.md. CLAUDE.local.md -AGENTS.md GEMINI.md .claude/ .cursor/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..ed02f40 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,43 @@ +# cpp-sdk + +Instructions for LLM coding assistants working in this repository. Personal additions go in a gitignored local file (`CLAUDE.local.md` for Claude Code); see [CONTRIBUTING.md](CONTRIBUTING.md#llm-coding-assistants). + +## What this is + +A portable C++17 core for devices and controllers on the Electrification Bus (eBus), which builds on the [Homie 5 MQTT convention](https://homieiot.github.io/). It depends only on the C and C++ standard libraries and ArduinoJson; a port supplies the MQTT client, the console and the clock. [esp32-firmware](https://github.com/electrification-bus/esp32-firmware) consumes it as a git submodule, pinned to a release tag. + +## Layout + +| Path | Contents | +|---|---| +| `mqtt/` | `ebus_mqtt`: the transport interface, publishes held while disconnected, the reconnect order ([doc/mqtt.md](doc/mqtt.md)) | +| `discovery/` | `ebus_discovery`: mDNS TXT records, the `MdnsBackend` interface, broker discovery ([doc/discovery.md](doc/discovery.md)) | +| `homie/` | `ebus_homie`: Device, Node, Property, `/set` dispatch, the controller, validation ([doc/core.md](doc/core.md)) | +| `link/` | `ebus_link`: property links ([doc/link.md](doc/link.md)) | +| `include/` | The pre-split header paths (``), forwarding to the components | +| `ports/posix/` | The POSIX reference port (Paho MQTT C), its demo programs and end-to-end tests | +| `test/` | Unity suites, one directory per suite; `test/support/` holds the fakes that stand in for a port | + +## Commands + +```sh +cmake -S . -B build && cmake --build build -j && ctest --test-dir build --output-on-failure +cmake -S ports/posix -B ports/posix/build && cmake --build ports/posix/build -j && ctest --test-dir ports/posix/build --output-on-failure +``` + +The first runs the core's suites; the second builds the POSIX port and runs its end-to-end tests, which need `mosquitto` installed. A change to what goes on the wire needs the end-to-end tests too, not only a unit test. + +## House style for the core + +`mqtt/`, `discovery/`, `homie/`, `link/` and `include/` run on microcontrollers: + +- No dynamic allocation in steady state: fixed-size buffers and static or caller-owned storage. What allocates today is listed in [doc/core.md](doc/core.md) ("Rules for code in the core"); new code adds nothing to that list. +- No STL, no Arduino `String`, no lambdas. Use `snprintf`, and C function pointers with a `void*` context for callbacks. Members are underscore-prefixed. +- No Arduino, ESP-IDF, FreeRTOS or OS header. Each component includes only standard headers, its own, and those of the components it depends on; CI compiles each with only those include directories. +- C++17, GCC and Clang, warnings as errors in CI. +- Ports (`ports/`) may use their platform's facilities but keep the contract in [doc/core.md](doc/core.md). +- The Homie 5 convention and the [eBus specification](https://github.com/electrification-bus/specification) decide wire behavior: where code and spec disagree, fix the code. On a spec sync, update `.ebus-spec.json`. +- Comments explain a non-obvious why, not what the code does. +- User-visible changes get an entry under `## [Unreleased]` in [CHANGELOG.md](CHANGELOG.md). + +Markdown prose is written one paragraph per line, without hard wraps. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..43c994c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4d657be..ebf3ce5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -47,9 +47,11 @@ Pull requests are welcome. - **Don't hard-wrap Markdown prose.** Write each paragraph in docs as a single continuous line; reserve hard breaks for list items, headings, code fences, and tables. - One commit per logical change is fine; we don't require squash or any particular branch naming. -## Keep your personal LLM config out of the repo +## LLM coding assistants -If you use an LLM coding assistant (Claude Code, Cursor, Aider, etc.), do **not** commit your personal LLM config files (`CLAUDE.md`, `AGENTS.md`, `.claude/`, `.cursor/`, etc.). Different contributors have different setups. Keep them in a separate shadow repo symlinked into your working tree, or add the paths to `.git/info/exclude`. The project `.gitignore` already lists the common ones defensively. If you have a use case for project-wide LLM context that *should* be tracked, discuss with the maintainers first. +[`AGENTS.md`](AGENTS.md) holds the shared instructions for LLM coding assistants (Codex, Cursor, GitHub Copilot and others read it; [`CLAUDE.md`](CLAUDE.md) imports it for Claude Code). Change it by pull request when the project's conventions change. + +Keep your personal configuration out of the repo: `CLAUDE.local.md` (which Claude Code loads alongside `CLAUDE.md`), `.claude/`, `.cursor/` and the like are gitignored. To version them anyway, keep them in a separate private "shadow" repository and symlink them into your working tree, for example `ln -s ~/path/to/shadow-repo/cpp-sdk/CLAUDE.local.md CLAUDE.local.md`; for a file you don't need to version, `.git/info/exclude` works too. ## Code of conduct