ma-agents 2.20.3 → 2.22.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.
Files changed (149) hide show
  1. package/.opencode/skills/.ma-agents.json +241 -0
  2. package/.opencode/skills/MANIFEST.yaml +254 -0
  3. package/.opencode/skills/ai-audit-trail/SKILL.md +23 -0
  4. package/.opencode/skills/auto-bug-detection/SKILL.md +169 -0
  5. package/.opencode/skills/cmake-best-practices/SKILL.md +64 -0
  6. package/.opencode/skills/cmake-best-practices/examples/cmake.md +59 -0
  7. package/.opencode/skills/code-documentation/SKILL.md +57 -0
  8. package/.opencode/skills/code-documentation/examples/cpp.md +29 -0
  9. package/.opencode/skills/code-documentation/examples/csharp.md +28 -0
  10. package/.opencode/skills/code-documentation/examples/javascript_typescript.md +28 -0
  11. package/.opencode/skills/code-documentation/examples/python.md +57 -0
  12. package/.opencode/skills/code-review/SKILL.md +43 -0
  13. package/.opencode/skills/commit-message/SKILL.md +79 -0
  14. package/.opencode/skills/cpp-best-practices/SKILL.md +234 -0
  15. package/.opencode/skills/cpp-best-practices/examples/modern-idioms.md +189 -0
  16. package/.opencode/skills/cpp-best-practices/examples/naming-and-organization.md +102 -0
  17. package/.opencode/skills/cpp-concurrency-safety/SKILL.md +60 -0
  18. package/.opencode/skills/cpp-concurrency-safety/examples/concurrency.md +73 -0
  19. package/.opencode/skills/cpp-const-correctness/SKILL.md +63 -0
  20. package/.opencode/skills/cpp-const-correctness/examples/const_correctness.md +54 -0
  21. package/.opencode/skills/cpp-memory-handling/SKILL.md +42 -0
  22. package/.opencode/skills/cpp-memory-handling/examples/modern-cpp.md +49 -0
  23. package/.opencode/skills/cpp-memory-handling/examples/smart-pointers.md +46 -0
  24. package/.opencode/skills/cpp-modern-composition/SKILL.md +64 -0
  25. package/.opencode/skills/cpp-modern-composition/examples/composition.md +51 -0
  26. package/.opencode/skills/cpp-robust-interfaces/SKILL.md +55 -0
  27. package/.opencode/skills/cpp-robust-interfaces/examples/interfaces.md +56 -0
  28. package/.opencode/skills/create-hardened-docker-skill/SKILL.md +637 -0
  29. package/.opencode/skills/create-hardened-docker-skill/scripts/create-all.sh +489 -0
  30. package/.opencode/skills/csharp-best-practices/SKILL.md +278 -0
  31. package/.opencode/skills/docker-hardening-verification/SKILL.md +28 -0
  32. package/.opencode/skills/docker-hardening-verification/scripts/verify-hardening.sh +39 -0
  33. package/.opencode/skills/docker-image-signing/SKILL.md +28 -0
  34. package/.opencode/skills/docker-image-signing/scripts/sign-image.sh +33 -0
  35. package/.opencode/skills/document-revision-history/SKILL.md +104 -0
  36. package/.opencode/skills/git-workflow-skill/SKILL.md +194 -0
  37. package/.opencode/skills/git-workflow-skill/hooks/commit-msg +61 -0
  38. package/.opencode/skills/git-workflow-skill/hooks/pre-commit +38 -0
  39. package/.opencode/skills/git-workflow-skill/hooks/prepare-commit-msg +56 -0
  40. package/.opencode/skills/git-workflow-skill/scripts/finish-feature.sh +192 -0
  41. package/.opencode/skills/git-workflow-skill/scripts/install-hooks.sh +55 -0
  42. package/.opencode/skills/git-workflow-skill/scripts/start-feature.sh +110 -0
  43. package/.opencode/skills/git-workflow-skill/scripts/validate-workflow.sh +229 -0
  44. package/.opencode/skills/js-ts-dependency-mgmt/SKILL.md +49 -0
  45. package/.opencode/skills/js-ts-dependency-mgmt/examples/dependency_mgmt.md +60 -0
  46. package/.opencode/skills/js-ts-security-skill/SKILL.md +64 -0
  47. package/.opencode/skills/js-ts-security-skill/scripts/verify-security.sh +136 -0
  48. package/.opencode/skills/logging-best-practices/SKILL.md +50 -0
  49. package/.opencode/skills/logging-best-practices/examples/cpp.md +36 -0
  50. package/.opencode/skills/logging-best-practices/examples/csharp.md +49 -0
  51. package/.opencode/skills/logging-best-practices/examples/javascript.md +77 -0
  52. package/.opencode/skills/logging-best-practices/examples/python.md +57 -0
  53. package/.opencode/skills/logging-best-practices/references/logging-standards.md +29 -0
  54. package/.opencode/skills/open-presentation/SKILL.md +35 -0
  55. package/.opencode/skills/opentelemetry-best-practices/SKILL.md +34 -0
  56. package/.opencode/skills/opentelemetry-best-practices/examples/go.md +32 -0
  57. package/.opencode/skills/opentelemetry-best-practices/examples/javascript.md +58 -0
  58. package/.opencode/skills/opentelemetry-best-practices/examples/python.md +37 -0
  59. package/.opencode/skills/opentelemetry-best-practices/references/otel-standards.md +37 -0
  60. package/.opencode/skills/python-best-practices/SKILL.md +385 -0
  61. package/.opencode/skills/python-dependency-mgmt/SKILL.md +42 -0
  62. package/.opencode/skills/python-dependency-mgmt/examples/dependency_mgmt.md +67 -0
  63. package/.opencode/skills/python-security-skill/SKILL.md +56 -0
  64. package/.opencode/skills/python-security-skill/examples/security.md +56 -0
  65. package/.opencode/skills/self-signed-cert/SKILL.md +42 -0
  66. package/.opencode/skills/self-signed-cert/scripts/generate-cert.ps1 +45 -0
  67. package/.opencode/skills/self-signed-cert/scripts/generate-cert.sh +43 -0
  68. package/.opencode/skills/skill-creator/SKILL.md +196 -0
  69. package/.opencode/skills/skill-creator/references/output-patterns.md +82 -0
  70. package/.opencode/skills/skill-creator/references/workflows.md +28 -0
  71. package/.opencode/skills/skill-creator/scripts/init_skill.py +208 -0
  72. package/.opencode/skills/skill-creator/scripts/package_skill.py +99 -0
  73. package/.opencode/skills/skill-creator/scripts/quick_validate.py +113 -0
  74. package/.opencode/skills/story-status-lookup/SKILL.md +78 -0
  75. package/.opencode/skills/test-accompanied-development/SKILL.md +50 -0
  76. package/.opencode/skills/test-generator/SKILL.md +65 -0
  77. package/.opencode/skills/vercel-react-best-practices/SKILL.md +109 -0
  78. package/.opencode/skills/verify-hardened-docker-skill/SKILL.md +442 -0
  79. package/.opencode/skills/verify-hardened-docker-skill/scripts/verify-docker-hardening.sh +439 -0
  80. package/AiAudit.md +5 -0
  81. package/QUICK_START.md +11 -5
  82. package/README.md +52 -1
  83. package/bin/cli.js +31 -4
  84. package/docs/BMAD_AI_Development_Training.pptx +0 -0
  85. package/docs/technical-notes/context-persistence-research.md +434 -0
  86. package/docs/technical-notes/enforcement-hooks-research.md +415 -0
  87. package/lib/agents.js +34 -0
  88. package/lib/bmad-extension/agents/bmm-architect.customize.yaml +5 -0
  89. package/lib/bmad-extension/agents/bmm-bmad-master.customize.yaml +5 -0
  90. package/lib/bmad-extension/agents/bmm-cyber.customize.yaml +30 -0
  91. package/lib/bmad-extension/agents/bmm-dev.customize.yaml +5 -0
  92. package/lib/bmad-extension/agents/bmm-devops.customize.yaml +30 -0
  93. package/lib/bmad-extension/agents/bmm-mil498.customize.yaml +42 -0
  94. package/lib/bmad-extension/agents/bmm-pm.customize.yaml +5 -0
  95. package/lib/bmad-extension/agents/bmm-qa.customize.yaml +5 -0
  96. package/lib/bmad-extension/agents/bmm-sm.customize.yaml +5 -0
  97. package/lib/bmad-extension/agents/bmm-sre.customize.yaml +30 -0
  98. package/lib/bmad-extension/agents/bmm-tech-writer.customize.yaml +5 -0
  99. package/lib/bmad-extension/agents/bmm-ux-designer.customize.yaml +5 -0
  100. package/lib/bmad-extension/module-help.csv +7 -0
  101. package/lib/bmad-extension/module.yaml +3 -0
  102. package/lib/bmad-extension/workflows/add-sprint/workflow.md +112 -0
  103. package/lib/bmad-extension/workflows/add-to-sprint/workflow.md +206 -0
  104. package/lib/bmad-extension/workflows/create-bug-story/workflow.md +186 -0
  105. package/lib/bmad-extension/workflows/modify-sprint/workflow.md +250 -0
  106. package/lib/bmad-extension/workflows/project-context-expansion/workflow.md +229 -0
  107. package/lib/bmad-extension/workflows/sprint-status-view/workflow.md +193 -0
  108. package/lib/bmad.js +168 -36
  109. package/lib/hooks/claude-code/verify-manifest.js +56 -0
  110. package/lib/installer.js +282 -1
  111. package/lib/methodology/BMAD_AI_Development_Training.pptx +0 -0
  112. package/lib/methodology/version.json +7 -0
  113. package/lib/skill-authoring.js +732 -0
  114. package/lib/templates/project-context.template.md +47 -0
  115. package/opencode.json +8 -0
  116. package/package.json +2 -2
  117. package/skills/auto-bug-detection/SKILL.md +165 -0
  118. package/skills/auto-bug-detection/skill.json +8 -0
  119. package/skills/code-review/SKILL.md +40 -0
  120. package/skills/cpp-best-practices/SKILL.md +230 -0
  121. package/skills/cpp-best-practices/examples/modern-idioms.md +189 -0
  122. package/skills/cpp-best-practices/examples/naming-and-organization.md +102 -0
  123. package/skills/cpp-best-practices/skill.json +25 -0
  124. package/skills/csharp-best-practices/SKILL.md +274 -0
  125. package/skills/csharp-best-practices/skill.json +23 -0
  126. package/skills/git-workflow-skill/skill.json +1 -1
  127. package/skills/open-presentation/SKILL.md +31 -0
  128. package/skills/open-presentation/skill.json +11 -0
  129. package/skills/python-best-practices/SKILL.md +381 -0
  130. package/skills/python-best-practices/skill.json +26 -0
  131. package/skills/story-status-lookup/SKILL.md +74 -0
  132. package/skills/story-status-lookup/skill.json +8 -0
  133. package/test/agent-injection-strategy.test.js +13 -7
  134. package/test/bmad-extension.test.js +237 -0
  135. package/test/bmad-output-policy.test.js +119 -0
  136. package/test/build-bmad-args.test.js +361 -0
  137. package/test/create-agent.test.js +232 -0
  138. package/test/enforcement-hooks.test.js +324 -0
  139. package/test/generate-project-context.test.js +337 -0
  140. package/test/integration-verification.test.js +402 -0
  141. package/test/opencode-agent.test.js +150 -0
  142. package/test/opencode-json-error.test.js +260 -0
  143. package/test/opencode-json-injection.test.js +256 -0
  144. package/test/opencode-json-merge.test.js +299 -0
  145. package/test/skill-authoring.test.js +272 -0
  146. package/test/skill-customize-agent.test.js +253 -0
  147. package/test/skill-mandatory.test.js +235 -0
  148. package/test/skill-validation.test.js +378 -0
  149. package/test/yes-flag.test.js +1 -1
