Skip to content

docs: rewrite copilot-instructions.md for effective code review#247

Merged
bburda merged 1 commit intomainfrom
docs/update-copilot-instructions
Mar 4, 2026
Merged

docs: rewrite copilot-instructions.md for effective code review#247
bburda merged 1 commit intomainfrom
docs/update-copilot-instructions

Conversation

@bburda
Copy link
Collaborator

@bburda bburda commented Mar 4, 2026

Pull Request

Summary

Comprehensive rewrite of .github/copilot-instructions.md to reflect the current state of the project and optimize instructions for GitHub Copilot PR reviews.

The previous version was outdated - missing packages (fault_manager, serialization, diagnostic_bridge), the handler pattern (HandlerContext, validate_entity_for_route), error handling (tl::expected, error_codes.hpp), plugin framework, and used human-oriented checklists that Copilot couldn't effectively act on.

Key changes:

  • Architecture: Added LogManager, PluginManager, HandlerContext, full entity model with SOVD capability matrix
  • Handler pattern: Documented the 6-step handler flow with HandlerContext validation, error codes, and dual-path routing
  • Review rules: Replaced - [ ] checklists with "Flag when..." directives - actionable rules Copilot can apply to PR diffs
  • Testing requirements: Granular rules for unit tests (handlers, managers, utilities) and integration tests (endpoints, error cases, GatewayTestCase)
  • Anti-patterns table: 11 concrete "if you see X, suggest Y" pairs with real code snippets
  • Documentation rule: "Documentation is part of every change, not a follow-up task"
  • Build system: CMake modules (Compat, Ccache, Linting), medkit_* helpers, multi-distro compatibility

Issue

N/A - maintenance task, no issue tracking required.


Type

  • Bug fix
  • New feature or tests
  • Breaking change
  • Documentation only

Testing

Documentation-only change. No code or tests affected.


Checklist

  • Breaking changes are clearly described (and announced in docs / changelog if needed)
  • Tests were added or updated if needed
  • Docs were updated if behavior or public API changed

Comprehensive update to reflect the current state of the project and
optimize the instructions for GitHub Copilot PR reviews.

Key changes:
- Add full package structure (fault_manager, serialization, etc.)
- Document current architecture (LogManager, PluginManager, HandlerContext)
- Add SOVD entity model with capability matrix
- Document handler pattern with HandlerContext validation flow
- Add error codes reference (SOVD standard + vendor x-medkit-*)
- Document plugin framework and provider interfaces
- Add CMake module documentation (Compat, Ccache, Linting)
- Replace human-oriented checklists with AI-actionable review rules
  using "Flag when..." directives that Copilot can apply to PR diffs
- Add granular test requirements: unit tests for handlers/managers,
  integration tests for endpoints, error case coverage
- Add anti-patterns quick reference table with concrete code examples
- Add documentation-as-part-of-every-change rule
Copilot AI review requested due to automatic review settings March 4, 2026 19:50
@bburda bburda self-assigned this Mar 4, 2026
@bburda bburda requested a review from mfaferek93 March 4, 2026 19:50
@bburda bburda merged commit 1493676 into main Mar 4, 2026
6 checks passed
@bburda bburda deleted the docs/update-copilot-instructions branch March 4, 2026 19:53
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Rewrites .github/copilot-instructions.md to better reflect the current ros2_medkit architecture and provide actionable, diff-oriented rules for GitHub Copilot PR reviews (handlers, error handling, plugins, build/test expectations).

Changes:

  • Expands project/package/architecture documentation to cover current gateway subsystems and multi-package workspace.
  • Documents the handler/route/error-code patterns and adds concrete “Flag when…” review rules plus anti-pattern guidance.
  • Adds more specific unit/integration testing requirements and traceability guidance.

Comment on lines +41 to +46
Defined in `include/ros2_medkit_gateway/models/`:

- **Area** - namespace grouping (`/powertrain`, `/chassis`, `root`)
- **Component** - groups Apps by namespace (synthetic in runtime mode, explicit in manifest)
- **App** - individual ROS 2 node
- **Function** - capability grouping (functional view, aggregates Apps)
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The doc says the Area/Component/App/Function entity model is defined in include/ros2_medkit_gateway/models/, but those concrete entity structs live under include/ros2_medkit_gateway/discovery/models/ (the models/ directory contains capabilities/types/cache wrappers). Please update this path to match the actual code locations so reviewers/bots don’t get sent to the wrong headers.

