From ebc285a23bcea5010c7ac32b34fc9eaeefb4bb0d Mon Sep 17 00:00:00 2001 From: lugassawan Date: Sat, 2 May 2026 18:47:09 +0700 Subject: [PATCH 1/4] [docs] Backfill README + catalog for /capture, cleanup-merged, product-manager - Add /capture and /cleanup-merged to README commands list - Add product-manager to README subagents list - Add /capture row to catalog.md Commands table - Add product-manager row to catalog.md Subagents table - Add argument-hint frontmatter to review and security-review commands --- README.md | 4 ++-- commands/review.md | 1 + commands/security-review.md | 1 + docs/catalog.md | 2 ++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 803f254..8c2dfd5 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,8 @@ cd swe-workbench ## What's inside -- **Commands** — `/swe-workbench:review`, `/swe-workbench:design`, `/swe-workbench:refactor`, `/swe-workbench:debug`, `/swe-workbench:implement`, `/swe-workbench:test`, `/swe-workbench:security-review` — see [docs/catalog.md](docs/catalog.md). -- **Subagents** — `reviewer`, `senior-engineer`, `refactorer`, `debugger`, `security-auditor`, `test-writer` — see [docs/catalog.md](docs/catalog.md). +- **Commands** — `/swe-workbench:review`, `/swe-workbench:design`, `/swe-workbench:refactor`, `/swe-workbench:debug`, `/swe-workbench:implement`, `/swe-workbench:test`, `/swe-workbench:security-review`, `/swe-workbench:capture`, `/swe-workbench:cleanup-merged` — see [docs/catalog.md](docs/catalog.md). +- **Subagents** — `reviewer`, `senior-engineer`, `refactorer`, `debugger`, `security-auditor`, `test-writer`, `product-manager` — see [docs/catalog.md](docs/catalog.md). - **Principles** — Clean Architecture, DDD, SOLID, TDD, design patterns, clean code, observability, API design, concurrency, error handling, security — auto-load by trigger keyword. - **Languages** — Go, Rust, TypeScript — auto-load by file extension. - **Integrations** — `ticket-context` — auto-loads on ticket references (Jira, Confluence, GitHub) to feed the full spec into commands. diff --git a/commands/review.md b/commands/review.md index ef21855..48d2eb0 100644 --- a/commands/review.md +++ b/commands/review.md @@ -1,5 +1,6 @@ --- description: Review the current git diff with senior-engineer depth — correctness, security, design, and test gaps +argument-hint: "[ticket ref or leave blank to review current diff]" --- Review the pending changes on this branch. diff --git a/commands/security-review.md b/commands/security-review.md index 652229c..72a6511 100644 --- a/commands/security-review.md +++ b/commands/security-review.md @@ -1,5 +1,6 @@ --- description: Audit the current git diff for security vulnerabilities — OWASP Top 10, secrets, insecure APIs, dependency CVEs +argument-hint: "[ticket ref or leave blank to audit current diff]" --- Audit the pending changes on this branch for security vulnerabilities. diff --git a/docs/catalog.md b/docs/catalog.md index c0b76bb..09bed48 100644 --- a/docs/catalog.md +++ b/docs/catalog.md @@ -11,6 +11,7 @@ | `/swe-workbench:debug ` | Diagnose a bug or failing test via systematic-debugging, then minimal fix + regression test. | | `/swe-workbench:test ` | Write focused, behavioural tests in the target language's idiom. | | `/swe-workbench:implement ` | Drive a feature end-to-end — branch, plan, TDD build, verify, review, PR. Orchestrates the full 5-phase `workflow-development` lifecycle. | +| `/swe-workbench:capture ` | Capture an idea, bug, or improvement as a well-framed GitHub issue via the `product-manager` subagent. Auth + repo detection, product framing, duplicate scan, draft preview, and user-confirm gate before filing. | | `/swe-workbench:cleanup-merged [PR number]` | Remove the worktree, local branch, and remote branch for a merged PR. Defaults to the current branch. Squash-merge safe. | ## Subagents @@ -23,6 +24,7 @@ | `refactorer` | Cleaning up smells before adding a feature. | | `debugger` | Bug diagnosis and minimal fix — composes `superpowers:systematic-debugging`, layers principle lens. | | `test-writer` | Authoring tests for an existing function, module, or change set. | +| `product-manager` | Drafts a well-framed GitHub issue from a raw idea — product framing (problem, value, RICE-lite), template detection, duplicate scan, and confirm gate. Invoked by `/swe-workbench:capture`. | ## Skills From 50083dc8f0a34c0a4b66b807b7e9597f76f7fcff Mon Sep 17 00:00:00 2001 From: lugassawan Date: Sat, 2 May 2026 18:48:08 +0700 Subject: [PATCH 2/4] [refactor] DRY ticket-context trigger description across 5 commands Each command previously inlined the full trigger-pattern list (Jira keys, Atlassian/Confluence URLs, GitHub refs). Those patterns are already the canonical source of truth in skills/ticket-context/SKILL.md "When to invoke". Replace with a short invocation line that references the skill, eliminating the copy-paste surface that drifts when detection rules change. --- commands/debug.md | 2 +- commands/design.md | 2 +- commands/implement.md | 2 +- commands/refactor.md | 2 +- commands/test.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/commands/debug.md b/commands/debug.md index e0d5370..2bdc24e 100644 --- a/commands/debug.md +++ b/commands/debug.md @@ -5,7 +5,7 @@ argument-hint: Symptom: $ARGUMENTS -If $ARGUMENTS contains a ticket reference (Jira key like `PROJ-123`, an `atlassian.net` URL, a Confluence wiki URL, or a GitHub issue/PR URL or `#NNN`), invoke the `swe-workbench:ticket-context` skill first and prepend its structured summary to the delegation context below. +If $ARGUMENTS contains a ticket reference, invoke `swe-workbench:ticket-context` first and prepend its structured summary to the delegation context below. (Trigger patterns — Jira keys, Atlassian/Confluence URLs, GitHub issue/PR URLs — are defined in that skill's "When to invoke" section.) Delegate to the `debugger` subagent. Its output must include: diff --git a/commands/design.md b/commands/design.md index 5f9c7f3..018a7df 100644 --- a/commands/design.md +++ b/commands/design.md @@ -5,7 +5,7 @@ argument-hint: The user is asking: $ARGUMENTS -If $ARGUMENTS contains a ticket reference (Jira key like `PROJ-123`, an `atlassian.net` URL, a Confluence wiki URL, or a GitHub issue/PR URL or `#NNN`), invoke the `swe-workbench:ticket-context` skill first and prepend its structured summary so the subagent has the full design brief. +If $ARGUMENTS contains a ticket reference, invoke `swe-workbench:ticket-context` first and prepend its structured summary so the subagent has the full design brief. (Trigger patterns are defined in that skill's "When to invoke" section.) Delegate to the `senior-engineer` subagent. Its response must contain: diff --git a/commands/implement.md b/commands/implement.md index 545ecb6..b7e01b3 100644 --- a/commands/implement.md +++ b/commands/implement.md @@ -5,7 +5,7 @@ argument-hint: Feature request: $ARGUMENTS -If $ARGUMENTS contains a ticket reference (Jira key like `PROJ-123`, an `atlassian.net` URL, a Confluence wiki URL, or a GitHub issue/PR URL or `#NNN`), invoke the `swe-workbench:ticket-context` skill first and prepend its structured summary to the context below. Skip this prelude if $ARGUMENTS is free-text with no recognizable ref. +If $ARGUMENTS contains a ticket reference, invoke `swe-workbench:ticket-context` first and prepend its structured summary to the context below. Skip if $ARGUMENTS is free-text with no recognizable ref. (Trigger patterns are defined in that skill's "When to invoke" section.) Activate the `swe-workbench:workflow-development` skill in **Mode B (Implementation-Time Behavior)**. Execute all five phases in order: diff --git a/commands/refactor.md b/commands/refactor.md index b12a73c..2cf99d8 100644 --- a/commands/refactor.md +++ b/commands/refactor.md @@ -5,7 +5,7 @@ argument-hint: Target: $ARGUMENTS -If $ARGUMENTS contains a ticket reference (Jira key like `PROJ-123`, an `atlassian.net` URL, a Confluence wiki URL, or a GitHub issue/PR URL or `#NNN`), invoke the `swe-workbench:ticket-context` skill first; a refactor motivated by a ticket needs the ticket's scope and constraints in the delegation context. +If $ARGUMENTS contains a ticket reference, invoke `swe-workbench:ticket-context` first — a refactor motivated by a ticket needs the ticket's scope and constraints in the delegation context. (Trigger patterns are defined in that skill's "When to invoke" section.) Delegate to the `refactorer` subagent. Its output must include: diff --git a/commands/test.md b/commands/test.md index 520407b..6a6fb1c 100644 --- a/commands/test.md +++ b/commands/test.md @@ -5,7 +5,7 @@ argument-hint: Target: $ARGUMENTS -If $ARGUMENTS contains a ticket reference (Jira key like `PROJ-123`, an `atlassian.net` URL, a Confluence wiki URL, or a GitHub issue/PR URL or `#NNN`), invoke the `swe-workbench:ticket-context` skill first; tests motivated by a ticket need the ticket's acceptance criteria in the delegation context. +If $ARGUMENTS contains a ticket reference, invoke `swe-workbench:ticket-context` first — tests motivated by a ticket need the ticket's acceptance criteria in the delegation context. (Trigger patterns are defined in that skill's "When to invoke" section.) Delegate to the `test-writer` subagent. Its output must include: From 36aac731cb805c214b3bc424c0a735f0525c3e89 Mon Sep 17 00:00:00 2001 From: lugassawan Date: Sat, 2 May 2026 18:49:27 +0700 Subject: [PATCH 3/4] [feat] Add language-python skill, closes #8 Adds skills/language-python/SKILL.md covering: - Type hints and dataclasses (PEP 484, Protocol, TypedDict) - Error handling idioms - Context managers and generators - Concurrency: GIL caveat, asyncio TaskGroup, ProcessPoolExecutor - Pattern matching (3.10+) - Packaging: pyproject.toml, uv/poetry, virtualenvs - Testing: pytest, parametrize, pytest-asyncio - Performance: cProfile, py-spy, C extension guidance - Avoid section Also updates README and docs/catalog.md with Python in the Languages table. --- README.md | 2 +- docs/catalog.md | 1 + skills/language-python/SKILL.md | 110 ++++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 skills/language-python/SKILL.md diff --git a/README.md b/README.md index 8c2dfd5..33443f4 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ cd swe-workbench - **Commands** — `/swe-workbench:review`, `/swe-workbench:design`, `/swe-workbench:refactor`, `/swe-workbench:debug`, `/swe-workbench:implement`, `/swe-workbench:test`, `/swe-workbench:security-review`, `/swe-workbench:capture`, `/swe-workbench:cleanup-merged` — see [docs/catalog.md](docs/catalog.md). - **Subagents** — `reviewer`, `senior-engineer`, `refactorer`, `debugger`, `security-auditor`, `test-writer`, `product-manager` — see [docs/catalog.md](docs/catalog.md). - **Principles** — Clean Architecture, DDD, SOLID, TDD, design patterns, clean code, observability, API design, concurrency, error handling, security — auto-load by trigger keyword. -- **Languages** — Go, Rust, TypeScript — auto-load by file extension. +- **Languages** — Go, Rust, TypeScript, Python — auto-load by file extension. - **Integrations** — `ticket-context` — auto-loads on ticket references (Jira, Confluence, GitHub) to feed the full spec into commands. - **Workflows** — `development` orchestrator wrapping the full 5-phase implementation lifecycle. diff --git a/docs/catalog.md b/docs/catalog.md index 09bed48..5a67aed 100644 --- a/docs/catalog.md +++ b/docs/catalog.md @@ -51,6 +51,7 @@ | `language-go` | `.go` files, `go.mod`, `go.sum`, keywords: Go, Golang, goroutine, channel, context. | | `language-rust` | `.rs` files, `Cargo.toml`, keywords: Rust, cargo, ownership, borrow checker, trait, lifetime. | | `language-typescript` | `.ts`, `.tsx`, `.js`, `.jsx`, `package.json`, keywords: TypeScript, Node, tsconfig. | +| `language-python` | `.py` files, `pyproject.toml`, `requirements.txt`, keywords: Python, pytest, asyncio, dataclass, type hints, virtualenv. | ### Workflows — auto-load during implementation diff --git a/skills/language-python/SKILL.md b/skills/language-python/SKILL.md new file mode 100644 index 0000000..19a005f --- /dev/null +++ b/skills/language-python/SKILL.md @@ -0,0 +1,110 @@ +--- +name: language-python +description: Python idioms — PEP 8, type hints, dataclasses, context managers, generators, asyncio, and testing. Auto-load when working with .py files, pyproject.toml, requirements.txt, or when the user mentions Python, pytest, asyncio, dataclass, type hints, or virtualenv. +--- + +# Python + +## Type hints +- Annotate all function signatures; `Any` is a smell unless at a genuine boundary. +- Use `dataclass` for data containers with behavior; `TypedDict` for dict-shaped data at boundaries. +- Prefer `Protocol` over ABC when duck typing suffices — no inheritance required. +- `from __future__ import annotations` for forward refs in 3.9 and earlier. + +```python +from dataclasses import dataclass, field + +@dataclass +class Order: + id: str + items: list[str] = field(default_factory=list) + total: float = 0.0 +``` + +## Errors and exceptions +- Use exceptions for exceptional paths, not flow control. +- Raise specific subclasses; catch the narrowest class you can handle. +- `except Exception:` is almost always wrong — at minimum log and re-raise. +- `contextlib.suppress(SomeError)` for intentional ignore; bare `except:` never. + +```python +try: + result = load(path) +except FileNotFoundError: + raise MissingConfigError(path) from None +``` + +## Context managers +- `with` for any resource with a cleanup obligation: files, locks, DB connections. +- `@contextlib.contextmanager` for ad-hoc managers without a full class. +- Never hold a resource longer than the `with` block. + +## Generators and iterators +- Prefer generators over materializing full lists when you only iterate once. +- `yield from` to delegate to sub-generators. +- Reach for `itertools` before writing loops: `chain`, `islice`, `groupby`, `product`. + +```python +def read_chunks(path: Path, size: int = 4096): + with open(path, "rb") as f: + while chunk := f.read(size): + yield chunk +``` + +## Concurrency +- **GIL caveat:** threads don't parallelize CPU-bound work — use `ProcessPoolExecutor` or `multiprocessing`. +- `asyncio` for IO-bound concurrency; `asyncio.TaskGroup` (3.11+) for structured fan-out. +- `ThreadPoolExecutor` for legacy sync IO or blocking C extensions. +- One event loop per process; never nest or mix loops. + +```python +async def fetch_all(urls: list[str]) -> list[str]: + async with asyncio.TaskGroup() as tg: + tasks = [tg.create_task(fetch(u)) for u in urls] + return [t.result() for t in tasks] +``` + +## Pattern matching (3.10+) +Use `match` for structural dispatch on data shapes; avoid it as a glorified `if/elif` chain. + +```python +match command: + case {"action": "move", "direction": dir}: + move(dir) + case {"action": "quit"}: + quit() + case _: + raise ValueError(f"unknown command: {command}") +``` + +## Dependencies and packaging +- `pyproject.toml` is the standard — no `setup.py` in new projects. +- `uv` for fast installs; `poetry` for lockfile publishing workflows. +- Pin transitive deps via lockfile (`uv.lock`, `poetry.lock`) in applications; use version ranges in libraries. +- Always isolate with a virtualenv — never install into the system Python. + +## Testing +- `pytest` over `unittest` — fixtures, parametrize, and plugins make it richer. +- `@pytest.mark.parametrize` instead of loops inside tests. +- `unittest.mock.patch` for external boundaries only; don't mock internals. +- `pytest-asyncio` for async tests; `respx` or `httpx` mock transport for HTTP clients. + +```python +@pytest.mark.parametrize("a, b, expected", [(1, 2, 3), (0, 0, 0)]) +def test_add(a, b, expected): + assert add(a, b) == expected +``` + +## Performance +- Profile before optimizing: `cProfile` for CPU hotspots, `tracemalloc` for memory. +- `py-spy` samples live processes without code changes. +- C extensions (`cffi`, `Cython`) only after profiling confirms a Python bottleneck. +- Cache attribute lookups in tight loops: `fn = obj.method` outside the loop. + +## Avoid +- Mutable default arguments (`def f(x=[])` — use `None`, assign inside). +- `from module import *` — pollutes namespace, breaks static analysis. +- `global` / `nonlocal` except in narrow closures. +- Broad `try/except` blocks that swallow errors silently. +- `subprocess.run(shell=True)` with user-controlled input — use the list form. +- Reimplementing what `itertools`, `functools`, or `collections` already provide. From e1d6220111a4eaf4d562a607c5c7d400b53b5868 Mon Sep 17 00:00:00 2001 From: lugassawan Date: Sat, 2 May 2026 18:58:29 +0700 Subject: [PATCH 4/4] [polish] Apply review suggestions: DRY debug.md prelude, Python skill examples - commands/debug.md: strip inline trigger-pattern examples from parenthetical to match the other four DRY'd commands and prevent future drift - skills/language-python/SKILL.md: add @contextlib.contextmanager code example to Context managers section (matches peer skills' example-per-section style) - skills/language-python/SKILL.md: annotate walrus operator usage with # 3.8+ for consistency with the file's version-annotation convention --- commands/debug.md | 2 +- skills/language-python/SKILL.md | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/commands/debug.md b/commands/debug.md index 2bdc24e..ef2eb90 100644 --- a/commands/debug.md +++ b/commands/debug.md @@ -5,7 +5,7 @@ argument-hint: Symptom: $ARGUMENTS -If $ARGUMENTS contains a ticket reference, invoke `swe-workbench:ticket-context` first and prepend its structured summary to the delegation context below. (Trigger patterns — Jira keys, Atlassian/Confluence URLs, GitHub issue/PR URLs — are defined in that skill's "When to invoke" section.) +If $ARGUMENTS contains a ticket reference, invoke `swe-workbench:ticket-context` first and prepend its structured summary to the delegation context below. (Trigger patterns are defined in that skill's "When to invoke" section.) Delegate to the `debugger` subagent. Its output must include: diff --git a/skills/language-python/SKILL.md b/skills/language-python/SKILL.md index 19a005f..59b0a1d 100644 --- a/skills/language-python/SKILL.md +++ b/skills/language-python/SKILL.md @@ -39,6 +39,16 @@ except FileNotFoundError: - `@contextlib.contextmanager` for ad-hoc managers without a full class. - Never hold a resource longer than the `with` block. +```python +@contextlib.contextmanager +def managed_resource(): + r = acquire() + try: + yield r + finally: + release(r) +``` + ## Generators and iterators - Prefer generators over materializing full lists when you only iterate once. - `yield from` to delegate to sub-generators. @@ -47,7 +57,7 @@ except FileNotFoundError: ```python def read_chunks(path: Path, size: int = 4096): with open(path, "rb") as f: - while chunk := f.read(size): + while chunk := f.read(size): # walrus operator, 3.8+ yield chunk ```