@@ -0,0 +1,381 @@
1
+ # Python Best Practices
2
+
3
+ Coding standards for modern Python (3.10+). This skill covers language-level patterns, type hinting, async conventions, and packaging. For security and dependency hardening, see the cross-referenced skills at the end of this document.
4
+
5
+ ---
6
+
7
+ ## 1. Naming Conventions (PEP 8)
8
+
9
+ **Rule:** Use consistent naming to maximize readability and tooling compatibility.
10
+
11
+ | Element | Convention | Example |
12
+ |---------|-----------|---------|
13
+ | Module / package | `snake_case` | `order_service`, `user_auth` |
14
+ | Function / method | `snake_case` | `get_customer()`, `parse_response()` |
15
+ | Variable | `snake_case` | `customer_count`, `is_active` |
16
+ | Class | `PascalCase` | `CustomerService`, `OrderItem` |
17
+ | Exception | `PascalCase` + `Error`/`Exception` | `NotFoundError`, `ValidationException` |
18
+ | Constant | `UPPER_SNAKE_CASE` | `MAX_RETRY_COUNT`, `DEFAULT_TIMEOUT` |
19
+ | Type alias | `PascalCase` | `CustomerList`, `JsonPayload` |
20
+ | Private identifier | leading `_` | `_internal_helper()`, `_cache` |
21
+ | Dunder / magic | leading and trailing `__` | `__init__`, `__repr__` |
22
+
23
+ - Do not abbreviate names unless the abbreviation is universally understood in the domain (`url`, `id`, `db`).
24
+ - Avoid single-letter names except for short-lived loop indices (`i`, `j`) or mathematical variables.
25
+
26
+ ---
27
+
28
+ ## 2. Code Organization
29
+
30
+ **Rule:** Keep modules focused; make boundaries explicit via `__all__`.
31
+
32
+ - One logical concept per module; group related modules into packages with `__init__.py`.
33
+ - Declare `__all__` in any module intended for public consumption to control the exported API.
34
+ - Standard import order (enforced by `ruff`): stdlib → third-party → local. One blank line between each group.
35
+ - Use absolute imports; avoid relative imports except within a tightly coupled sub-package.
36
+
37
+ ```python
38
+ # __init__.py — explicit public surface
39
+ from .service import CustomerService
40
+ from .models import Customer, Address
41
+
42
+ __all__ = ["CustomerService", "Customer", "Address"]
43
+ ```
44
+
45
+ ---
46
+
47
+ ## 3. Type Hinting (3.10+)
48
+
49
+ **Rule:** Annotate all public function signatures and module-level variables. Use modern syntax.
50
+
51
+ ### 3.1 Modern Syntax Table
52
+
53
+ | Pattern | Pre-3.10 (avoid) | Modern 3.10+ (use) |
54
+ |---------|-----------------|-------------------|
55
+ | Union types | `Union[str, int]` | `str \| int` |
56
+ | Optional | `Optional[str]` | `str \| None` |
57
+ | List | `List[str]` | `list[str]` |
58
+ | Dict | `Dict[str, int]` | `dict[str, int]` |
59
+ | Tuple | `Tuple[str, ...]` | `tuple[str, ...]` |
60
+ | Set | `Set[int]` | `set[int]` |
61
+ | Type alias (3.12+) | `MyType = list[str]` | `type MyType = list[str]` |
62
+ | Callable | `Callable[[int], str]` | `Callable[[int], str]` (unchanged) |
63
+
64
+ ### 3.2 Advanced Typing Constructs
65
+
66
+ - **`TypeAlias`** (3.10): use for readability when the alias is used in multiple places but you cannot yet use the `type` statement.
67
+ - **`TypeVar`**: constrain generic functions to a family of types.
68
+ - **`ParamSpec`** (3.10): preserve parameter types in higher-order functions and decorators.
69
+ - **`Protocol`**: define structural (duck-typed) interfaces; prefer over ABC for external or loosely coupled types.
70
+ - **`TypeGuard`** (3.10): narrow types in user-defined type guard functions.
71
+ - **`Self`** (3.11): annotate methods that return the instance's own type (replaces `TypeVar("T", bound="MyClass")`).
72
+
73
+ ```python
74
+ from typing import TypeVar, ParamSpec, Protocol, TypeGuard
75
+ from typing import Self # 3.11+
76
+
77
+ T = TypeVar("T")
78
+ P = ParamSpec("P")
79
+
80
+ class Comparable(Protocol):
81
+ def __lt__(self, other: Self) -> bool: ...
82
+
83
+ def is_string_list(val: list[object]) -> TypeGuard[list[str]]:
84
+ return all(isinstance(x, str) for x in val)
85
+ ```
86
+
87
+ ### 3.3 Variable Annotations
88
+
89
+ Annotate module-level and class-level variables; omit annotations for obvious local assignments.
90
+
91
+ ```python
92
+ # Module-level
93
+ MAX_CONNECTIONS: int = 100
94
+ _cache: dict[str, bytes] = {}
95
+
96
+ # Class-level (with __slots__ for memory efficiency)
97
+ class Point:
98
+ __slots__ = ("x", "y")
99
+ x: float
100
+ y: float
101
+
102
+ def __init__(self, x: float, y: float) -> None:
103
+ self.x = x
104
+ self.y = y
105
+ ```
106
+
107
+ ---
108
+
109
+ ## 4. Modern Python Patterns
110
+
111
+ ### 4.1 Structural Pattern Matching (3.10)
112
+
113
+ Use `match/case` to replace complex `if/elif` chains on structured data.
114
+
115
+ ```python
116
+ def handle_event(event: dict) -> str:
117
+ match event:
118
+ case {"type": "click", "button": button}:
119
+ return f"Clicked {button}"
120
+ case {"type": "keypress", "key": key} if key.isalpha():
121
+ return f"Key pressed: {key}"
122
+ case {"type": "resize", "width": w, "height": h}:
123
+ return f"Resized to {w}x{h}"
124
+ case _:
125
+ return "Unknown event"
126
+ ```
127
+
128
+ Prefer `match/case` over `isinstance` chains when dispatching on data shape; avoid it for simple boolean conditions.
129
+
130
+ ### 4.2 Exception Groups and `except*` (3.11)
131
+
132
+ `ExceptionGroup` allows multiple unrelated exceptions to propagate together; `except*` handles them selectively.
133
+
134
+ ```python
135
+ import asyncio
136
+
137
+ async def gather_tasks() -> None:
138
+ async with asyncio.TaskGroup() as tg:
139
+ tg.create_task(fetch_user())
140
+ tg.create_task(fetch_orders())
141
+ # TaskGroup raises ExceptionGroup if any task fails
142
+
143
+ try:
144
+ await gather_tasks()
145
+ except* ValueError as eg:
146
+ for exc in eg.exceptions:
147
+ print(f"Validation error: {exc}")
148
+ except* IOError as eg:
149
+ for exc in eg.exceptions:
150
+ print(f"IO error: {exc}")
151
+ ```
152
+
153
+ ### 4.3 F-String Improvements (3.12)
154
+
155
+ 3.12 removes restrictions on f-string content: nested quotes, backslashes, and complex expressions are now valid.
156
+
157
+ ```python
158
+ # 3.12: nested quotes and backslashes inside f-strings
159
+ name = "world"
160
+ msg = f"Hello, {name!r}"
161
+ path = f"{'\\'.join(['a', 'b', 'c'])}" # backslash inside f-string (3.12+)
162
+ ```
163
+
164
+ ### 4.4 Walrus Operator (`:=`)
165
+
166
+ Use assignment expressions to eliminate redundant calls in comprehensions and loops.
167
+
168
+ ```python
169
+ # With walrus — single call
170
+ if result := compute_expensive():
171
+ process(result)
172
+
173
+ # In comprehension — filter and use in one expression
174
+ filtered = [cleaned for raw in records if (cleaned := clean(raw))]
175
+ ```
176
+
177
+ Use sparingly; prefer clarity over brevity when the expression becomes hard to read.
178
+
179
+ ### 4.5 `__slots__` Usage
180
+
181
+ Declare `__slots__` on data-heavy classes to reduce per-instance memory by 30-50%.
182
+
183
+ ```python
184
+ class Vector:
185
+ __slots__ = ("x", "y", "z")
186
+
187
+ def __init__(self, x: float, y: float, z: float) -> None:
188
+ self.x, self.y, self.z = x, y, z
189
+ ```
190
+
191
+ Do not use `__slots__` on classes intended to be subclassed without explicit slot coordination.
192
+
193
+ ### 4.6 Dataclasses vs attrs vs Pydantic
194
+
195
+ | Tool | When to use |
196
+ |------|-------------|
197
+ | `dataclasses` (stdlib) | Simple data containers; no validation; no serialization needed |
198
+ | `attrs` | More control than dataclasses; validators, converters, `__slots__` automation |
199
+ | `Pydantic v2` | External data (API requests, config files); runtime validation and JSON serialization |
200
+
201
+ - Use `@dataclass(frozen=True, slots=True)` for immutable value objects.
202
+ - Use Pydantic `BaseModel` at system boundaries (HTTP, config); avoid deep inside the domain layer.
203
+
204
+ ```python
205
+ from dataclasses import dataclass
206
+
207
+ @dataclass(frozen=True, slots=True)
208
+ class Money:
209
+ amount: int # in cents
210
+ currency: str
211
+
212
+ def __post_init__(self) -> None:
213
+ if self.amount < 0:
214
+ raise ValueError("Amount must be non-negative")
215
+ ```
216
+
217
+ ### 4.7 Modern Stdlib Additions
218
+
219
+ **`StrEnum` (3.11+):** Combine enum membership with string behavior — no need for `.value` in comparisons or string formatting.
220
+
221
+ ```python
222
+ from enum import StrEnum
223
+
224
+ class Color(StrEnum):
225
+ RED = "red"
226
+ GREEN = "green"
227
+ BLUE = "blue"
228
+
229
+ assert Color.RED == "red" # True — no .value needed
230
+ print(f"Color: {Color.GREEN}") # "Color: green"
231
+ ```
232
+
233
+ **`tomllib` (3.11+ standard library):** Read TOML files without third-party dependencies; write via `tomli_w` or `tomllib` write support in 3.13+.
234
+
235
+ ```python
236
+ import tomllib
237
+
238
+ with open("pyproject.toml", "rb") as f: # must open in binary mode
239
+ config = tomllib.load(f)
240
+
241
+ version = config["project"]["version"]
242
+ ```
243
+
244
+ **`@override` decorator (3.12+, `typing`):** Explicitly mark methods that override a base-class method; type checkers flag mismatches (wrong signature, missing base method).
245
+
246
+ ```python
247
+ from typing import override
248
+
249
+ class Base:
250
+ def process(self, data: str) -> str:
251
+ return data
252
+
253
+ class Child(Base):
254
+ @override
255
+ def process(self, data: str) -> str: # type checker verifies this overrides Base.process
256
+ return data.strip()
257
+ ```
258
+
259
+ Use `@override` on every intentional override; it serves as both documentation and a static-analysis safety net.
260
+
261
+ ---
262
+
263
+ ## 5. Async Patterns
264
+
265
+ **Rule:** Use `asyncio` conventions consistently; never mix sync-blocking calls into async code paths.
266
+
267
+ - Prefer `async def` for I/O-bound functions; use `asyncio.to_thread()` to run blocking code in a thread pool.
268
+ - Use `async for` and `async with` for async iteration and context management.
269
+ - Use `asyncio.TaskGroup` (3.11) over `asyncio.gather` for structured concurrency with proper error propagation.
270
+ - Never call `asyncio.sleep(0)` in a busy loop — use proper awaitable primitives.
271
+ - Avoid mixing `asyncio.run()` inside an already-running event loop; use `asyncio.get_event_loop().run_until_complete()` only in legacy contexts.
272
+
273
+ ```python
274
+ import asyncio
275
+ from pathlib import Path
276
+
277
+ async def fetch_all(urls: list[str]) -> list[bytes]:
278
+ async with asyncio.TaskGroup() as tg:
279
+ tasks = [tg.create_task(fetch(url)) for url in urls]
280
+ return [t.result() for t in tasks]
281
+
282
+ async def read_file_async(path: str) -> str:
283
+ # Run blocking I/O in a thread pool — pass callable, not result
284
+ return await asyncio.to_thread(Path(path).read_text)
285
+ ```
286
+
287
+ ---
288
+
289
+ ## 6. Packaging Best Practices
290
+
291
+ **Rule:** Use `pyproject.toml` as the single configuration file; use `src/` layout.
292
+
293
+ ### 6.1 Project Layout
294
+
295
+ ```
296
+ my-project/
297
+ src/
298
+ my_package/
299
+ __init__.py
300
+ service.py
301
+ tests/
302
+ test_service.py
303
+ pyproject.toml
304
+ README.md
305
+ ```
306
+
307
+ The `src/` layout prevents accidental imports of the development tree; tests always import the installed package.
308
+
309
+ ### 6.2 pyproject.toml (PEP 621)
310
+
311
+ ```toml
312
+ [build-system]
313
+ requires = ["hatchling"]
314
+ build-backend = "hatchling.build"
315
+
316
+ [project]
317
+ name = "my-package"
318
+ version = "1.0.0"
319
+ requires-python = ">=3.10"
320
+ dependencies = [
321
+ "httpx>=0.27",
322
+ "pydantic>=2.0",
323
+ ]
324
+
325
+ [project.optional-dependencies]
326
+ dev = ["pytest>=8", "ruff", "mypy"]
327
+
328
+ [tool.ruff]
329
+ line-length = 100
330
+ target-version = "py310"
331
+
332
+ [tool.mypy]
333
+ python_version = "3.10"
334
+ strict = true
335
+ ```
336
+
337
+ ### 6.3 Recommended Toolchain
338
+
339
+ | Tool | Purpose | Replaces |
340
+ |------|---------|---------|
341
+ | `uv` | Package manager and virtual env (Rust-based, fast) | `pip` + `venv` + `pip-tools` |
342
+ | `ruff` | Linting and formatting | `flake8` + `black` + `isort` |
343
+ | `mypy` or `pyright` | Static type checking | — |
344
+ | `pytest` | Testing framework | `unittest` |
345
+ | `hatchling` | Build backend | `setuptools` |
346
+
347
+ - Use `uv sync` to install from lockfile; `uv add <dep>` to add dependencies with automatic lockfile update.
348
+ - Run `ruff check . --fix` and `ruff format .` in CI to enforce formatting and linting.
349
+ - Enable `mypy --strict` or equivalent `pyright` settings in CI.
350
+
351
+ ### 6.4 Virtual Environments
352
+
353
+ Use `uv venv` to create isolated environments; name the directory `.venv` (the conventional default recognized by editors and CI tools).
354
+
355
+ ```bash
356
+ uv venv # creates .venv/ in the current directory
357
+ source .venv/bin/activate # Linux/macOS
358
+ .venv\Scripts\activate # Windows
359
+ uv sync # install dependencies from lockfile into .venv
360
+ ```
361
+
362
+ - Commit the `uv.lock` lockfile; add `.venv/` to `.gitignore`.
363
+ - Prefer `uv run <command>` in CI to avoid activating the environment explicitly.
364
+
365
+ ---
366
+
367
+ ## 7. Python Version Awareness (3.13 forward-looking)
368
+
369
+ **Python 3.13 (awareness only — not yet required):**
370
+
371
+ - **Free-threaded mode** (`--disable-gil` / `python3.13t`): removes the GIL, enabling true multi-core parallelism in CPython. Do not design code around GIL removal yet; avoid shared mutable state as a general practice.
372
+ - **Improved error messages**: Python 3.13 continues the trend of actionable `TypeError`/`NameError` messages — write tests that do not over-assert on exception message strings.
373
+
374
+ ---
375
+
376
+ ## Cross-References
377
+
378
+ This skill covers broad Python coding standards. For deeper coverage of specialized domains, refer to:
379
+
380
+ > For Python security best practices (OWASP 2025 aligned), see the `python-security-skill`.
381
+ > For dependency security, supply chain protection, and lockfile management, see the `python-dependency-mgmt` skill.
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "Python Best Practices",
3
+ "description": "Comprehensive Python coding standards covering PEP 8 conventions, type hinting (3.10+), modern patterns (match/case, exception groups), async, and packaging best practices. Cross-references security-focused Python skills.",
4
+ "version": "1.0.0",
5
+ "category": "language",
6
+ "author": "ma-agents",
7
+ "tags": [
8
+ "python",
9
+ "coding-standards",
10
+ "best-practices",
11
+ "pep8",
12
+ "type-hints",
13
+ "python3.10",
14
+ "python3.11",
15
+ "python3.12"
16
+ ],
17
+ "applies_when": [
18
+ "writing python code",
19
+ "modifying python code",
20
+ "creating new python files or modules",
21
+ "reviewing python code style or conventions",
22
+ "refactoring python code",
23
+ "setting up a python project"
24
+ ],
25
+ "always_load": false
26
+ }
@@ -0,0 +1,74 @@
1
+ # Story Status Lookup
2
+
3
+ Look up the current status of a story to determine whether its code is **delivered** or **work-in-progress**.
4
+
5
+ ## Purpose
6
+
7
+ Used by other skills (notably `auto-bug-detection`) to classify code before deciding whether to flag defects.
8
+ Do not flag bugs in WIP code. Do flag bugs in delivered code.
9
+
10
+ ---
11
+
12
+ ## Backend Configuration
13
+
14
+ Before performing a lookup, check the project context for the configured sprint management backend.
15
+
16
+ **Where to look (in priority order):**
17
+ 1. `project-context.md` in the project root — look for a `sprint_management` field
18
+ 2. The root directives file (`CLAUDE.md`, `.cursor/rules`, or equivalent for the active agent)
19
+ 3. If neither defines a backend, **default to `file-system`**
20
+
21
+ | `sprint_management` value | Backend |
22
+ |---|---|
23
+ | `file-system` or not set | Read `sprint-status.yaml` (see below) |
24
+ | `jira` | *(Future — see Jira section below)* |
25
+
26
+ ---
27
+
28
+ ## File-System Backend
29
+
30
+ **Status file:** `_bmad-output/implementation-artifacts/sprint-status.yaml`
31
+
32
+ ### Step 1 — Identify the story slug
33
+
34
+ Derive the story slug from the available context, in this order of preference:
35
+
36
+ 1. The story file name currently in scope (e.g. `11-1-auto-bug-detection-skill.md` → slug is `11-1-auto-bug-detection-skill`)
37
+ 2. The git branch name — strip prefixes (`feature/`, `fix/`, `chore/`) and normalize: lowercase, replace spaces and underscores with hyphens, remove non-alphanumeric characters except hyphens
38
+ 3. Any explicit story reference in the current task description
39
+
40
+ ### Step 2 — Look up the slug
41
+
42
+ Find the slug as a key under `development_status` in `sprint-status.yaml`.
43
+
44
+ ### Step 3 — Map status to delivered / WIP
45
+
46
+ | Status value | Classification | Action |
47
+ |---|---|---|
48
+ | `done` | **Delivered** | Flag bugs |
49
+ | `review` | **Delivered** | Flag bugs — dev work is complete, code is awaiting review |
50
+ | `in-progress` | WIP | Do not flag |
51
+ | `ready-for-dev` | WIP | Do not flag |
52
+ | `backlog` | WIP | Do not flag |
53
+ | `on-hold` | WIP | Do not flag |
54
+
55
+ ### Fallback rule
56
+
57
+ If any of the following are true, **classify as WIP and do not flag**:
58
+ - The story slug cannot be determined from context
59
+ - The slug is not found in `sprint-status.yaml`
60
+ - The status file does not exist
61
+
62
+ Never guess or assume delivered status. When in doubt, WIP.
63
+
64
+ ---
65
+
66
+ ## Future: Jira Backend
67
+
68
+ When `sprint_management: jira` is set in the project context, this extension point applies:
69
+
70
+ - Jira base URL, project key, and credentials will be defined in the project context or environment config
71
+ - Query the Jira issue status API for the relevant issue key
72
+ - Map the Jira workflow status to delivered/WIP using a status mapping defined in the project context
73
+
74
+ **This backend is not yet implemented.** When Jira support is added, update this skill with the lookup procedure and status mapping. The file-system backend remains the default fallback if Jira is unreachable.
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "story-status-lookup",
3
+ "version": "1.0.0",
4
+ "description": "Looks up the current status of a story to classify code as delivered or work-in-progress. Supports file-system backend now; Jira backend reserved for future configuration.",
5
+ "category": "workflow",
6
+ "tags": ["story-status", "sprint-management", "bug-detection"],
7
+ "always_load": true
8
+ }
@@ -65,15 +65,15 @@ test('3.3: installer.js contains NO agent-name-specific logic', () => {
65
65
 
66
66
  console.log('\nTask 4 — Registry completeness');
67
67
 
68
- const EXPECTED_IDE = ['claude-code', 'gemini', 'copilot', 'kilocode', 'cline', 'cursor', 'antigravity'];
68
+ const EXPECTED_IDE = ['claude-code', 'gemini', 'copilot', 'kilocode', 'cline', 'cursor', 'antigravity', 'opencode'];
69
69
  const EXPECTED_BMAD = ['bmm-sre', 'bmm-devops', 'bmm-cyber', 'bmm-mil498'];
70
70
  const EXPECTED_ALL = [...EXPECTED_IDE, ...EXPECTED_BMAD];
71
71
 
72
- test('4.1: registry has exactly 11 agents (7 IDE + 4 BMAD)', () => {
73
- assert.strictEqual(allAgents.length, 11, `Expected 11 agents, got ${allAgents.length}`);
72
+ test('4.1: registry has at least 12 agents (8+ IDE + 4 BMAD)', () => {
73
+ assert.ok(allAgents.length >= 12, `Expected at least 12 agents, got ${allAgents.length}`);
74
74
  const ideCount = allAgents.filter(a => a.category === 'ide').length;
75
75
  const bmadCount = allAgents.filter(a => a.category === 'bmad').length;
76
- assert.strictEqual(ideCount, 7, `Expected 7 IDE agents, got ${ideCount}`);
76
+ assert.ok(ideCount >= 8, `Expected at least 8 IDE agents, got ${ideCount}`);
77
77
  assert.strictEqual(bmadCount, 4, `Expected 4 BMAD agents, got ${bmadCount}`);
78
78
  });
79
79
 
@@ -83,13 +83,18 @@ test('4.2: every agent has well-shaped injectionStrategy property', () => {
83
83
  `Agent '${agent.id}' is missing injectionStrategy`);
84
84
  assert.strictEqual(typeof agent.injectionStrategy.position, 'string',
85
85
  `Agent '${agent.id}' injectionStrategy.position should be a string`);
86
- assert.ok(Array.isArray(agent.injectionStrategy.skipPatterns),
87
- `Agent '${agent.id}' injectionStrategy.skipPatterns should be an array, got ${typeof agent.injectionStrategy.skipPatterns}`);
86
+ // skipPatterns is only required for non-json-merge strategies
87
+ if (agent.injectionStrategy.position !== 'json-merge') {
88
+ assert.ok(Array.isArray(agent.injectionStrategy.skipPatterns),
89
+ `Agent '${agent.id}' injectionStrategy.skipPatterns should be an array, got ${typeof agent.injectionStrategy.skipPatterns}`);
90
+ }
88
91
  }
89
92
  });
90
93
 
91
94
  test('4.3: all agents with .md instruction files have skipPatterns: [---]', () => {
92
95
  for (const agent of allAgents) {
96
+ // json-merge agents use a different injection mechanism; skip this check for them
97
+ if (agent.injectionStrategy.position === 'json-merge') continue;
93
98
  const hasMdFiles = agent.instructionFiles.some(f => f.endsWith('.md'));
94
99
  if (hasMdFiles) {
95
100
  assert.ok(agent.injectionStrategy.skipPatterns,
@@ -100,8 +105,9 @@ test('4.3: all agents with .md instruction files have skipPatterns: [---]', () =
100
105
  }
101
106
  });
102
107
 
103
- test('4.3b: all agents have position: top', () => {
108
+ test('4.3b: non-json-merge agents have position: top', () => {
104
109
  for (const agent of allAgents) {
110
+ if (agent.injectionStrategy.position === 'json-merge') continue;
105
111
  assert.strictEqual(agent.injectionStrategy.position, 'top',
106
112
  `Agent '${agent.id}' should have position: 'top'`);
107
113
  }