Copilot uses AI. Check for mistakes.
Comment on lines +54 to 61
| Collection | Server | Area | Component | App | Function |
|-----------|--------|------|-----------|-----|----------|
| configurations | x | | x | x | |
| data | x | | x | x | x (aggregated) |
| faults | x | | x | x | |
| operations | x | | x | x | x (aggregated) |
| logs | x | | x | x | |

Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the “SOVD Resource Collections” table, logs is listed as a resource collection, but the code’s ResourceCollection enum uses COMMUNICATION_LOGS with the path segment communication-logs (and logs appears as a resource name in EntityCapabilities). Consider renaming this row or clarifying whether you mean the /logs resource vs the communication-logs collection so the table matches the implementation.

Suggested change
| Collection | Server | Area | Component | App | Function |
|-----------|--------|------|-----------|-----|----------|
| configurations | x | | x | x | |
| data | x | | x | x | x (aggregated) |
| faults | x | | x | x | |
| operations | x | | x | x | x (aggregated) |
| logs | x | | x | x | |
| Collection (path segment) | Server | Area | Component | App | Function |
|---------------------------|--------|------|-----------|-----|----------|
| configurations | x | | x | x | |
| data | x | | x | x | x (aggregated) |
| faults | x | | x | x | |
| operations | x | | x | x | x (aggregated) |
| communication-logs | x | | x | x | |
Note: The `/logs` resource (as referenced in `EntityCapabilities`) is provided within the `communication-logs` collection.

Copilot uses AI. Check for mistakes.
Comment on lines +122 to +131
**Vendor-specific** (`x-medkit-` prefix): `ERR_X_MEDKIT_ROS2_SERVICE_UNAVAILABLE`, `ERR_X_MEDKIT_ROS2_NODE_UNAVAILABLE`, `ERR_X_MEDKIT_ROS2_TOPIC_UNAVAILABLE`, etc.

- **ROS 2 Jazzy** (Ubuntu 24.04) / **ROS 2 Humble** (Ubuntu 22.04) / **ROS 2 Rolling** (Ubuntu 24.04, best-effort)
- **cpp-httplib**: HTTP server (found via pkg-config)
- **nlohmann_json**: JSON serialization
- **yaml-cpp**: Configuration parsing
Error response schema:
```json
{
"error_code": "entity-not-found",
"message": "Component not found",
"parameters": {"entity_id": "my_component"}
}
```
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error response schema example omits the vendor_code field that HandlerContext::send_error() adds for vendor errors (x-medkit-*), where error_code becomes vendor-error. Please update this section to mention/illustrate vendor_code, otherwise it suggests an incorrect response format for vendor-specific failures.

Copilot uses AI. Check for mistakes.
### Error Handling

## Design Principles
- **Flag** `throw` statements in handler or manager code. Use `tl::expected<T, std::string>` and return `tl::make_unexpected(msg)` instead.
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rule “Flag throw statements in handler or manager code” doesn’t match the current codebase: several manager/config modules do throw (e.g., AuthManager, DataAccessManager, manifest parsing, etc.). If the intent is only “don’t throw from HTTP handlers” (or only from specific layers), please narrow/reword this rule to avoid generating false-positive PR comments against existing patterns.

Suggested change
- **Flag** `throw` statements in handler or manager code. Use `tl::expected<T, std::string>` and return `tl::make_unexpected(msg)` instead.
- **Flag** `throw` statements in HTTP handler code (e.g., REST handlers in `rest_server.cpp`). Prefer using `tl::expected<T, std::string>` to propagate failures or `HandlerContext::send_error()` with an early return instead of throwing. Manager and configuration layers may continue to use exceptions where consistent with existing patterns.

Copilot uses AI. Check for mistakes.
| `UpdateProvider` | `providers/update_provider.hpp` | Software update management |
| `IntrospectionProvider` | `providers/introspection_provider.hpp` | Custom entity introspection |

