devlyn-cli 0.2.1 → 0.4.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.
@@ -0,0 +1,241 @@
1
+ # Test Infrastructure Reference
2
+
3
+ Test setup, seed factories, and integration test patterns for Better Auth with Bun.
4
+
5
+ ## Table of Contents
6
+ 1. [Test Preload](#test-preload)
7
+ 2. [Seed Data Factory](#seed-data-factory)
8
+ 3. [Integration Test App](#integration-test-app)
9
+ 4. [Database Cleanup](#database-cleanup)
10
+ 5. [Key Testing Patterns](#key-testing-patterns)
11
+
12
+ ## Test Preload
13
+
14
+ Prevents the most common testing pitfall: real emails sent during test runs.
15
+
16
+ ```typescript
17
+ // src/test-utils/setup.ts — preloaded via bunfig.toml
18
+ // Without this, test signups send real emails through Resend
19
+ // when RESEND_API_KEY is in your .env file.
20
+ process.env.NODE_ENV = "test";
21
+ process.env.RESEND_API_KEY = ""; // Force email to console-log fallback
22
+
23
+ // Bridge test database — use a separate DB for tests
24
+ if (process.env.TEST_DATABASE_URL) {
25
+ process.env.DATABASE_URL = process.env.TEST_DATABASE_URL;
26
+ }
27
+ ```
28
+
29
+ ```toml
30
+ # bunfig.toml
31
+ [test]
32
+ preload = ["./src/test-utils/setup.ts"]
33
+ ```
34
+
35
+ **Why preload?** Bun's preload runs before any test file imports. This guarantees that config validation (which runs at import time) sees the correct environment variables. Setting `RESEND_API_KEY = ""` before any module loads ensures the email module's lazy client never initializes.
36
+
37
+ ## Seed Data Factory
38
+
39
+ Creates a complete tenant hierarchy for integration tests. Every call produces unique identifiers to prevent collisions in parallel test runs.
40
+
41
+ ```typescript
42
+ // src/test-utils/db.ts
43
+ import { db } from "../db";
44
+ import {
45
+ organizations, users, orgMemberships,
46
+ projects, apiKeys, sessions, accounts,
47
+ verifications, invitations,
48
+ } from "../db/schema";
49
+
50
+ export async function seedTestData() {
51
+ const uniqueSuffix = `${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
52
+
53
+ // Create org → user → membership → project → API key
54
+ const [org] = await db.insert(organizations).values({
55
+ name: `Test Org ${uniqueSuffix}`,
56
+ slug: `test-org-${uniqueSuffix}`,
57
+ plan: "free",
58
+ }).returning();
59
+
60
+ const [user] = await db.insert(users).values({
61
+ email: `test-${uniqueSuffix}@example.com`,
62
+ name: "Test User",
63
+ emailVerified: true,
64
+ }).returning();
65
+
66
+ await db.insert(orgMemberships).values({
67
+ organizationId: org.id,
68
+ userId: user.id,
69
+ role: "owner",
70
+ });
71
+
72
+ const [project] = await db.insert(projects).values({
73
+ organizationId: org.id,
74
+ name: `Test Project ${uniqueSuffix}`,
75
+ slug: `test-project-${uniqueSuffix}`,
76
+ }).returning();
77
+
78
+ // Generate API key
79
+ const { key, hash, prefix } = await generateTestApiKey();
80
+ const [apiKey] = await db.insert(apiKeys).values({
81
+ projectId: project.id,
82
+ name: "Test Key",
83
+ keyHash: hash,
84
+ keyPrefix: prefix,
85
+ }).returning();
86
+
87
+ return { org, user, project, apiKey, plaintextKey: key };
88
+ }
89
+
90
+ // Helper: generate a test API key
91
+ async function generateTestApiKey() {
92
+ const { API_KEY_PREFIX, base62Encode, hashKey } = await import("../lib/api-keys");
93
+ const randomBytes = crypto.getRandomValues(new Uint8Array(32));
94
+ const key = API_KEY_PREFIX + base62Encode(randomBytes);
95
+ const hash = await hashKey(key);
96
+ const prefix = key.slice(0, 12);
97
+ return { key, hash, prefix };
98
+ }
99
+ ```
100
+
101
+ **Key design decisions:**
102
+ - `uniqueSuffix` uses `Date.now()` + random chars for collision-free parallel tests
103
+ - `emailVerified: true` so tests don't need to go through email verification flow
104
+ - Returns `plaintextKey` so tests can immediately make authenticated requests
105
+
106
+ ## Integration Test App
107
+
108
+ Builds the full middleware chain matching production. This catches middleware ordering bugs before they reach production.
109
+
110
+ ```typescript
111
+ // src/test-utils/app.ts
112
+ import { Hono } from "hono";
113
+
114
+ // Lazy imports to avoid circular dependency issues during test setup
115
+ export function createIntegrationApp() {
116
+ const { authMiddleware } = require("../middleware/auth");
117
+ const { tenantContextMiddleware } = require("../middleware/tenant-context");
118
+ const { rateLimitMiddleware } = require("../middleware/rate-limit");
119
+
120
+ const app = new Hono();
121
+
122
+ // Request ID
123
+ app.use("*", async (c, next) => {
124
+ c.set("requestId", crypto.randomUUID());
125
+ await next();
126
+ });
127
+
128
+ // Auth → Tenant Context → Rate Limit (same order as production)
129
+ app.use("*", authMiddleware);
130
+ app.use("*", tenantContextMiddleware);
131
+ app.use("*", rateLimitMiddleware);
132
+
133
+ // Mount route handlers here...
134
+ return app;
135
+ }
136
+ ```
137
+
138
+ **Why lazy imports?** The auth module imports the database module, which reads `DATABASE_URL` from the environment. If imported eagerly at the top level, the test preload script might not have run yet, causing config validation to fail.
139
+
140
+ ## Database Cleanup
141
+
142
+ Delete tables in FK dependency order to avoid constraint violations.
143
+
144
+ ```typescript
145
+ // Clean tables in FK dependency order
146
+ export async function cleanupDatabase() {
147
+ // Children first, parents last
148
+ await db.delete(apiKeys);
149
+ await db.delete(projects);
150
+ await db.delete(orgMemberships);
151
+ await db.delete(sessions);
152
+ await db.delete(accounts);
153
+ await db.delete(verifications);
154
+ await db.delete(invitations);
155
+ await db.delete(organizations);
156
+ await db.delete(users);
157
+ }
158
+ ```
159
+
160
+ **Order matters.** If you try to delete `organizations` before `projects`, the FK constraint on `projects.organization_id` will reject the delete. Start from leaf tables and work toward root tables.
161
+
162
+ ## Key Testing Patterns
163
+
164
+ ### Test Auth via API Key
165
+
166
+ ```typescript
167
+ import { describe, test, expect, beforeAll, afterAll } from "bun:test";
168
+
169
+ describe("Protected endpoint", () => {
170
+ let testData: Awaited<ReturnType<typeof seedTestData>>;
171
+
172
+ beforeAll(async () => {
173
+ testData = await seedTestData();
174
+ });
175
+
176
+ afterAll(async () => {
177
+ await cleanupDatabase();
178
+ });
179
+
180
+ test("returns 200 with valid API key", async () => {
181
+ const app = createIntegrationApp();
182
+ const res = await app.request("/v1/endpoint", {
183
+ headers: {
184
+ Authorization: `Bearer ${testData.plaintextKey}`,
185
+ },
186
+ });
187
+ expect(res.status).toBe(200);
188
+ });
189
+
190
+ test("returns 401 without auth", async () => {
191
+ const app = createIntegrationApp();
192
+ const res = await app.request("/v1/endpoint");
193
+ expect(res.status).toBe(401);
194
+ });
195
+ });
196
+ ```
197
+
198
+ ### Test Signup Flow
199
+
200
+ ```typescript
201
+ test("signup creates user and personal org", async () => {
202
+ const res = await app.request("/auth/sign-up/email", {
203
+ method: "POST",
204
+ headers: { "Content-Type": "application/json" },
205
+ body: JSON.stringify({
206
+ email: `signup-test-${Date.now()}@example.com`,
207
+ password: "secure-password-123",
208
+ name: "Test User",
209
+ }),
210
+ });
211
+
212
+ expect(res.status).toBe(200);
213
+
214
+ // Verify auto-org creation via databaseHooks
215
+ const user = await db.select().from(users)
216
+ .where(eq(users.email, email)).limit(1);
217
+
218
+ const membership = await db.select().from(orgMemberships)
219
+ .where(eq(orgMemberships.userId, user[0].id)).limit(1);
220
+
221
+ expect(membership).toHaveLength(1);
222
+ expect(membership[0].role).toBe("owner");
223
+ });
224
+ ```
225
+
226
+ ### Test Tenant Isolation
227
+
228
+ ```typescript
229
+ test("cannot access resources from another org", async () => {
230
+ const org1 = await seedTestData();
231
+ const org2 = await seedTestData();
232
+
233
+ // Use org1's API key to try accessing org2's project
234
+ const res = await app.request(`/v1/projects/${org2.project.id}`, {
235
+ headers: { Authorization: `Bearer ${org1.plaintextKey}` },
236
+ });
237
+
238
+ // Should be 404 (not 403, to prevent ID enumeration)
239
+ expect(res.status).toBe(404);
240
+ });
241
+ ```
@@ -0,0 +1,60 @@
1
+ # Skill Quality Checklist
2
+
3
+ Verify the generated skill against every item below before finalizing.
4
+
5
+ ---
6
+
7
+ ## Frontmatter
8
+
9
+ - [ ] `name` is lowercase, hyphens and digits only, max 64 chars
10
+ - [ ] `name` does not contain "anthropic", "claude", or "official"
11
+ - [ ] `description` is third-person, max 1024 chars
12
+ - [ ] `description` includes specific trigger phrases ("Use when user says...")
13
+ - [ ] `description` first sentence states what the skill does
14
+ - [ ] `allowed-tools` uses the minimal set needed (not all tools)
15
+ - [ ] `argument-hint` shows expected input format if skill takes arguments
16
+ - [ ] No XML tags in any frontmatter field values
17
+
18
+ ## Body Structure
19
+
20
+ - [ ] Starts with a title (`#`) and one-line purpose statement
21
+ - [ ] Lists reference files with descriptions (if multi-file)
22
+ - [ ] Workflow uses numbered steps with `###` headings
23
+ - [ ] Each step starts with an action verb (Parse, Read, Generate, Validate)
24
+ - [ ] Each step has clear entry and exit criteria
25
+ - [ ] Output format is explicitly defined
26
+
27
+ ## Content Quality
28
+
29
+ - [ ] Instructions are explicit, not vague ("Review for X, Y, Z" not "Review the code")
30
+ - [ ] Includes WHY context for non-obvious rules
31
+ - [ ] Uses XML tags for complex structure (`<example>`, `<rules>`, `<output-format>`)
32
+ - [ ] Uses "consider"/"evaluate" instead of "think"
33
+ - [ ] Contains at least one concrete `<example>` block
34
+ - [ ] Scope is bounded (file limits, directory limits, or explicit boundaries)
35
+ - [ ] No conflicting instructions
36
+
37
+ ## Error Handling
38
+
39
+ - [ ] Handles empty `$ARGUMENTS` (asks user or uses sensible detection)
40
+ - [ ] Handles missing files (clear error message, not silent fallback)
41
+ - [ ] Handles unexpected input (validation with actionable error)
42
+ - [ ] No silent fallbacks to defaults (project convention)
43
+
44
+ ## Prompt Engineering
45
+
46
+ - [ ] No over-triggering (description is specific, not generic)
47
+ - [ ] No aggressive language ("MUST", "NEVER EVER", "ABSOLUTELY")
48
+ - [ ] No wall of text without headings or structure
49
+ - [ ] No unbounded scope ("analyze everything")
50
+ - [ ] Anti-hallucination patterns applied (grounded in file content)
51
+ - [ ] Degree of freedom matches skill type (guardrails for high, specs for low)
52
+
53
+ ## Completeness
54
+
55
+ - [ ] All reference files mentioned in SKILL.md exist
56
+ - [ ] Reference files have table of contents if over 100 lines
57
+ - [ ] Reference files are one level deep (no nested references)
58
+ - [ ] Total SKILL.md is under 500 lines (split if over)
59
+ - [ ] Skill is self-contained (works without external dependencies)
60
+ - [ ] Installation path is correct (`.claude/skills/<skill-name>/`)
@@ -0,0 +1,370 @@
1
+ # Prompt Patterns for Claude 4.6 Skills
2
+
3
+ Patterns and anti-patterns for writing effective skill body content that works well with Claude 4.6 models.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Core Principles](#core-principles)
8
+ - [Structural Patterns](#structural-patterns)
9
+ - [Anti-Patterns](#anti-patterns)
10
+ - [Anti-Hallucination Patterns](#anti-hallucination-patterns)
11
+ - [Degree of Freedom Guide](#degree-of-freedom-guide)
12
+
13
+ ---
14
+
15
+ ## Core Principles
16
+
17
+ ### 1. Be Explicit
18
+
19
+ Claude 4.6 follows instructions precisely. Vague prompts get literal interpretations.
20
+
21
+ ```markdown
22
+ # Bad — vague
23
+ Review the code and fix issues.
24
+
25
+ # Good — explicit
26
+ Review the code for:
27
+ 1. Security vulnerabilities (SQL injection, XSS, command injection)
28
+ 2. Performance anti-patterns (N+1 queries, unnecessary re-renders)
29
+ 3. Missing error handling
30
+
31
+ For each issue found, output:
32
+ - File and line number
33
+ - Severity (critical/warning/info)
34
+ - Description of the issue
35
+ - Suggested fix with code snippet
36
+ ```
37
+
38
+ ### 2. Provide WHY Context
39
+
40
+ Claude generalizes better when it understands the reasoning behind instructions.
41
+
42
+ ```markdown
43
+ # Bad — no context
44
+ Always use `const` instead of `let`.
45
+
46
+ # Good — with WHY
47
+ Use `const` by default because it signals immutability to other developers
48
+ and prevents accidental reassignment. Only use `let` when the variable
49
+ must be reassigned within its scope.
50
+ ```
51
+
52
+ ### 3. Use XML Tags for Structure
53
+
54
+ XML tags create clear semantic boundaries. Use them for complex sections.
55
+
56
+ ```markdown
57
+ <rules>
58
+ - Never modify files outside the project directory
59
+ - Always create a backup before destructive operations
60
+ - Ask for confirmation before deleting more than 3 files
61
+ </rules>
62
+
63
+ <output-format>
64
+ ## Review Report
65
+ - **File**: {path}
66
+ - **Issues**: {count}
67
+ - **Severity**: {critical|warning|info}
68
+ </output-format>
69
+
70
+ <example>
71
+ Input: `/review src/auth.ts`
72
+ Output: Review report with 3 issues found...
73
+ </example>
74
+ ```
75
+
76
+ ### 4. Avoid "Think"
77
+
78
+ When extended thinking is disabled, "think" can cause confusion. Use alternatives:
79
+
80
+ | Instead of | Use |
81
+ |---|---|
82
+ | "Think about..." | "Consider..." |
83
+ | "Think through..." | "Evaluate..." |
84
+ | "Think step by step" | "Work through each step" |
85
+ | "Let me think" | "Let me analyze" |
86
+
87
+ ---
88
+
89
+ ## Structural Patterns
90
+
91
+ ### Pattern 1: Workflow (Most Common)
92
+
93
+ Sequential steps with clear entry/exit criteria. Best for medium-freedom skills.
94
+
95
+ ```markdown
96
+ ## Workflow
97
+
98
+ ### Step 1: Parse Input
99
+ Extract the target from `$ARGUMENTS`.
100
+ If empty, ask the user for the target.
101
+
102
+ ### Step 2: Analyze
103
+ Read the target file(s) and identify {specific things}.
104
+
105
+ ### Step 3: Generate Output
106
+ Produce {specific output format}.
107
+
108
+ ### Step 4: Validate
109
+ Verify the output meets {specific criteria}.
110
+ ```
111
+
112
+ **When to use**: Most skills. Provides clear structure while allowing flexibility within steps.
113
+
114
+ ### Pattern 2: Template (Fill-in-the-Blanks)
115
+
116
+ Fixed output structure with variable content. Best for low-freedom skills.
117
+
118
+ ```markdown
119
+ ## Output Template
120
+
121
+ Generate the following file:
122
+
123
+ \```yaml
124
+ name: {extracted-name}
125
+ version: {detected-version}
126
+ dependencies:
127
+ {for each dependency}
128
+ - name: {dep-name}
129
+ version: {dep-version}
130
+ {end for}
131
+ \```
132
+
133
+ Rules:
134
+ - `name` must be lowercase with hyphens
135
+ - `version` must follow semver (x.y.z)
136
+ - Dependencies sorted alphabetically
137
+ ```
138
+
139
+ **When to use**: Config generation, scaffolding, report generation.
140
+
141
+ ### Pattern 3: Decision Tree
142
+
143
+ Branching logic based on input analysis. Best for skills that adapt behavior.
144
+
145
+ ```markdown
146
+ ## Decision Logic
147
+
148
+ Analyze the input and follow the appropriate path:
149
+
150
+ ### Path A: Single File
151
+ If `$ARGUMENTS` points to a single file:
152
+ 1. Read the file
153
+ 2. Analyze for {criteria}
154
+ 3. Output inline suggestions
155
+
156
+ ### Path B: Directory
157
+ If `$ARGUMENTS` points to a directory:
158
+ 1. Glob for relevant files (`**/*.{ts,tsx}`)
159
+ 2. Analyze each file
160
+ 3. Output a summary report
161
+
162
+ ### Path C: No Input
163
+ If `$ARGUMENTS` is empty:
164
+ 1. Detect the project type from package.json / pyproject.toml
165
+ 2. Find the most relevant files
166
+ 3. Follow Path A or Path B based on results
167
+ ```
168
+
169
+ **When to use**: Skills that handle multiple input types or contexts.
170
+
171
+ ### Pattern 4: Conditional Workflow
172
+
173
+ Workflow with conditional steps based on context. Combines workflow + decision tree.
174
+
175
+ ```markdown
176
+ ## Workflow
177
+
178
+ ### Step 1: Detect Context
179
+ Read the project structure and determine:
180
+ - Language (TypeScript, Python, Go, etc.)
181
+ - Framework (Next.js, FastAPI, etc.)
182
+ - Test runner (Jest, Pytest, etc.)
183
+
184
+ ### Step 2: Analyze (language-specific)
185
+
186
+ **If TypeScript/JavaScript:**
187
+ - Check for type errors with LSP
188
+ - Scan for common JS anti-patterns
189
+
190
+ **If Python:**
191
+ - Check for type hints
192
+ - Scan for common Python anti-patterns
193
+
194
+ ### Step 3: Report
195
+ Output findings in a unified format regardless of language.
196
+ ```
197
+
198
+ **When to use**: Skills that work across different project types.
199
+
200
+ ### Pattern 5: Examples-Driven
201
+
202
+ Heavy use of examples to specify behavior. Best for high-freedom skills.
203
+
204
+ ```markdown
205
+ ## Behavior
206
+
207
+ Generate code following these examples exactly:
208
+
209
+ <example>
210
+ Input: "a function that fetches user data"
211
+ Output:
212
+ \```typescript
213
+ async function fetchUserData(userId: string): Promise<User> {
214
+ const response = await fetch(`/api/users/${userId}`);
215
+ if (!response.ok) {
216
+ throw new Error(`Failed to fetch user ${userId}: ${response.statusText}`);
217
+ }
218
+ return response.json();
219
+ }
220
+ \```
221
+ </example>
222
+
223
+ <example>
224
+ Input: "a React hook for local storage"
225
+ Output:
226
+ \```typescript
227
+ function useLocalStorage<T>(key: string, initialValue: T) {
228
+ const [value, setValue] = useState<T>(() => {
229
+ const stored = localStorage.getItem(key);
230
+ return stored ? JSON.parse(stored) : initialValue;
231
+ });
232
+ // ...
233
+ }
234
+ \```
235
+ </example>
236
+
237
+ Key patterns shown in examples:
238
+ - Always include error handling
239
+ - Use TypeScript generics where appropriate
240
+ - Async functions return typed Promises
241
+ ```
242
+
243
+ **When to use**: Code generation, formatting, transformation skills.
244
+
245
+ ---
246
+
247
+ ## Anti-Patterns
248
+
249
+ Common mistakes when writing Claude 4.6 skills:
250
+
251
+ | Anti-Pattern | Problem | Fix |
252
+ |---|---|---|
253
+ | Over-triggering | Description matches too many scenarios | Add specific trigger phrases: `"Use when user says X, Y, Z"` |
254
+ | Aggressive language | "You MUST", "NEVER EVER", "ABSOLUTELY" | Use calm, clear directives: "Always X", "Do not Y" |
255
+ | Vague triggers | "Use when helpful" | Specific: "Use when reviewing TypeScript code for security" |
256
+ | Wall of text | No structure, no headings | Break into steps with `###` headings |
257
+ | Conflicting rules | "Be concise" + "Include all details" | Prioritize: "Be concise. Include details only for critical issues." |
258
+ | No examples | Claude guesses at desired output | Add 1-2 concrete `<example>` blocks |
259
+ | Unbounded scope | "Analyze everything" | Limit: "Analyze files in `src/` matching `*.ts`" |
260
+ | Silent failures | No error handling instructions | Add: "When X fails, display the error and suggest next steps" |
261
+
262
+ ### Over-Triggering Fix
263
+
264
+ ```markdown
265
+ # Bad — triggers on any code question
266
+ description: Helps with code. Use for any coding task.
267
+
268
+ # Good — specific triggers
269
+ description: >
270
+ Generate unit tests for TypeScript functions using Jest.
271
+ Use when user says "generate tests", "add tests", "write tests for",
272
+ or when reviewing untested code.
273
+ ```
274
+
275
+ ### Scope Bounding
276
+
277
+ ```markdown
278
+ # Bad — unbounded
279
+ Analyze the entire codebase for issues.
280
+
281
+ # Good — bounded
282
+ Analyze files matching `$ARGUMENTS` (default: `src/**/*.ts`).
283
+ Limit to 50 files maximum. If more files match, ask the user to narrow the scope.
284
+ ```
285
+
286
+ ---
287
+
288
+ ## Anti-Hallucination Patterns
289
+
290
+ Prevent Claude from inventing information in skills:
291
+
292
+ ### 1. Ground in File Content
293
+
294
+ ```markdown
295
+ # Bad
296
+ Describe the project architecture.
297
+
298
+ # Good
299
+ Read `README.md`, `package.json`, and the `src/` directory structure.
300
+ Describe the architecture based ONLY on what these files contain.
301
+ Do not infer or assume features not present in the code.
302
+ ```
303
+
304
+ ### 2. Explicit Unknowns
305
+
306
+ ```markdown
307
+ If you cannot determine {X} from the available files:
308
+ - State "Unable to determine {X} from the codebase"
309
+ - List what files you checked
310
+ - Suggest what the user could provide to resolve this
311
+ ```
312
+
313
+ ### 3. Verify Before Acting
314
+
315
+ ```markdown
316
+ Before generating code:
317
+ 1. Read the existing implementation in `$1`
318
+ 2. Identify the patterns already used (naming, error handling, imports)
319
+ 3. Generate code that matches these existing patterns
320
+ Do not introduce new patterns or dependencies without explicit instruction.
321
+ ```
322
+
323
+ ---
324
+
325
+ ## Degree of Freedom Guide
326
+
327
+ How much latitude to give Claude based on skill type:
328
+
329
+ ### High Freedom
330
+ The skill makes autonomous decisions. Requires strong guardrails.
331
+
332
+ ```markdown
333
+ ## Guardrails
334
+ - Do NOT modify files outside `$ARGUMENTS` path
335
+ - Do NOT add new dependencies without asking
336
+ - Do NOT delete existing code without replacement
337
+ - Maximum 200 lines of generated code per invocation
338
+ - Always show a diff preview before applying changes
339
+ ```
340
+
341
+ **Examples**: code generation, refactoring, migration skills
342
+
343
+ ### Medium Freedom
344
+ The skill follows a workflow but adapts to context. Requires clear decision criteria.
345
+
346
+ ```markdown
347
+ ## Decision Criteria
348
+ - If the file has fewer than 50 lines: inline review
349
+ - If the file has 50-500 lines: section-by-section review
350
+ - If the file has more than 500 lines: focus on public API and entry points only
351
+ ```
352
+
353
+ **Examples**: review, analysis, documentation skills
354
+
355
+ ### Low Freedom
356
+ The skill executes a fixed procedure. Requires exact input/output specs.
357
+
358
+ ```markdown
359
+ ## Input
360
+ - `$1`: PR number (required, integer)
361
+ - `$2`: Template name (optional, default: "standard")
362
+
363
+ ## Output
364
+ A markdown report with exactly these sections:
365
+ 1. Summary (1-2 sentences)
366
+ 2. Checklist (pass/fail for each template requirement)
367
+ 3. Missing Items (list of unfulfilled requirements)
368
+ ```
369
+
370
+ **Examples**: validation, scanning, formatting skills