From e3310565008cdf224fd9d6daf387bf08e900413b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 5 Nov 2025 16:35:01 -0600 Subject: [PATCH 1/3] Update AI instructions with C++ style guidelines from developers documentation --- .ai/instructions.md | 62 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/.ai/instructions.md b/.ai/instructions.md index 5f314a0dc9..fbff419efa 100644 --- a/.ai/instructions.md +++ b/.ai/instructions.md @@ -51,7 +51,67 @@ This document provides essential context for AI models interacting with this pro * **Naming Conventions:** * **Python:** Follows PEP 8. Use clear, descriptive names following snake_case. - * **C++:** Follows the Google C++ Style Guide. + * **C++:** Follows the Google C++ Style Guide with these specifics (following clang-tidy conventions): + - Function, method, and variable names: `lower_snake_case` + - Class/struct/enum names: `UpperCamelCase` + - Top-level constants (global/namespace scope): `UPPER_SNAKE_CASE` + - Function-local constants: `lower_snake_case` + - Protected/private fields: `lower_snake_case_with_trailing_underscore_` + - Favor descriptive names over abbreviations + +* **C++ Field Visibility:** + * **Prefer `protected`:** Use `protected` for most class fields to enable extensibility and testing. Fields should be `lower_snake_case_with_trailing_underscore_`. + * **Use `private` for safety-critical cases:** Use `private` visibility when direct field access could introduce bugs or violate invariants: + 1. **Pointer lifetime issues:** When setters validate pointers against known lists to prevent dangling references. + ```cpp + class SelectComponent { + public: + void set_options(const std::vector &options) { + this->options_ = options; + this->current_option_ = nullptr; // Reset to prevent dangling pointer + } + void set_selected_option(const std::string *option) { + // Validate that option points to an entry in options_ + if (std::find(this->options_.begin(), this->options_.end(), *option) != this->options_.end()) { + this->current_option_ = option; + } + } + private: + std::vector options_; + const std::string *current_option_{nullptr}; // Must point to entry in options_ + }; + ``` + 2. **Invariant coupling:** When multiple fields must remain synchronized to prevent buffer overflows or data corruption. + ```cpp + class Buffer { + public: + void resize(size_t new_size) { + auto new_data = std::make_unique(new_size); + if (this->data_) { + std::memcpy(new_data.get(), this->data_.get(), std::min(this->size_, new_size)); + } + this->data_ = std::move(new_data); + this->size_ = new_size; // Must stay in sync with data_ + } + private: + std::unique_ptr data_; + size_t size_{0}; // Must match allocated size of data_ + }; + ``` + 3. **Resource management:** When setters perform cleanup or registration operations that derived classes might skip. + * **Provide `protected` accessor methods:** When derived classes need controlled access to `private` members. + +* **C++ Preprocessor Directives:** + * **Avoid `#define` for constants:** Using `#define` for constants is discouraged and should be replaced with `const` variables or enums. + * **Use `#define` only for:** + - Conditional compilation (`#ifdef`, `#ifndef`) + - Compile-time sizes calculated during Python code generation (e.g., configuring `std::array` or `StaticVector` dimensions via `cg.add_define()`) + +* **C++ Additional Conventions:** + * **Member access:** Prefix all class member access with `this->` (e.g., `this->value_` not `value_`) + * **Indentation:** Use spaces (two per indentation level), not tabs + * **Type aliases:** Prefer `using type_t = int;` over `typedef int type_t;` + * **Line length:** Wrap lines at no more than 120 characters * **Component Structure:** * **Standard Files:** From c83e5e076be04398c209fc0854246f9dea0e055c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 5 Nov 2025 16:41:26 -0600 Subject: [PATCH 2/3] cleanup --- .ai/instructions.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.ai/instructions.md b/.ai/instructions.md index fbff419efa..bb87eb3050 100644 --- a/.ai/instructions.md +++ b/.ai/instructions.md @@ -71,10 +71,17 @@ This document provides essential context for AI models interacting with this pro this->current_option_ = nullptr; // Reset to prevent dangling pointer } void set_selected_option(const std::string *option) { - // Validate that option points to an entry in options_ - if (std::find(this->options_.begin(), this->options_.end(), *option) != this->options_.end()) { - this->current_option_ = option; + // Validate that option points to an entry in options_ by checking address range + if (option == nullptr) { + return; } + for (const auto &opt : this->options_) { + if (&opt == option) { + this->current_option_ = option; + return; + } + } + // Invalid pointer - doesn't point to an element in options_ } private: std::vector options_; From f8aee13a3ab9fa7773549d19dfba553a73e4eb85 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 5 Nov 2025 16:44:06 -0600 Subject: [PATCH 3/3] use actual pattern --- .ai/instructions.md | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/.ai/instructions.md b/.ai/instructions.md index bb87eb3050..9309c67c65 100644 --- a/.ai/instructions.md +++ b/.ai/instructions.md @@ -62,30 +62,35 @@ This document provides essential context for AI models interacting with this pro * **C++ Field Visibility:** * **Prefer `protected`:** Use `protected` for most class fields to enable extensibility and testing. Fields should be `lower_snake_case_with_trailing_underscore_`. * **Use `private` for safety-critical cases:** Use `private` visibility when direct field access could introduce bugs or violate invariants: - 1. **Pointer lifetime issues:** When setters validate pointers against known lists to prevent dangling references. + 1. **Pointer lifetime issues:** When setters validate and store pointers from known lists to prevent dangling references. ```cpp - class SelectComponent { - public: - void set_options(const std::vector &options) { - this->options_ = options; - this->current_option_ = nullptr; // Reset to prevent dangling pointer + // Helper to find matching string in vector and return its pointer + inline const char *vector_find(const std::vector &vec, const char *value) { + for (const char *item : vec) { + if (strcmp(item, value) == 0) + return item; } - void set_selected_option(const std::string *option) { - // Validate that option points to an entry in options_ by checking address range - if (option == nullptr) { - return; + return nullptr; + } + + class ClimateDevice { + public: + void set_custom_fan_modes(std::initializer_list modes) { + this->custom_fan_modes_ = modes; + this->active_custom_fan_mode_ = nullptr; // Reset when modes change + } + bool set_custom_fan_mode(const char *mode) { + // Find mode in supported list and store that pointer (not the input pointer) + const char *validated_mode = vector_find(this->custom_fan_modes_, mode); + if (validated_mode != nullptr) { + this->active_custom_fan_mode_ = validated_mode; + return true; } - for (const auto &opt : this->options_) { - if (&opt == option) { - this->current_option_ = option; - return; - } - } - // Invalid pointer - doesn't point to an element in options_ + return false; } private: - std::vector options_; - const std::string *current_option_{nullptr}; // Must point to entry in options_ + std::vector custom_fan_modes_; // Pointers to string literals in flash + const char *active_custom_fan_mode_{nullptr}; // Must point to entry in custom_fan_modes_ }; ``` 2. **Invariant coupling:** When multiple fields must remain synchronized to prevent buffer overflows or data corruption.