Plugins loaded as `.so` files with `extern "C"` factory. Provider interfaces return typed C++ structs (not JSON) - manager layer handles serialization. Plugin failures are caught and isolated.
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This says provider interfaces “return typed C++ structs (not JSON)”, but at least UpdateProvider::get_update/register_update uses nlohmann::json, and IntrospectionProvider::IntrospectionResult::metadata is JSON. Please adjust this wording to reflect that providers may exchange JSON for metadata while still avoiding “HTTP-level JSON responses” in the plugin API.

Suggested change
Plugins loaded as `.so` files with `extern "C"` factory. Provider interfaces return typed C++ structs (not JSON) - manager layer handles serialization. Plugin failures are caught and isolated.
Plugins are loaded as `.so` files with an `extern "C"` factory. Provider interfaces primarily return typed C++ structs, with optional `nlohmann::json` fields for metadata (e.g., update payloads or introspection metadata); HTTP-level JSON responses and serialization remain the responsibility of the manager/REST layer. Plugin failures are caught and isolated.

Copilot uses AI. Check for mistakes.
}
```

**ROS_DOMAIN_ID isolation**: GTest targets creating `rclcpp::Node` need unique domain IDs. Current: 62-66 (fault_manager), 99 (gateway). Next available: 67.
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ROS_DOMAIN_ID note is out of date: ros2_medkit_fault_manager uses 62–65 and ros2_medkit_gateway uses 66 (see package CMakeLists). There is no 99 in current CTest properties. Please update the “current IDs” list so it stays consistent with the build config.

Suggested change
**ROS_DOMAIN_ID isolation**: GTest targets creating `rclcpp::Node` need unique domain IDs. Current: 62-66 (fault_manager), 99 (gateway). Next available: 67.
**ROS_DOMAIN_ID isolation**: GTest targets creating `rclcpp::Node` need unique domain IDs. Current: 62–65 (`ros2_medkit_fault_manager`), 66 (`ros2_medkit_gateway`). Next available: 67.

Copilot uses AI. Check for mistakes.

**General test rules:**
- **Flag** any use of `GTEST_SKIP()`, `@pytest.mark.skip`, `unittest.skip`, or equivalent - tests must not be skipped, fix the code or the test instead.
- **Flag** GTest files that create `rclcpp::Node` without setting a unique `ROS_DOMAIN_ID` in CMakeLists.txt `set_tests_properties()`. Current IDs: 62-66, 99. Next available: 67.
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This rule references “Current IDs: 62-66, 99”, but the repository’s CMake currently assigns 62–65 to fault_manager tests and 66 to gateway’s test_log_manager. Please update this line (and keep the “next available” guidance consistent) to avoid encoding incorrect IDs into future PR reviews.

Suggested change
- **Flag** GTest files that create `rclcpp::Node` without setting a unique `ROS_DOMAIN_ID` in CMakeLists.txt `set_tests_properties()`. Current IDs: 62-66, 99. Next available: 67.
- **Flag** GTest files that create `rclcpp::Node` without setting a unique `ROS_DOMAIN_ID` in CMakeLists.txt `set_tests_properties()`. Current ROS_DOMAIN_IDs in CMake: 62–65 (fault_manager tests), 66 (gateway `test_log_manager`), 99. Next available: 67.

Copilot uses AI. Check for mistakes.
| `find_package(yaml-cpp REQUIRED)` | Use `medkit_find_yaml_cpp()` |
| `res.set_header("Content-Type", ...)` + `set_chunked_content_provider(...)` | Remove `set_header` - provider sets Content-Type |
| `GTEST_SKIP()` or `@pytest.mark.skip` | Fix the test or the code, never skip |
| `set_tests_properties(... ENVIRONMENT "ROS_DOMAIN_ID=99")` reusing existing ID | Assign next available ID (67) |
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The anti-pattern example hard-codes ROS_DOMAIN_ID=99 as an “existing ID”, but the current gateway tests use 66 (and fault_manager uses 62–65). Please update this example to reference the actual assigned IDs so it remains actionable and accurate.

Suggested change
| `set_tests_properties(... ENVIRONMENT "ROS_DOMAIN_ID=99")` reusing existing ID | Assign next available ID (67) |
| `set_tests_properties(... ENVIRONMENT "ROS_DOMAIN_ID=66")` reusing existing ID | Assign next available ID (67) |

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants