ma-agents 3.1.0 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.opencode/skills/.ma-agents.json +99 -99
- package/.roo/rules/00-ma-agents.md +13 -0
- package/.roo/skills/.ma-agents.json +241 -0
- package/.roo/skills/MANIFEST.yaml +254 -0
- package/.roo/skills/ai-audit-trail/SKILL.md +23 -0
- package/.roo/skills/auto-bug-detection/SKILL.md +169 -0
- package/.roo/skills/cmake-best-practices/SKILL.md +64 -0
- package/.roo/skills/cmake-best-practices/examples/cmake.md +59 -0
- package/.roo/skills/code-documentation/SKILL.md +57 -0
- package/.roo/skills/code-documentation/examples/cpp.md +29 -0
- package/.roo/skills/code-documentation/examples/csharp.md +28 -0
- package/.roo/skills/code-documentation/examples/javascript_typescript.md +28 -0
- package/.roo/skills/code-documentation/examples/python.md +57 -0
- package/.roo/skills/code-review/SKILL.md +43 -0
- package/.roo/skills/commit-message/SKILL.md +79 -0
- package/.roo/skills/cpp-best-practices/SKILL.md +234 -0
- package/.roo/skills/cpp-best-practices/examples/modern-idioms.md +189 -0
- package/.roo/skills/cpp-best-practices/examples/naming-and-organization.md +102 -0
- package/.roo/skills/cpp-concurrency-safety/SKILL.md +60 -0
- package/.roo/skills/cpp-concurrency-safety/examples/concurrency.md +73 -0
- package/.roo/skills/cpp-const-correctness/SKILL.md +63 -0
- package/.roo/skills/cpp-const-correctness/examples/const_correctness.md +54 -0
- package/.roo/skills/cpp-memory-handling/SKILL.md +42 -0
- package/.roo/skills/cpp-memory-handling/examples/modern-cpp.md +49 -0
- package/.roo/skills/cpp-memory-handling/examples/smart-pointers.md +46 -0
- package/.roo/skills/cpp-modern-composition/SKILL.md +64 -0
- package/.roo/skills/cpp-modern-composition/examples/composition.md +51 -0
- package/.roo/skills/cpp-robust-interfaces/SKILL.md +55 -0
- package/.roo/skills/cpp-robust-interfaces/examples/interfaces.md +56 -0
- package/.roo/skills/create-hardened-docker-skill/SKILL.md +637 -0
- package/.roo/skills/create-hardened-docker-skill/scripts/create-all.sh +489 -0
- package/.roo/skills/csharp-best-practices/SKILL.md +278 -0
- package/.roo/skills/docker-hardening-verification/SKILL.md +28 -0
- package/.roo/skills/docker-hardening-verification/scripts/verify-hardening.sh +39 -0
- package/.roo/skills/docker-image-signing/SKILL.md +28 -0
- package/.roo/skills/docker-image-signing/scripts/sign-image.sh +33 -0
- package/.roo/skills/document-revision-history/SKILL.md +104 -0
- package/.roo/skills/git-workflow-skill/SKILL.md +194 -0
- package/.roo/skills/git-workflow-skill/hooks/commit-msg +61 -0
- package/.roo/skills/git-workflow-skill/hooks/pre-commit +38 -0
- package/.roo/skills/git-workflow-skill/hooks/prepare-commit-msg +56 -0
- package/.roo/skills/git-workflow-skill/scripts/finish-feature.sh +192 -0
- package/.roo/skills/git-workflow-skill/scripts/install-hooks.sh +55 -0
- package/.roo/skills/git-workflow-skill/scripts/start-feature.sh +110 -0
- package/.roo/skills/git-workflow-skill/scripts/validate-workflow.sh +229 -0
- package/.roo/skills/js-ts-dependency-mgmt/SKILL.md +49 -0
- package/.roo/skills/js-ts-dependency-mgmt/examples/dependency_mgmt.md +60 -0
- package/.roo/skills/js-ts-security-skill/SKILL.md +64 -0
- package/.roo/skills/js-ts-security-skill/scripts/verify-security.sh +136 -0
- package/.roo/skills/logging-best-practices/SKILL.md +50 -0
- package/.roo/skills/logging-best-practices/examples/cpp.md +36 -0
- package/.roo/skills/logging-best-practices/examples/csharp.md +49 -0
- package/.roo/skills/logging-best-practices/examples/javascript.md +77 -0
- package/.roo/skills/logging-best-practices/examples/python.md +57 -0
- package/.roo/skills/logging-best-practices/references/logging-standards.md +29 -0
- package/.roo/skills/open-presentation/SKILL.md +35 -0
- package/.roo/skills/opentelemetry-best-practices/SKILL.md +34 -0
- package/.roo/skills/opentelemetry-best-practices/examples/go.md +32 -0
- package/.roo/skills/opentelemetry-best-practices/examples/javascript.md +58 -0
- package/.roo/skills/opentelemetry-best-practices/examples/python.md +37 -0
- package/.roo/skills/opentelemetry-best-practices/references/otel-standards.md +37 -0
- package/.roo/skills/python-best-practices/SKILL.md +385 -0
- package/.roo/skills/python-dependency-mgmt/SKILL.md +42 -0
- package/.roo/skills/python-dependency-mgmt/examples/dependency_mgmt.md +67 -0
- package/.roo/skills/python-security-skill/SKILL.md +56 -0
- package/.roo/skills/python-security-skill/examples/security.md +56 -0
- package/.roo/skills/self-signed-cert/SKILL.md +42 -0
- package/.roo/skills/self-signed-cert/scripts/generate-cert.ps1 +45 -0
- package/.roo/skills/self-signed-cert/scripts/generate-cert.sh +43 -0
- package/.roo/skills/skill-creator/SKILL.md +196 -0
- package/.roo/skills/skill-creator/references/output-patterns.md +82 -0
- package/.roo/skills/skill-creator/references/workflows.md +28 -0
- package/.roo/skills/skill-creator/scripts/init_skill.py +208 -0
- package/.roo/skills/skill-creator/scripts/package_skill.py +99 -0
- package/.roo/skills/skill-creator/scripts/quick_validate.py +113 -0
- package/.roo/skills/story-status-lookup/SKILL.md +78 -0
- package/.roo/skills/test-accompanied-development/SKILL.md +50 -0
- package/.roo/skills/test-generator/SKILL.md +65 -0
- package/.roo/skills/vercel-react-best-practices/SKILL.md +109 -0
- package/.roo/skills/verify-hardened-docker-skill/SKILL.md +442 -0
- package/.roo/skills/verify-hardened-docker-skill/scripts/verify-docker-hardening.sh +439 -0
- package/README.md +50 -3
- package/lib/agents.js +23 -0
- package/lib/bmad-extension/module-help.csv +8 -4
- package/lib/bmad-extension/skills/add-sprint/SKILL.md +126 -40
- package/lib/bmad-extension/skills/add-to-sprint/SKILL.md +116 -142
- package/lib/bmad-extension/skills/cleanup-done/.gitkeep +0 -0
- package/lib/bmad-extension/skills/cleanup-done/SKILL.md +159 -0
- package/lib/bmad-extension/skills/cleanup-done/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/create-bug-story/SKILL.md +75 -7
- package/lib/bmad-extension/skills/generate-backlog/SKILL.md +183 -0
- package/lib/bmad-extension/skills/generate-backlog/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/modify-sprint/SKILL.md +63 -0
- package/lib/bmad-extension/skills/prioritize-backlog/.gitkeep +0 -0
- package/lib/bmad-extension/skills/prioritize-backlog/SKILL.md +195 -0
- package/lib/bmad-extension/skills/prioritize-backlog/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/remove-from-sprint/.gitkeep +0 -0
- package/lib/bmad-extension/skills/remove-from-sprint/SKILL.md +163 -0
- package/lib/bmad-extension/skills/remove-from-sprint/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/sprint-status-view/SKILL.md +199 -138
- package/lib/bmad-extension/workflows/add-sprint/workflow.md +129 -39
- package/lib/bmad-extension/workflows/add-to-sprint/workflow.md +3 -205
- package/lib/bmad-extension/workflows/modify-sprint/workflow.md +5 -0
- package/lib/bmad-extension/workflows/sprint-status-view/workflow.md +3 -192
- package/package.json +4 -3
- package/test/roo-code-agent.test.js +166 -0
- package/test/roo-code-injection.test.js +172 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# JavaScript & TypeScript Documentation (JSDoc Style)
|
|
2
|
+
|
|
3
|
+
### File Header
|
|
4
|
+
```typescript
|
|
5
|
+
/**
|
|
6
|
+
* @file api-client.ts
|
|
7
|
+
* @description Centralized HTTP client with automatic retry and error handling.
|
|
8
|
+
* @author Antigravity / ma-agents
|
|
9
|
+
* @version 1.2.0
|
|
10
|
+
*/
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Method Documentation
|
|
14
|
+
```typescript
|
|
15
|
+
/**
|
|
16
|
+
* Fetches data from a specific endpoint with optional caching.
|
|
17
|
+
*
|
|
18
|
+
* @template T The expected type of the response data.
|
|
19
|
+
* @param {string} url The target URL (must be absolute).
|
|
20
|
+
* @param {RequestOptions} [options] Optional configuration for headers and timeouts.
|
|
21
|
+
* @returns {Promise<T>} A promise that resolves to the parsed JSON response.
|
|
22
|
+
* @throws {NetworkError} If the server is unreachable.
|
|
23
|
+
* @throws {ValidationError} If the response schema does not match T.
|
|
24
|
+
*/
|
|
25
|
+
async function fetchData<T>(url: string, options?: RequestOptions): Promise<T> {
|
|
26
|
+
// ...
|
|
27
|
+
}
|
|
28
|
+
```
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Python Documentation (Google/NumPy Style)
|
|
2
|
+
|
|
3
|
+
### File Header
|
|
4
|
+
Every module should start with a docstring that provides a high-level overview.
|
|
5
|
+
|
|
6
|
+
```python
|
|
7
|
+
"""
|
|
8
|
+
data_processor.py
|
|
9
|
+
~~~~~~~~~~~~~~~~~
|
|
10
|
+
Handles high-performance transformation of raw sensor data using NumPy.
|
|
11
|
+
|
|
12
|
+
:copyright: (c) 2026 by Antigravity.
|
|
13
|
+
:license: MIT, see LICENSE for more details.
|
|
14
|
+
"""
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Method Documentation
|
|
18
|
+
Preferred style is Google or NumPy style for readability and integration with tools like Sphinx.
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
def calculate_moving_average(data, window_size):
|
|
22
|
+
"""Calculates the moving average of a dataset.
|
|
23
|
+
|
|
24
|
+
This method uses a sliding window algorithm to smooth out volatility
|
|
25
|
+
in sensor inputs.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
data (list[float]): A list or array of float values to process.
|
|
29
|
+
window_size (int): The size of the averaging window (must be > 0).
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
float: The calculated moving average.
|
|
33
|
+
|
|
34
|
+
Raises:
|
|
35
|
+
ValueError: If data is empty or window_size is invalid.
|
|
36
|
+
|
|
37
|
+
Note:
|
|
38
|
+
This implementation assumes data is already cleaned.
|
|
39
|
+
"""
|
|
40
|
+
if not data or window_size <= 0:
|
|
41
|
+
raise ValueError("Invalid data or window_size")
|
|
42
|
+
# ... implementation
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Class Documentation
|
|
46
|
+
```python
|
|
47
|
+
class SignalFilter:
|
|
48
|
+
"""A collection of signal processing utilities.
|
|
49
|
+
|
|
50
|
+
Attributes:
|
|
51
|
+
sampling_rate (int): The frequency at which signals are sampled.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
def __init__(self, sampling_rate):
|
|
55
|
+
"""Initializes the SignalFilter with a specific sampling rate."""
|
|
56
|
+
self.sampling_rate = sampling_rate
|
|
57
|
+
```
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Code Review
|
|
3
|
+
description: Performs comprehensive code reviews with best practices
|
|
4
|
+
---
|
|
5
|
+
# Code Review
|
|
6
|
+
|
|
7
|
+
Perform comprehensive code reviews following industry best practices.
|
|
8
|
+
|
|
9
|
+
## What to Review
|
|
10
|
+
|
|
11
|
+
1. **Code Quality**: Readability, naming conventions, structure
|
|
12
|
+
2. **Best Practices**: Language-specific patterns, error handling, performance
|
|
13
|
+
3. **Security**: Common vulnerabilities (SQL injection, XSS, CSRF, etc.)
|
|
14
|
+
4. **Testing**: Coverage, edge cases, test quality
|
|
15
|
+
5. **Documentation**: Comments, API docs, clarity
|
|
16
|
+
|
|
17
|
+
## Review Process
|
|
18
|
+
|
|
19
|
+
- Analyze code for bugs and logical errors
|
|
20
|
+
- Check adherence to coding standards
|
|
21
|
+
- Identify security vulnerabilities
|
|
22
|
+
- Suggest refactoring opportunities
|
|
23
|
+
- Assess test coverage and documentation
|
|
24
|
+
|
|
25
|
+
## Output Format
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
## Code Review Summary
|
|
29
|
+
|
|
30
|
+
### Strengths
|
|
31
|
+
- [Positive aspects]
|
|
32
|
+
|
|
33
|
+
### Issues Found
|
|
34
|
+
- **[High/Medium/Low]** [Issue description]
|
|
35
|
+
- Location: [file:line]
|
|
36
|
+
- Fix: [recommendation]
|
|
37
|
+
|
|
38
|
+
### Suggestions
|
|
39
|
+
- [Improvements]
|
|
40
|
+
|
|
41
|
+
### Overall Assessment
|
|
42
|
+
[Summary and rating]
|
|
43
|
+
```
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Commit Message Generator
|
|
3
|
+
description: Generates conventional commit messages from code changes
|
|
4
|
+
---
|
|
5
|
+
# Commit Message Generator
|
|
6
|
+
|
|
7
|
+
Generate meaningful commit messages following Conventional Commits specification.
|
|
8
|
+
|
|
9
|
+
## Format
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
<type>(<scope>): <subject>
|
|
13
|
+
|
|
14
|
+
<body>
|
|
15
|
+
|
|
16
|
+
<footer>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Types
|
|
20
|
+
|
|
21
|
+
- `feat`: New feature
|
|
22
|
+
- `fix`: Bug fix
|
|
23
|
+
- `docs`: Documentation changes
|
|
24
|
+
- `style`: Code style/formatting
|
|
25
|
+
- `refactor`: Code refactoring
|
|
26
|
+
- `test`: Adding/updating tests
|
|
27
|
+
- `chore`: Maintenance tasks
|
|
28
|
+
- `perf`: Performance improvements
|
|
29
|
+
- `ci`: CI/CD changes
|
|
30
|
+
- `build`: Build system changes
|
|
31
|
+
- `revert`: Revert previous commit
|
|
32
|
+
|
|
33
|
+
## Guidelines
|
|
34
|
+
|
|
35
|
+
1. **Subject line** (max 50 chars):
|
|
36
|
+
- Use imperative mood ("Add" not "Added")
|
|
37
|
+
- Don't capitalize first letter
|
|
38
|
+
- No period at the end
|
|
39
|
+
|
|
40
|
+
2. **Body** (optional):
|
|
41
|
+
- Explain what and why, not how
|
|
42
|
+
- Wrap at 72 characters
|
|
43
|
+
|
|
44
|
+
3. **Footer** (optional):
|
|
45
|
+
- Breaking changes: `BREAKING CHANGE: description`
|
|
46
|
+
- Issue references: `Fixes #123`
|
|
47
|
+
|
|
48
|
+
## Examples
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
feat(auth): add JWT token refresh mechanism
|
|
52
|
+
|
|
53
|
+
Implement automatic token refresh to improve user experience
|
|
54
|
+
and reduce re-authentication prompts.
|
|
55
|
+
|
|
56
|
+
Fixes #456
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
fix(api): resolve memory leak in user service
|
|
61
|
+
|
|
62
|
+
The user cache was not being cleared properly, causing
|
|
63
|
+
memory to grow over time.
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
docs: update installation instructions
|
|
68
|
+
|
|
69
|
+
Add steps for Windows users and clarify dependency requirements.
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Process
|
|
73
|
+
|
|
74
|
+
1. Analyze the code changes
|
|
75
|
+
2. Determine the type of change
|
|
76
|
+
3. Identify the scope (component/module affected)
|
|
77
|
+
4. Write clear, concise subject
|
|
78
|
+
5. Add body if changes need explanation
|
|
79
|
+
6. Add footer for breaking changes or issue refs
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: C++ Best Practices
|
|
3
|
+
description: Comprehensive C++ coding standards covering naming conventions, modern C++ idioms (C++17/20/23), error handling, and build guidelines. Cross-references domain-specific C++ skills for deep-dives.
|
|
4
|
+
---
|
|
5
|
+
# C++ Best Practices
|
|
6
|
+
|
|
7
|
+
This skill establishes baseline C++ coding standards applicable to modern C++ projects (C++17/20/23). It covers naming conventions, code organization, memory management, error handling, modern idioms, and build guidelines. Domain-specific topics are handled by dedicated sibling skills — this skill provides the umbrella foundation and cross-references those skills where relevant.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 1. Naming Conventions
|
|
12
|
+
|
|
13
|
+
### Rule: Use consistent case styles by identifier type.
|
|
14
|
+
|
|
15
|
+
| Identifier | Convention | Example |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| Types (class, struct, enum, alias) | `PascalCase` | `UserAccount`, `ConnectionPool` |
|
|
18
|
+
| Functions and methods | `camelCase` | `getUserName()`, `processData()` |
|
|
19
|
+
| Variables (local, parameter) | `camelCase` | `userName`, `itemCount` |
|
|
20
|
+
| Member variables (private) | `camelCase_` with trailing underscore | `name_`, `bufferSize_` |
|
|
21
|
+
| Constants and enumerators | `UPPER_SNAKE_CASE` | `MAX_RETRY_COUNT`, `DEFAULT_TIMEOUT` |
|
|
22
|
+
| Macros | `UPPER_SNAKE_CASE` | `ASSERT_NOT_NULL`, `LOG_LEVEL` |
|
|
23
|
+
| Namespaces | `lowercase_snake_case` | `network::http`, `core::utils` |
|
|
24
|
+
| Template parameters | `PascalCase` | `template<typename ValueType>` |
|
|
25
|
+
| Files | `snake_case.cpp` / `snake_case.h` | `user_account.cpp`, `connection_pool.h` |
|
|
26
|
+
|
|
27
|
+
**Action:** Do not abbreviate unless the abbreviation is universally understood in the domain (e.g., `id`, `url`, `http`). Avoid single-letter names except for loop indices (`i`, `j`, `k`) and template parameters (`T`, `U`).
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 2. Code Organization
|
|
32
|
+
|
|
33
|
+
### Rule: One primary type per header file; name the file after the type.
|
|
34
|
+
|
|
35
|
+
**Action:**
|
|
36
|
+
- Place class declarations in `.h` files; place definitions in `.cpp` files.
|
|
37
|
+
- Use `#pragma once` at the top of every header (preferred over include guards in new code).
|
|
38
|
+
- Group headers: project headers first, then third-party, then standard library — each group separated by a blank line.
|
|
39
|
+
- Keep headers self-contained: every header must include what it needs to compile in isolation.
|
|
40
|
+
|
|
41
|
+
### Rule: Use namespaces to model the logical module hierarchy.
|
|
42
|
+
|
|
43
|
+
**Action:**
|
|
44
|
+
- Prefer deeply nested namespaces over flat ones: `namespace myapp::network::http { ... }`.
|
|
45
|
+
- Avoid `using namespace` in header files. Restrict `using namespace std;` to `.cpp` file scope if used at all.
|
|
46
|
+
- Use `inline namespace` only for versioning public APIs (e.g., `inline namespace v2`).
|
|
47
|
+
|
|
48
|
+
### Rule: Keep translation units small and focused.
|
|
49
|
+
|
|
50
|
+
**Action:**
|
|
51
|
+
- Limit headers to declarations and inline functions under ~20 lines.
|
|
52
|
+
- Move non-trivial inline logic into `.inl` files included at the bottom of the header.
|
|
53
|
+
- Use forward declarations in headers to reduce compilation dependencies.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 3. Memory Management
|
|
58
|
+
|
|
59
|
+
**Action:** Apply RAII (Resource Acquisition Is Initialization) for all resources. Never allocate resources without an owning object responsible for releasing them.
|
|
60
|
+
|
|
61
|
+
Key policies:
|
|
62
|
+
- Prefer stack allocation. Use heap allocation only when lifetime exceeds scope or size is dynamic.
|
|
63
|
+
- Use `std::make_unique<T>()` for exclusive ownership; `std::make_shared<T>()` only when shared ownership is truly required.
|
|
64
|
+
- Never use raw `new` or `delete` outside of a low-level container implementation.
|
|
65
|
+
- Use standard containers (`std::vector`, `std::string`, `std::array`) instead of raw arrays and buffers.
|
|
66
|
+
|
|
67
|
+
> For detailed memory management patterns, see the `cpp-memory-handling` skill if installed.
|
|
68
|
+
> It covers RAII, smart pointer selection, Rule of Zero/Five, and ownership transfer patterns.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 4. Modern C++ Idioms
|
|
73
|
+
|
|
74
|
+
### C++17
|
|
75
|
+
|
|
76
|
+
**Action:** Use these C++17 features where they improve clarity:
|
|
77
|
+
|
|
78
|
+
- **Structured bindings**: `auto [key, value] = myMap.begin()->first;` — prefer over `first`/`second`.
|
|
79
|
+
- **`std::optional<T>`**: Return optional values instead of `nullptr` sentinels or output parameters.
|
|
80
|
+
- **`std::variant<T...>`**: Model sum types explicitly instead of void pointers or inheritance hierarchies.
|
|
81
|
+
- **`if constexpr`**: Replace SFINAE with readable compile-time branching in templates.
|
|
82
|
+
- **Fold expressions**: Simplify variadic template expansions: `(args + ... + 0)`.
|
|
83
|
+
- **`std::filesystem`**: Use `std::filesystem::path` for all file path manipulation; never concatenate paths with string operations.
|
|
84
|
+
- **Class template argument deduction (CTAD)**: Write `std::pair p{1, "hello"s}` instead of `std::make_pair`.
|
|
85
|
+
|
|
86
|
+
### C++20
|
|
87
|
+
|
|
88
|
+
**Action:** Adopt C++20 features when targeting C++20 or later:
|
|
89
|
+
|
|
90
|
+
- **Concepts**: Constrain template parameters with `requires` clauses instead of relying on substitution failures.
|
|
91
|
+
```cpp
|
|
92
|
+
template<std::integral T>
|
|
93
|
+
T clamp(T value, T lo, T hi);
|
|
94
|
+
```
|
|
95
|
+
- **Ranges**: Replace hand-written loops over containers with range adaptors (`std::views::filter`, `std::views::transform`, `std::ranges::sort`).
|
|
96
|
+
- **`std::format`**: Replace `printf`/`sprintf`/`ostringstream` with `std::format("{} has {} items", name, count)`.
|
|
97
|
+
- **Three-way comparison (`<=>`)**: Define `operator<=>` to implement all comparison operators at once.
|
|
98
|
+
- **Coroutines**: Use for asynchronous I/O and generator patterns; avoid raw `co_await` boilerplate — prefer a library abstraction (e.g., cppcoro, Asio).
|
|
99
|
+
- **Modules**: New projects targeting C++20+ should plan for module adoption; existing headers remain valid but prefer named module interface units for new public APIs.
|
|
100
|
+
|
|
101
|
+
### C++23
|
|
102
|
+
|
|
103
|
+
**Action:** Use C++23 features when the toolchain supports them:
|
|
104
|
+
|
|
105
|
+
- **`std::expected<T, E>`**: Return `expected<Result, ErrorCode>` from functions that can fail, eliminating exception-based control flow for expected failures.
|
|
106
|
+
- **`std::print` / `std::println`**: Replace `std::cout` for formatted output.
|
|
107
|
+
- **Deducing `this`**: Use explicit object parameter `this` to eliminate CRTP boilerplate and write recursive lambdas cleanly.
|
|
108
|
+
- **`std::flat_map` / `std::flat_set`**: Prefer over `std::map`/`std::set` for small to medium sorted collections requiring cache-friendly iteration.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## 5. Const-Correctness
|
|
113
|
+
|
|
114
|
+
### Rule: Make everything const by default; relax only when mutation is required.
|
|
115
|
+
|
|
116
|
+
**Action:**
|
|
117
|
+
- Declare local variables `const auto` unless reassignment is needed.
|
|
118
|
+
- Mark member functions `const` whenever they do not modify observable state.
|
|
119
|
+
- Use `constexpr` for values and functions computable at compile-time.
|
|
120
|
+
- Pass large types by `const&`; pass cheap types (scalars, pointers, `string_view`) by value.
|
|
121
|
+
- Never return `const` by value from a function — it prevents move semantics.
|
|
122
|
+
|
|
123
|
+
> For detailed const-correctness policies, see the `cpp-const-correctness` skill if installed.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 6. Error Handling
|
|
128
|
+
|
|
129
|
+
### Rule: Choose an error-handling strategy per layer and apply it consistently.
|
|
130
|
+
|
|
131
|
+
| Context | Preferred Mechanism |
|
|
132
|
+
|---|---|
|
|
133
|
+
| Programmer errors (precondition violations) | `assert()` or contracts (C++26); never exceptions |
|
|
134
|
+
| Expected failures in library APIs | `std::expected<T, E>` (C++23) or error codes |
|
|
135
|
+
| Exceptional conditions that prevent normal flow | Exceptions (`std::runtime_error` hierarchy) |
|
|
136
|
+
| Async / coroutine code | Error channels in the coroutine framework |
|
|
137
|
+
|
|
138
|
+
**Action:**
|
|
139
|
+
- Mark functions that cannot throw `noexcept`. Destructors, move constructors, and swap functions MUST be `noexcept`.
|
|
140
|
+
- Catch exceptions by `const&` only: `catch (const std::exception& e)`.
|
|
141
|
+
- Never catch `...` (catch-all) except at top-level handlers or plugin boundaries.
|
|
142
|
+
- Do not use exceptions for control flow or expected failure paths — use `std::optional` or `std::expected` instead.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## 7. Class Design
|
|
147
|
+
|
|
148
|
+
### Rule: Follow the Rule of Zero.
|
|
149
|
+
|
|
150
|
+
**Action:**
|
|
151
|
+
- Design classes so that the compiler-generated special members (copy/move constructor, copy/move assignment, destructor) are correct by default.
|
|
152
|
+
- Use RAII members (smart pointers, standard containers) to make this automatic.
|
|
153
|
+
- If you must define any special member function, define all five (destructor, copy ctor, move ctor, copy assign, move assign) — the Rule of Five.
|
|
154
|
+
|
|
155
|
+
### Rule: Prefer composition over inheritance for code reuse.
|
|
156
|
+
|
|
157
|
+
**Action:**
|
|
158
|
+
- Use `public` inheritance only to model true "is-a" relationships with polymorphic behavior.
|
|
159
|
+
- Mark base class destructors `virtual` when the class is intended to be used polymorphically.
|
|
160
|
+
- Mark overriding methods `override`; mark non-overridable methods `final`.
|
|
161
|
+
- Prefer free functions over member functions for operations that do not require access to private state.
|
|
162
|
+
- Mark factory functions and pure query methods with `[[nodiscard]]` (C++17) to turn silent result-discard into a compiler warning.
|
|
163
|
+
|
|
164
|
+
> For detailed composition patterns and elimination of legacy C patterns, see the `cpp-modern-composition` skill if installed.
|
|
165
|
+
> For interface design contracts and strong typing, see the `cpp-robust-interfaces` skill if installed.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## 8. Concurrency
|
|
170
|
+
|
|
171
|
+
### Rule: Never share mutable state between threads without synchronization.
|
|
172
|
+
|
|
173
|
+
**Action:**
|
|
174
|
+
- Prefer task-based concurrency (`std::async`, thread pools) over raw `std::thread`. Always specify `std::launch::async` explicitly — `std::async` without a launch policy may run deferred (synchronously on the calling thread), which defeats the purpose of async execution.
|
|
175
|
+
- Protect shared data with `std::mutex`; always use `std::lock_guard` or `std::unique_lock` — never call `lock()`/`unlock()` manually.
|
|
176
|
+
- Declare data accessed from multiple threads as `std::atomic<T>` when appropriate (single-variable synchronization, counters, flags).
|
|
177
|
+
- Avoid `volatile` for inter-thread communication; use `std::atomic` instead.
|
|
178
|
+
|
|
179
|
+
> For detailed concurrency safety patterns, see the `cpp-concurrency-safety` skill if installed.
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## 9. Build and Compilation Guidelines
|
|
184
|
+
|
|
185
|
+
### Rule: Enable high-warning levels and treat warnings as errors.
|
|
186
|
+
|
|
187
|
+
**Action:**
|
|
188
|
+
- GCC/Clang: `-Wall -Wextra -Wpedantic -Wconversion -Wshadow -Werror`
|
|
189
|
+
- MSVC: `/W4 /WX`
|
|
190
|
+
- Do not disable warnings without an inline comment explaining the rationale.
|
|
191
|
+
|
|
192
|
+
### Rule: Use sanitizers during development and CI.
|
|
193
|
+
|
|
194
|
+
| Sanitizer | Flag (GCC/Clang) | Detects |
|
|
195
|
+
|---|---|---|
|
|
196
|
+
| AddressSanitizer | `-fsanitize=address` | Buffer overflows, use-after-free |
|
|
197
|
+
| UndefinedBehaviorSanitizer | `-fsanitize=undefined` | UB (integer overflow, null deref) |
|
|
198
|
+
| ThreadSanitizer | `-fsanitize=thread` | Data races |
|
|
199
|
+
|
|
200
|
+
**Action:** Enable at least `-fsanitize=address,undefined` in Debug and CI builds. Do not ship sanitizer builds.
|
|
201
|
+
|
|
202
|
+
### Rule: Set the C++ standard explicitly.
|
|
203
|
+
|
|
204
|
+
**Action:** Always specify `-std=c++17` (or higher) explicitly. Do not rely on compiler defaults, which differ across vendors.
|
|
205
|
+
|
|
206
|
+
> For CMake-specific build configuration patterns, see the `cmake-best-practices` skill if installed.
|
|
207
|
+
> It covers target-based CMake, `target_compile_options`, and compiler flag propagation.
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## 10. General Code Quality
|
|
212
|
+
|
|
213
|
+
### Rule: Prefer clarity over cleverness.
|
|
214
|
+
|
|
215
|
+
**Action:**
|
|
216
|
+
- Write code for the next reader, not the compiler. Compilers optimize well; humans struggle with obfuscation.
|
|
217
|
+
- Extract magic numbers into named `constexpr` constants.
|
|
218
|
+
- Prefer algorithms from `<algorithm>` and `<numeric>` over hand-written loops.
|
|
219
|
+
- Limit function length to what fits on one screen (~50 lines). If longer, extract named helper functions.
|
|
220
|
+
- Avoid deep nesting (more than 3 levels). Use early-return and guard clauses to flatten control flow.
|
|
221
|
+
|
|
222
|
+
### Rule: Use `auto` judiciously.
|
|
223
|
+
|
|
224
|
+
**Action:**
|
|
225
|
+
- Use `auto` when the type is verbose and already clear from context (e.g., iterators, lambda types, CTAD).
|
|
226
|
+
- Do not use `auto` when the type communicates intent and is not immediately obvious from the right-hand side.
|
|
227
|
+
- Always specify `auto&` or `const auto&` for range-for loops over containers of non-trivial types.
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Resources
|
|
232
|
+
|
|
233
|
+
- [Naming and Organization Examples](examples/naming-and-organization.md)
|
|
234
|
+
- [Modern C++ Idioms Examples](examples/modern-idioms.md)
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# Modern C++ Idioms Examples
|
|
2
|
+
|
|
3
|
+
## C++17: Structured Bindings and std::optional
|
|
4
|
+
|
|
5
|
+
```cpp
|
|
6
|
+
#include <map>
|
|
7
|
+
#include <optional>
|
|
8
|
+
#include <string>
|
|
9
|
+
|
|
10
|
+
// Structured bindings — prefer over .first/.second
|
|
11
|
+
std::map<std::string, int> scores = {{"Alice", 95}, {"Bob", 87}};
|
|
12
|
+
for (const auto& [name, score] : scores) {
|
|
13
|
+
// name and score are directly named — no .first/.second
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// std::optional — no more nullptr sentinels or bool out-parameters
|
|
17
|
+
std::optional<std::string> findUser(int id) {
|
|
18
|
+
if (id == 42) return "Alice";
|
|
19
|
+
return std::nullopt; // Not found — explicit, type-safe
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
void example() {
|
|
23
|
+
if (const auto user = findUser(42); user.has_value()) {
|
|
24
|
+
// C++17 if-with-initializer keeps 'user' scoped tightly
|
|
25
|
+
doSomethingWith(*user);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## C++17: std::variant for Sum Types
|
|
31
|
+
|
|
32
|
+
```cpp
|
|
33
|
+
#include <variant>
|
|
34
|
+
#include <string>
|
|
35
|
+
|
|
36
|
+
struct Success { std::string message; };
|
|
37
|
+
struct NotFound { int id; };
|
|
38
|
+
struct PermissionDenied { std::string reason; };
|
|
39
|
+
|
|
40
|
+
using LookupResult = std::variant<Success, NotFound, PermissionDenied>;
|
|
41
|
+
|
|
42
|
+
LookupResult lookup(int id) {
|
|
43
|
+
if (id == 0) return NotFound{id};
|
|
44
|
+
if (id < 0) return PermissionDenied{"negative ids reserved"};
|
|
45
|
+
return Success{"found item " + std::to_string(id)};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
void handle(const LookupResult& result) {
|
|
49
|
+
std::visit([](const auto& v) {
|
|
50
|
+
using T = std::decay_t<decltype(v)>;
|
|
51
|
+
if constexpr (std::is_same_v<T, Success>) {
|
|
52
|
+
log(v.message);
|
|
53
|
+
} else if constexpr (std::is_same_v<T, NotFound>) {
|
|
54
|
+
log("not found: " + std::to_string(v.id));
|
|
55
|
+
} else {
|
|
56
|
+
log("denied: " + v.reason);
|
|
57
|
+
}
|
|
58
|
+
}, result);
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## C++20: Concepts
|
|
63
|
+
|
|
64
|
+
```cpp
|
|
65
|
+
#include <concepts>
|
|
66
|
+
#include <iostream>
|
|
67
|
+
#include <vector>
|
|
68
|
+
|
|
69
|
+
// Before concepts: SFINAE was required — hard to read and debug
|
|
70
|
+
// After concepts: clear, readable constraints
|
|
71
|
+
|
|
72
|
+
template<std::integral T>
|
|
73
|
+
T clamp(T value, T lo, T hi) {
|
|
74
|
+
return std::max(lo, std::min(value, hi));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Custom concept
|
|
78
|
+
template<typename T>
|
|
79
|
+
concept Printable = requires(T t) {
|
|
80
|
+
{ t.toString() } -> std::convertible_to<std::string>;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
template<Printable T>
|
|
84
|
+
void printAll(const std::vector<T>& items) {
|
|
85
|
+
for (const auto& item : items) {
|
|
86
|
+
std::cout << item.toString() << '\n';
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## C++20: Ranges
|
|
92
|
+
|
|
93
|
+
```cpp
|
|
94
|
+
#include <algorithm>
|
|
95
|
+
#include <iostream>
|
|
96
|
+
#include <ranges>
|
|
97
|
+
#include <vector>
|
|
98
|
+
#include <string>
|
|
99
|
+
|
|
100
|
+
void modernRanges() {
|
|
101
|
+
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
|
102
|
+
|
|
103
|
+
// Chain range adaptors — lazy, composable, readable
|
|
104
|
+
auto evenSquares = numbers
|
|
105
|
+
| std::views::filter([](int n) { return n % 2 == 0; })
|
|
106
|
+
| std::views::transform([](int n) { return n * n; });
|
|
107
|
+
|
|
108
|
+
// Iterate result without materializing an intermediate container
|
|
109
|
+
for (int v : evenSquares) {
|
|
110
|
+
std::cout << v << '\n'; // 4 16 36 64 100
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Sorting with ranges — no begin/end iterator boilerplate
|
|
114
|
+
std::vector<std::string> names = {"Charlie", "Alice", "Bob"};
|
|
115
|
+
std::ranges::sort(names);
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## C++23: std::expected for Error Handling
|
|
120
|
+
|
|
121
|
+
```cpp
|
|
122
|
+
#include <expected>
|
|
123
|
+
#include <string>
|
|
124
|
+
#include <fstream>
|
|
125
|
+
|
|
126
|
+
enum class ParseError { InvalidFormat, EmptyInput, Overflow };
|
|
127
|
+
|
|
128
|
+
// Return expected<T, E> instead of throwing for anticipated failures
|
|
129
|
+
std::expected<int, ParseError> parsePositiveInt(std::string_view input) {
|
|
130
|
+
if (input.empty()) return std::unexpected(ParseError::EmptyInput);
|
|
131
|
+
int result = 0;
|
|
132
|
+
for (char c : input) {
|
|
133
|
+
if (c < '0' || c > '9') return std::unexpected(ParseError::InvalidFormat);
|
|
134
|
+
result = result * 10 + (c - '0');
|
|
135
|
+
if (result < 0) return std::unexpected(ParseError::Overflow);
|
|
136
|
+
}
|
|
137
|
+
return result;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
void usage() {
|
|
141
|
+
const auto result = parsePositiveInt("123");
|
|
142
|
+
if (result) {
|
|
143
|
+
std::println("Parsed: {}", *result);
|
|
144
|
+
} else {
|
|
145
|
+
// Handle error without try/catch — expected path, not exceptional
|
|
146
|
+
switch (result.error()) {
|
|
147
|
+
case ParseError::InvalidFormat: std::println("invalid format"); break;
|
|
148
|
+
case ParseError::EmptyInput: std::println("empty input"); break;
|
|
149
|
+
case ParseError::Overflow: std::println("overflow"); break;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Class Design: Rule of Zero
|
|
156
|
+
|
|
157
|
+
```cpp
|
|
158
|
+
#include <memory>
|
|
159
|
+
#include <string>
|
|
160
|
+
#include <vector>
|
|
161
|
+
|
|
162
|
+
// Good: Rule of Zero — all members manage themselves
|
|
163
|
+
class Document {
|
|
164
|
+
public:
|
|
165
|
+
explicit Document(std::string title) : title_(std::move(title)) {}
|
|
166
|
+
|
|
167
|
+
void addSection(std::string content) {
|
|
168
|
+
sections_.emplace_back(std::move(content));
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private:
|
|
172
|
+
std::string title_; // manages its own lifetime
|
|
173
|
+
std::vector<std::string> sections_; // manages its own lifetime
|
|
174
|
+
// No destructor, no copy/move definitions needed — compiler generates correct ones
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// Bad: unnecessary manual resource management
|
|
178
|
+
class BadDocument {
|
|
179
|
+
public:
|
|
180
|
+
BadDocument(const char* title) {
|
|
181
|
+
title_ = new char[strlen(title) + 1]; // raw new — avoid this
|
|
182
|
+
strcpy(title_, title);
|
|
183
|
+
}
|
|
184
|
+
~BadDocument() { delete[] title_; } // manual cleanup — fragile
|
|
185
|
+
// Must also define copy ctor, copy assign, move ctor, move assign correctly...
|
|
186
|
+
private:
|
|
187
|
+
char* title_;
|
|
188
|
+
};
|
|
189
|
+
```
|