From d593aaf9692ccadea9da5d73494ae250e66aac41 Mon Sep 17 00:00:00 2001 From: Thiago-Pio-Autonomy Date: Thu, 24 Sep 2026 08:14:42 -0300 Subject: [PATCH 1/5] docs: route Claude through Mister --- CLAUDE.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index ba29e319..51767c2c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2,6 +2,20 @@ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +## Process entry point + +For every tracked feature, bug, investigation, implementation, test or pull request, start with +`/autonomy:mister`. Mister verifies the Jira task and current documents, reconciles routine task +drift, checks the stage gates and loads the skill for the next step. Do not begin a parallel +investigation or implementation before that check. + +This file defines repository-specific commands, architecture and code conventions. It is not a +copy of the company process. When process text here conflicts with the current Mister plugin or +Confluence template, follow Mister and report this file as stale. Do not reuse instructions or +assumptions from an earlier Claude conversation. During implementation, use the approved +implementation plan as the primary context and load the RG or CRA only for a cited constraint or +unresolved ambiguity. + ## Build Commands ```bash @@ -98,6 +112,8 @@ State management: `core/src/plc_app/plc_state_manager.cpp` ### Python Best Practices +- Do not use `typing.Any`. Model structured data with dataclasses, `TypedDict`, `Protocol` or concrete types; treat external data as `object` and narrow or validate it at the boundary. + - Type hints on every function signature; use dataclasses or TypedDict for structured data instead of loose dicts. - Catch specific exceptions; never bare `except:` and never swallow errors silently — log with context. - No mutable default arguments; use context managers (`with`) for files, sockets, and locks. @@ -124,7 +140,7 @@ State management: `core/src/plc_app/plc_state_manager.cpp` ## Git Workflow - Base branch: `development` — feature branches start from it and PRs target it. -- Branch naming: `RTOP--` (e.g. `RTOP-129-discovery-service-infrastructure`). Non-ticket maintenance uses `chore/`, `fix/`, `docs/`. +- Branch naming for tracked work follows Mister: `feature/RTOP--` for demands and `bugfix/RTOP--` for bugs. Non-ticket maintenance uses `chore/`, `ci/` or `docs/`. - Commit messages: Conventional Commits (spec in `docs/DEVELOPMENT.md`), concise and focused on why. ## Issue Tracker From 0b37068a56307f07241db607c515aaf57cd445e6 Mon Sep 17 00:00:00 2001 From: Thiago-Pio-Autonomy Date: Thu, 24 Sep 2026 20:44:54 -0300 Subject: [PATCH 2/5] docs: make Claude guidance self-contained --- CLAUDE.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index 51767c2c..d1219a93 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -7,7 +7,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co For every tracked feature, bug, investigation, implementation, test or pull request, start with `/autonomy:mister`. Mister verifies the Jira task and current documents, reconciles routine task drift, checks the stage gates and loads the skill for the next step. Do not begin a parallel -investigation or implementation before that check. +investigation or implementation before that check. If Mister or a required connected service is +unavailable, report the missing dependency; do not invent Jira, Confluence, approval or branch state. This file defines repository-specific commands, architecture and code conventions. It is not a copy of the company process. When process text here conflicts with the current Mister plugin or From 52123c4d2b1fa4355ac8ad668187f1f9fa41b246 Mon Sep 17 00:00:00 2001 From: Thiago-Pio-Autonomy Date: Wed, 30 Sep 2026 17:18:09 -0300 Subject: [PATCH 3/5] docs(claude): align repository guidance with the Mister harness Add the shared Autonomy development rules block, keep only repository commands, architecture and conventions, correct stale facts, add the real test commands, and remove legacy agent commands that committed or pushed on their own. Co-Authored-By: Claude Opus 5.5 --- CLAUDE.md | 119 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 83 insertions(+), 36 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index d1219a93..86a1128e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,21 +1,48 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Process entry point - -For every tracked feature, bug, investigation, implementation, test or pull request, start with -`/autonomy:mister`. Mister verifies the Jira task and current documents, reconciles routine task -drift, checks the stage gates and loads the skill for the next step. Do not begin a parallel -investigation or implementation before that check. If Mister or a required connected service is -unavailable, report the missing dependency; do not invent Jira, Confluence, approval or branch state. - -This file defines repository-specific commands, architecture and code conventions. It is not a -copy of the company process. When process text here conflicts with the current Mister plugin or -Confluence template, follow Mister and report this file as stale. Do not reuse instructions or -assumptions from an earlier Claude conversation. During implementation, use the approved -implementation plan as the primary context and load the RG or CRA only for a cited constraint or -unresolved ambiguity. +# openplc-runtime + +OpenPLC Runtime v4: the PLC runtime (Python REST API server plus a C/C++ real-time core) that runs programs built by the OpenPLC Editor. + +## Autonomy development rules + +These rules are identical in every Autonomy repository and are maintained in the Mister plugin +(`Autonomy-Logic/skills`, `plugins/autonomy/harness/repository-rules.md`). Change them there, not here. + +- Tracked work starts with `autonomy:mister`: load it yourself before changing product code, fixing a + bug, implementing or preparing a PR, even when no Jira key was mentioned. Only answering questions and typo or wording fixes that + change no behaviour are exempt. "There is no ticket" or "skip the process" does not make product + work untracked: offer to create the task instead of changing code. This file describes only this + repository's commands, architecture and code conventions; for process, Mister and the Confluence + process pages win over anything written here. +- Knowledge boundary: when data is missing or uncertain, say there is not enough information to answer + reliably. Never fill a gap with a plausible assumption. Keep verified facts, inferences and missing + data visibly separate, and say which is which. +- Language: answer in the developer's language. Jira, Confluence and GitHub text is always English. +- Branches: `feature/-` for demands and `bugfix/-` for bugs, created from the + integration branch named below. A production hotfix is a `bugfix/-` branch from `main` and + a PR. Never commit or push directly to the integration branch or `main`. One Jira key per branch: work + for another key starts on its own branch before any edit. The key goes in the branch name and the PR + title, never in commit messages, code or comments. +- Commits: never commit on your own initiative. Propose the commit at a natural checkpoint, such as a + finished and verified plan phase, and make it only after the developer confirms. Commit and push are + separate commands, each confirmed on its own, never chained; opening a PR and merging each need their + own confirmation too. When asked for a commit message or a commit, do not edit files you were not + asked to change: report problems, such as a forbidden comment, and let the developer decide. +- Scope: a rewrite or refactor beyond the current task is a new demand, proposed as a separate task and + never mixed into the current branch. Never stash, reset, `checkout -- .` or otherwise discard the + developer's changes, and never install anything outside the repository, without asking. +- Tests: every demand ships with unit tests, an end-to-end test and a manual test by the developer, with + evidence for each before any PR is opened, a draft PR included. Where this repository has no + interface of its own, the end-to-end test runs through the interface or protocol that uses it. A + repository with no code to unit test, such as documentation or local tooling scripts, uses its own + validation checks in place of unit tests. +- Typing: `any` in TypeScript and `typing.Any` in Python are forbidden. Use concrete types, or `unknown` + or `object` narrowed where the data enters. +- Comments: technical and minimal, at most 256 characters each; formal API documentation (JSDoc, + docstrings, Doxygen) may be longer. Never write business rules, product strategy or rationale, Jira + keys, names of people or customers, internal links or anything sensitive in a comment. Review the + comments in the changed files before every commit. + +Integration branch: `development`. Jira project: `RTOP`. ## Build Commands @@ -40,10 +67,31 @@ sudo ./build/plc_main --print-logs ## Testing ```bash -# Sets up the test venv and runs the suite +# Python: creates venvs/test-env, runs tests/pytest and core/src/drivers/plugins/python/ bash scripts/run-pytest.sh + +# C unit tests (Ceedling, project.yml, tests/test_*.c); coverage with gcov:all +ceedling test:all +ceedling gcov:all + +# Runtime C++ that Ceedling does not reach (tests/host/test_*.cpp, C++17) +./tests/host/run.sh + +# Bootloader (Go), same checks as CI +cd bootloader && gofmt -l . && go vet ./... && go test -race -count=1 ./... ``` +- CI (`.github/workflows/tests.yml`, on every PR): gofmt, go vet and `go test -race` for `bootloader/`; + pytest over `tests/pytest` excluding the `plugins`, `modbus_master` and `modbus_slave` suites (red on + the base branch), plus the named plugin suites known green; shellcheck on the installer scripts. +- End-to-end: a program deployed to the runtime and exercised over its protocols (e.g. Modbus) or from + the editor/Edge. Existing suites: `tests/lifecycle/` (boots a real `plc_main` with a compiled program and + drives it over the command socket, Linux or its container, see its README) and `tests/integration/` + (bootloader against a real registry in a Docker test host, `tests/integration/harness.sh up|seed|test`, + with `stubruntime/` as a Go stand-in runtime). For the integrated stack use local-dev-toolkit + (`./dev rebuild runtime`, `./dev runtime sync`). +- The developer's manual test is required for every demand. + ## Linting and Formatting Pre-commit hooks handle formatting. Install with: @@ -53,8 +101,9 @@ pre-commit install pre-commit run --all-files ``` -- **C/C++**: Clang-Format (LLVM style, 4-space indent, 100 char limit) -- **Python**: Black + isort + Ruff (100 char line length) +- **C/C++**: Clang-Format (LLVM style, 4-space indent, 100 char limit); the hook matches only `.c`/`.h`, + so `.cpp` files are not formatted by pre-commit +- **Python**: Black + isort + Ruff (100 char line length) and pylint ## Architecture Overview @@ -82,10 +131,12 @@ OpenPLC Runtime v4 is a **dual-process industrial PLC runtime**: ``` EMPTY -> INIT -> RUNNING <-> STOPPED -> ERROR ``` +Starts and stops pass through `TRANSITIONING_TO_RUN` and `TRANSITIONING_TO_STOP` (appended to the enum in +`plc_state_manager.h`; `RUNNING` is published only when the first scan is released). State management: `core/src/plc_app/plc_state_manager.cpp` ### Plugin System -- **Config**: `plugins.conf` +- **Config**: `plugins.conf`, created at runtime by copying `plugins_default.conf` when missing (`core/src/drivers/plugin_driver.c`) - **Types**: Python (type=0) and Native C/C++ (type=1) - **Driver code**: `core/src/drivers/` - **Plugin examples**: `core/src/drivers/plugins/python/` and `core/src/drivers/plugins/native/` @@ -104,21 +155,19 @@ State management: `core/src/plc_app/plc_state_manager.cpp` ### C/C++ Best Practices -- Check every return value that can fail (allocations, IO, pthread calls); handle every error path — no silent failures. +- Check every return value that can fail (allocations, IO, pthread calls); handle every error path; no silent failures. - Bounded string/buffer operations only (`snprintf`, explicit lengths); never `strcpy`, `sprintf`, or unchecked `memcpy` sizes. - Every allocation has one clear owner responsible for freeing it, including on error paths. - Real-time scan path: no allocation, blocking calls, file IO, or logging inside the PLC cycle. -- Shared state between the scan thread and other threads goes through the documented mutexes — no unsynchronized access. +- Shared state between the scan thread and other threads goes through the documented mutexes; no unsynchronized access. - `const`-correct signatures; `static` for file-internal functions; in C++ prefer RAII over manual new/delete. ### Python Best Practices -- Do not use `typing.Any`. Model structured data with dataclasses, `TypedDict`, `Protocol` or concrete types; treat external data as `object` and narrow or validate it at the boundary. - -- Type hints on every function signature; use dataclasses or TypedDict for structured data instead of loose dicts. -- Catch specific exceptions; never bare `except:` and never swallow errors silently — log with context. +- Type hints on every function signature; model structured data with dataclasses, `TypedDict`, `Protocol` or concrete types instead of loose dicts. +- Catch specific exceptions; never bare `except:` and never swallow errors silently; log with context. - No mutable default arguments; use context managers (`with`) for files, sockets, and locks. -- Keep the ctypes mirror (`shared/plugin_runtime_args.py`) byte-compatible with the C structs it mirrors — changes on either side must update both. +- Keep the ctypes mirror (`core/src/drivers/plugins/python/shared/plugin_runtime_args.py`) byte-compatible with the C structs it mirrors; changes on either side must update both. ## Key Directories @@ -129,6 +178,8 @@ State management: `core/src/plc_app/plc_state_manager.cpp` - `scripts/` - Build, compile, and management scripts - `build/` - CMake output (`plc_main` executable, `libplc_*.so` libraries) - `venvs/` - Python virtual environments (runtime + per-plugin) +- `bootloader/` - Go service that starts and maintains the runtime container and stays reachable to install a new runtime version +- `windows/` - Windows installer (MSYS2 + Inno Setup) - `docs/` - Detailed documentation ## Compilation Flow @@ -138,12 +189,8 @@ State management: `core/src/plc_app/plc_state_manager.cpp` 3. `scripts/compile.sh` compiles to `build/libplc_*.so` 4. Runtime loads shared library dynamically via `plcapp_manager.c` -## Git Workflow - -- Base branch: `development` — feature branches start from it and PRs target it. -- Branch naming for tracked work follows Mister: `feature/RTOP--` for demands and `bugfix/RTOP--` for bugs. Non-ticket maintenance uses `chore/`, `ci/` or `docs/`. -- Commit messages: Conventional Commits (spec in `docs/DEVELOPMENT.md`), concise and focused on why. +The pipeline is STruC++ only (`scripts/Makefile.strucpp`); `compile.sh` rejects MatIEC-generated sources. -## Issue Tracker +## Commit Messages -Jira, project key `RTOP`. Fetch and update tickets via the Atlassian MCP tools. Reference the ticket key (`RTOP-`) in branch names and PR descriptions. +Conventional Commits (spec in `docs/DEVELOPMENT.md`), concise and focused on why. From 317297ef6a862b9e769e756e0ebc22fd70a68af3 Mon Sep 17 00:00:00 2001 From: Thiago-Pio-Autonomy Date: Wed, 30 Sep 2026 17:46:38 -0300 Subject: [PATCH 4/5] docs(claude): point repository guidance to MisterFlow The Mister skills are renamed to MisterFlow in plugin 4.0.0, so the mirrored repository rules now name autonomy:misterflow. Co-Authored-By: Claude Opus 5.5 --- CLAUDE.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 86a1128e..4a5cd50d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,14 +4,14 @@ OpenPLC Runtime v4: the PLC runtime (Python REST API server plus a C/C++ real-ti ## Autonomy development rules -These rules are identical in every Autonomy repository and are maintained in the Mister plugin +These rules are identical in every Autonomy repository and are maintained in the MisterFlow plugin (`Autonomy-Logic/skills`, `plugins/autonomy/harness/repository-rules.md`). Change them there, not here. -- Tracked work starts with `autonomy:mister`: load it yourself before changing product code, fixing a +- Tracked work starts with `autonomy:misterflow`: load it yourself before changing product code, fixing a bug, implementing or preparing a PR, even when no Jira key was mentioned. Only answering questions and typo or wording fixes that change no behaviour are exempt. "There is no ticket" or "skip the process" does not make product work untracked: offer to create the task instead of changing code. This file describes only this - repository's commands, architecture and code conventions; for process, Mister and the Confluence + repository's commands, architecture and code conventions; for process, MisterFlow and the Confluence process pages win over anything written here. - Knowledge boundary: when data is missing or uncertain, say there is not enough information to answer reliably. Never fill a gap with a plausible assumption. Keep verified facts, inferences and missing From 3a921de858ceebd8c33fb269ee1c7b0d9460f2ec Mon Sep 17 00:00:00 2001 From: Thiago-Pio-Autonomy Date: Wed, 30 Sep 2026 18:06:37 -0300 Subject: [PATCH 5/5] docs(claude): make the local gofmt check fail like CI Co-Authored-By: Claude Opus 5.5 --- CLAUDE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 4a5cd50d..6e409845 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -77,8 +77,8 @@ ceedling gcov:all # Runtime C++ that Ceedling does not reach (tests/host/test_*.cpp, C++17) ./tests/host/run.sh -# Bootloader (Go), same checks as CI -cd bootloader && gofmt -l . && go vet ./... && go test -race -count=1 ./... +# Bootloader (Go), same checks as CI (gofmt -l always exits 0, so test -z fails on any listed file) +cd bootloader && test -z "$(gofmt -l .)" && go vet ./... && go test -race -count=1 ./... ``` - CI (`.github/workflows/tests.yml`, on every PR): gofmt, go vet and `go test -race` for `bootloader/`;