@nano-step/skill-manager 5.6.1 → 5.6.2
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/package.json +1 -1
- package/private-catalog.json +5 -0
- package/skills/deep-design/SKILL.md +402 -0
- package/skills/deep-design/evals/evals.json +23 -0
- package/skills/deep-design/skill.json +7 -0
- package/skills/feature-analysis/SKILL.md +290 -0
- package/skills/feature-analysis/skill.json +15 -0
- package/skills/nano-brain/skill.json +7 -0
- package/skills/pr-code-reviewer/CHANGELOG.md +287 -0
- package/skills/pr-code-reviewer/RESEARCH.md +60 -0
- package/skills/pr-code-reviewer/SKILL.md +530 -0
- package/skills/pr-code-reviewer/assets/config.json +47 -0
- package/skills/pr-code-reviewer/checklists/backend-express.md +357 -0
- package/skills/pr-code-reviewer/checklists/ci-cd.md +428 -0
- package/skills/pr-code-reviewer/checklists/consumer-search-matrix.md +339 -0
- package/skills/pr-code-reviewer/checklists/database.md +382 -0
- package/skills/pr-code-reviewer/checklists/frontend-vue-nuxt.md +426 -0
- package/skills/pr-code-reviewer/checklists/review-checklist.md +116 -0
- package/skills/pr-code-reviewer/references/framework-rules/express.md +39 -0
- package/skills/pr-code-reviewer/references/framework-rules/nestjs.md +41 -0
- package/skills/pr-code-reviewer/references/framework-rules/typeorm.md +52 -0
- package/skills/pr-code-reviewer/references/framework-rules/typescript.md +50 -0
- package/skills/pr-code-reviewer/references/framework-rules/vue-nuxt.md +53 -0
- package/skills/pr-code-reviewer/references/nano-brain-integration.md +61 -0
- package/skills/pr-code-reviewer/references/performance-patterns.md +26 -0
- package/skills/pr-code-reviewer/references/quality-patterns.md +25 -0
- package/skills/pr-code-reviewer/references/report-template.md +167 -0
- package/skills/pr-code-reviewer/references/security-patterns.md +31 -0
- package/skills/pr-code-reviewer/references/subagent-prompts.md +323 -0
- package/skills/pr-code-reviewer/skill.json +15 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# TypeScript Code Review Rules
|
|
2
|
+
|
|
3
|
+
## Critical Rules
|
|
4
|
+
- Using `any` type to bypass type checking
|
|
5
|
+
- Using `@ts-ignore` or `@ts-expect-error` without justification
|
|
6
|
+
- Type assertion (`as Type`) on untrusted external data
|
|
7
|
+
- Missing null checks before accessing optional properties
|
|
8
|
+
|
|
9
|
+
## Warning Rules
|
|
10
|
+
- Non-null assertion (`!`) without prior validation
|
|
11
|
+
- Using `as unknown as Type` double assertion
|
|
12
|
+
- Implicit `any` from missing return types
|
|
13
|
+
- Using `Object` or `{}` as type → too permissive
|
|
14
|
+
|
|
15
|
+
## Suggestions
|
|
16
|
+
- Use `unknown` instead of `any` for external data, then narrow
|
|
17
|
+
- Use discriminated unions for state machines
|
|
18
|
+
- Use `satisfies` operator for type checking without widening
|
|
19
|
+
- Use `readonly` for immutable data structures
|
|
20
|
+
|
|
21
|
+
## Detection Patterns
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
// CRITICAL: any type
|
|
25
|
+
const data: any = await fetchData()
|
|
26
|
+
data.whatever.you.want // no type safety
|
|
27
|
+
|
|
28
|
+
// SECURE: unknown + narrowing
|
|
29
|
+
const data: unknown = await fetchData()
|
|
30
|
+
if (isUserData(data)) {
|
|
31
|
+
data.name // type-safe
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// CRITICAL: Unsafe assertion
|
|
35
|
+
const user = JSON.parse(input) as User // input could be anything
|
|
36
|
+
|
|
37
|
+
// SECURE: Runtime validation
|
|
38
|
+
const user = userSchema.parse(JSON.parse(input)) // zod/yup validation
|
|
39
|
+
|
|
40
|
+
// WARNING: Non-null assertion without check
|
|
41
|
+
function process(user?: User) {
|
|
42
|
+
return user!.name // crashes if undefined
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// SECURE: With guard
|
|
46
|
+
function process(user?: User) {
|
|
47
|
+
if (!user) throw new Error('User required')
|
|
48
|
+
return user.name
|
|
49
|
+
}
|
|
50
|
+
```
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Vue 3 / Nuxt 3 Code Review Rules
|
|
2
|
+
|
|
3
|
+
## Critical Rules
|
|
4
|
+
|
|
5
|
+
### State Management (Vuex ↔ Pinia)
|
|
6
|
+
- `rootState.{module}` where module is Pinia store → Vuex cannot access Pinia state
|
|
7
|
+
- `useStore()` in Pinia-only context → wrong store type
|
|
8
|
+
- Store module exists but not registered in `store/index.js`
|
|
9
|
+
- Pinia store file missing `export` or `defineStore`
|
|
10
|
+
|
|
11
|
+
### Auto-Import Gotchas (Nuxt)
|
|
12
|
+
- Using function from `utils/` without import → only `composables/` auto-imported
|
|
13
|
+
- Using `defineStore` without import when `@pinia/nuxt` not in modules
|
|
14
|
+
|
|
15
|
+
### Component Issues
|
|
16
|
+
- Mutating props directly
|
|
17
|
+
- `v-if` and `v-for` on same element
|
|
18
|
+
|
|
19
|
+
## Warning Rules
|
|
20
|
+
|
|
21
|
+
### State Management
|
|
22
|
+
- Mixed `useStore()` and `use*Store()` in same composable
|
|
23
|
+
- Vuex action accessing Pinia store via workaround
|
|
24
|
+
- `rootState.{x}` or `rootGetters['{x}/...']` → verify module exists
|
|
25
|
+
|
|
26
|
+
### Reactivity
|
|
27
|
+
- Using `reactive()` for primitives → use `ref()`
|
|
28
|
+
- Destructuring reactive object without `toRefs()` or `storeToRefs()`
|
|
29
|
+
- Missing `.value` on ref in script (not template)
|
|
30
|
+
|
|
31
|
+
### Composables
|
|
32
|
+
- Composable not returning reactive refs
|
|
33
|
+
- Using `this` in composable (not available in setup)
|
|
34
|
+
|
|
35
|
+
## Suggestions
|
|
36
|
+
- Use `storeToRefs()` when destructuring Pinia store
|
|
37
|
+
- Use `computed` for derived state
|
|
38
|
+
- Prefer Pinia for new stores (migration in progress)
|
|
39
|
+
- Use `<script setup>` syntax for components
|
|
40
|
+
|
|
41
|
+
## Detection Patterns
|
|
42
|
+
|
|
43
|
+
```javascript
|
|
44
|
+
// CRITICAL: Vuex accessing Pinia (will be undefined)
|
|
45
|
+
rootState.currency.selectedRate // if currency is Pinia store
|
|
46
|
+
|
|
47
|
+
// WARNING: Check if module exists
|
|
48
|
+
rootState.{moduleName} // verify in store/index.js modules: { {moduleName} }
|
|
49
|
+
|
|
50
|
+
// CRITICAL: Missing import in utils (not auto-imported)
|
|
51
|
+
// In component using function from utils/helpers.js without import
|
|
52
|
+
stripImageSizeFromUrl(url) // will be undefined if not imported
|
|
53
|
+
```
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# nano-brain Integration
|
|
2
|
+
|
|
3
|
+
nano-brain provides persistent memory across sessions. The reviewer uses it for historical context about changed files:
|
|
4
|
+
- Past review findings and architectural decisions
|
|
5
|
+
- Known issues and tech debt in affected modules
|
|
6
|
+
- Prior discussions about the same code areas
|
|
7
|
+
|
|
8
|
+
## Access Method: CLI
|
|
9
|
+
|
|
10
|
+
All nano-brain operations use the CLI via Bash tool:
|
|
11
|
+
|
|
12
|
+
| Need | CLI Command |
|
|
13
|
+
|------|-------------|
|
|
14
|
+
| Hybrid search (best quality) | `npx nano-brain query "search terms"` |
|
|
15
|
+
| Keyword search (function name, error) | `npx nano-brain query "exact term" -c codebase` |
|
|
16
|
+
| Save review findings | `npx nano-brain write "content" --tags=review` |
|
|
17
|
+
|
|
18
|
+
## Setup
|
|
19
|
+
|
|
20
|
+
Run `/nano-brain-init` in the workspace, or `npx nano-brain init --root=/path/to/workspace`.
|
|
21
|
+
|
|
22
|
+
## Phase 1 Memory Queries
|
|
23
|
+
|
|
24
|
+
For each significantly changed file/module:
|
|
25
|
+
- **Hybrid search**: `npx nano-brain query "<module-name>"` (best quality, combines BM25 + vector + reranking)
|
|
26
|
+
- **Scoped search**: `npx nano-brain query "<function-name>" -c codebase` for code-specific results
|
|
27
|
+
|
|
28
|
+
Specific queries:
|
|
29
|
+
- Past review findings: `npx nano-brain query "review <module-name>"`
|
|
30
|
+
- Architectural decisions: `npx nano-brain query "<module-name> architecture design decision"`
|
|
31
|
+
- Known issues: `npx nano-brain query "<function-name> bug issue regression"`
|
|
32
|
+
|
|
33
|
+
Collect relevant memory hits as `projectMemory` context for subagents.
|
|
34
|
+
|
|
35
|
+
## Phase 2 Memory Queries (LOGIC changes)
|
|
36
|
+
|
|
37
|
+
Query nano-brain for known issues:
|
|
38
|
+
```bash
|
|
39
|
+
npx nano-brain query "<function-name> bug issue edge case regression"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Phase 5.5: Save Review to nano-brain
|
|
43
|
+
|
|
44
|
+
After generating the report, save key findings for future sessions:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npx nano-brain write "## Code Review: PR #<number> - <title>
|
|
48
|
+
Date: <date>
|
|
49
|
+
Files: <changed_files>
|
|
50
|
+
|
|
51
|
+
### Key Findings
|
|
52
|
+
<critical_issues_summary>
|
|
53
|
+
<warnings_summary>
|
|
54
|
+
|
|
55
|
+
### Decisions
|
|
56
|
+
<architectural_decisions_noted>
|
|
57
|
+
|
|
58
|
+
### Recommendation: <APPROVE|REQUEST_CHANGES|COMMENT>" --tags=review,pr-<number>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
This ensures future reviews can reference past findings on the same codebase areas.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Performance Patterns
|
|
2
|
+
|
|
3
|
+
## N+1 Queries
|
|
4
|
+
```javascript
|
|
5
|
+
// CRITICAL: N+1 pattern
|
|
6
|
+
const users = await db.query('SELECT * FROM users');
|
|
7
|
+
for (const user of users) {
|
|
8
|
+
const posts = await db.query('SELECT * FROM posts WHERE user_id = ?', [user.id]);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// SECURE: Eager loading
|
|
12
|
+
const users = await db.query(`
|
|
13
|
+
SELECT u.*, p.* FROM users u
|
|
14
|
+
LEFT JOIN posts p ON u.id = p.user_id
|
|
15
|
+
`);
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## React Re-renders
|
|
19
|
+
```jsx
|
|
20
|
+
// WARNING: Inline function
|
|
21
|
+
<button onClick={() => handleClick(id)}>
|
|
22
|
+
|
|
23
|
+
// BETTER: useCallback
|
|
24
|
+
const handleClick = useCallback(() => { ... }, [id]);
|
|
25
|
+
<button onClick={handleClick}>
|
|
26
|
+
```
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Quality Patterns
|
|
2
|
+
|
|
3
|
+
## Type Safety
|
|
4
|
+
```typescript
|
|
5
|
+
// WARNING: any type
|
|
6
|
+
const data: any = getData();
|
|
7
|
+
|
|
8
|
+
// BETTER: Proper typing
|
|
9
|
+
interface UserData { id: string; name: string; }
|
|
10
|
+
const data: UserData = getData();
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Error Handling
|
|
14
|
+
```javascript
|
|
15
|
+
// CRITICAL: Silent catch
|
|
16
|
+
try { await doSomething(); } catch (e) { }
|
|
17
|
+
|
|
18
|
+
// BETTER: Proper handling
|
|
19
|
+
try {
|
|
20
|
+
await doSomething();
|
|
21
|
+
} catch (error) {
|
|
22
|
+
logger.error('Operation failed', { error });
|
|
23
|
+
throw new CustomError('Operation failed', error);
|
|
24
|
+
}
|
|
25
|
+
```
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# Report Template
|
|
2
|
+
|
|
3
|
+
Save to `.opencode/reviews/{type}_{identifier}_{date}.md`.
|
|
4
|
+
Create `.opencode/reviews/` if it does not exist.
|
|
5
|
+
|
|
6
|
+
## Design Principle
|
|
7
|
+
|
|
8
|
+
**Short and meaningful.** People don't read long reports. Every section must earn its place.
|
|
9
|
+
|
|
10
|
+
- Critical + Warning = full detail (file, line, impact, fix)
|
|
11
|
+
- Improvements = one-liner with code suggestion
|
|
12
|
+
- Suggestions = count only (or brief list if < 3)
|
|
13
|
+
- Empty sections = omit entirely
|
|
14
|
+
- TL;DR at the top so the reader can stop after 3 lines if everything is clean
|
|
15
|
+
|
|
16
|
+
## Template
|
|
17
|
+
|
|
18
|
+
```markdown
|
|
19
|
+
# Code Review: PR #{number} — {pr_title}
|
|
20
|
+
|
|
21
|
+
## TL;DR
|
|
22
|
+
|
|
23
|
+
**{APPROVE | REQUEST CHANGES | COMMENT}** — {one sentence reason}
|
|
24
|
+
|
|
25
|
+
| Critical | Warnings | Improvements | Suggestions |
|
|
26
|
+
|----------|----------|--------------|-------------|
|
|
27
|
+
| {count} | {count} | {count} | {count} |
|
|
28
|
+
|
|
29
|
+
{If Phase 4.5 dropped findings: "🔍 Verification: {N} finding(s) dropped as false positives"}
|
|
30
|
+
{If Phase 4.5 verified all findings: "🔍 All findings verified"}
|
|
31
|
+
{If Phase 4.5 was skipped (no critical/warning): omit this line entirely}
|
|
32
|
+
|
|
33
|
+
## What This PR Does
|
|
34
|
+
|
|
35
|
+
{1-3 sentences. Start with action verb. Include business impact if clear.}
|
|
36
|
+
|
|
37
|
+
**Key Changes:**
|
|
38
|
+
- **{category}**: {brief description}
|
|
39
|
+
- **{category}**: {brief description}
|
|
40
|
+
|
|
41
|
+
## Ticket Alignment
|
|
42
|
+
|
|
43
|
+
> Only included when a Linear ticket is linked. Omit entirely if no ticket found.
|
|
44
|
+
|
|
45
|
+
**Ticket**: [{ticket_id}]({linear_url}) — {ticket_title}
|
|
46
|
+
**Status**: {ticket_status} | **Priority**: {ticket_priority}
|
|
47
|
+
|
|
48
|
+
### Acceptance Criteria Coverage
|
|
49
|
+
|
|
50
|
+
| # | Criteria | Status | Notes |
|
|
51
|
+
|---|----------|--------|-------|
|
|
52
|
+
| 1 | {criteria_text} | ✅ Met / ⚠️ Partial / ❌ Missing | {brief note} |
|
|
53
|
+
|
|
54
|
+
{If all criteria met: "All acceptance criteria addressed."}
|
|
55
|
+
{If gaps found: "**{count} criteria not fully addressed** — see details above."}
|
|
56
|
+
{If criteria are ambiguous: "⚠️ **Ambiguous acceptance criteria** — '{original_text}' can be interpreted as: (a) {interpretation_1}, (b) {interpretation_2}. This PR implements interpretation (a/b). Verify with ticket author."}
|
|
57
|
+
|
|
58
|
+
## Premise Check (DELETION changes only)
|
|
59
|
+
|
|
60
|
+
> Only included when the PR deletes existing behavior. Omit for additions/modifications.
|
|
61
|
+
|
|
62
|
+
| Question | Answer |
|
|
63
|
+
|----------|--------|
|
|
64
|
+
| Why was this code added originally? | {reason} |
|
|
65
|
+
| Is the underlying problem solved? | {yes/no — explanation} |
|
|
66
|
+
| Would fixing the logic be more correct? | {yes/no — explanation} |
|
|
67
|
+
| Cross-repo implications? | {backend config, API contracts, etc.} |
|
|
68
|
+
|
|
69
|
+
**Verdict**: {REMOVAL CORRECT / SHOULD FIX INSTEAD / NEEDS CLARIFICATION}
|
|
70
|
+
|
|
71
|
+
## Critical Issues (MUST FIX)
|
|
72
|
+
|
|
73
|
+
### 1. {Title}
|
|
74
|
+
**`{file}:{line}`** | {Security/Logic/Performance}
|
|
75
|
+
{What's wrong and what could go wrong.}
|
|
76
|
+
**Fix:** {Concrete suggestion or code snippet}
|
|
77
|
+
|
|
78
|
+
### 2. {Title}
|
|
79
|
+
...
|
|
80
|
+
|
|
81
|
+
## Warnings (SHOULD FIX)
|
|
82
|
+
|
|
83
|
+
### 1. {Title}
|
|
84
|
+
**`{file}:{line}`** | {Category}
|
|
85
|
+
{Issue description.}
|
|
86
|
+
**Fix:** {Suggestion}
|
|
87
|
+
|
|
88
|
+
## Code Improvements
|
|
89
|
+
|
|
90
|
+
> Opportunities to make the code better — cleaner, faster, more idiomatic.
|
|
91
|
+
|
|
92
|
+
- **`{file}:{line}`** — {description}. Consider: `{code_suggestion}`
|
|
93
|
+
- **`{file}:{line}`** — {description}
|
|
94
|
+
|
|
95
|
+
## Suggestions ({count})
|
|
96
|
+
|
|
97
|
+
{If ≤ 3, list as one-liners. If > 3, just show the count.}
|
|
98
|
+
|
|
99
|
+
- `{file}:{line}` — {brief}
|
|
100
|
+
|
|
101
|
+
## Files Changed
|
|
102
|
+
|
|
103
|
+
| File | Type | Summary |
|
|
104
|
+
|------|------|---------|
|
|
105
|
+
| `{path}` | {LOGIC/DELETION/STYLE/REFACTOR/NEW} | {one-liner} |
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Sections to OMIT unless they contain actionable findings:**
|
|
109
|
+
- Traced Dependencies
|
|
110
|
+
- nano-brain Memory Context
|
|
111
|
+
- Test Coverage Analysis
|
|
112
|
+
- Praise (include only if genuinely noteworthy — one line max)
|
|
113
|
+
- Change Classification table
|
|
114
|
+
|
|
115
|
+
## PR Summary Generation Guidelines
|
|
116
|
+
|
|
117
|
+
### What This PR Does (1-3 sentences)
|
|
118
|
+
- Start with action verb: "Adds", "Fixes", "Refactors", "Updates"
|
|
119
|
+
- Mention the feature/bug/improvement
|
|
120
|
+
- Include business impact if clear
|
|
121
|
+
|
|
122
|
+
### Key Changes categories
|
|
123
|
+
- `Feature`: New functionality
|
|
124
|
+
- `Bugfix`: Fixes broken behavior
|
|
125
|
+
- `Refactor`: Code restructuring without behavior change
|
|
126
|
+
- `Performance`: Speed/memory improvements
|
|
127
|
+
- `Security`: Security fixes or hardening
|
|
128
|
+
- `Docs`: Documentation updates
|
|
129
|
+
- `Tests`: Test additions/modifications
|
|
130
|
+
- `Config`: Configuration changes
|
|
131
|
+
- `Dependencies`: Package updates
|
|
132
|
+
|
|
133
|
+
### File-by-File Summary
|
|
134
|
+
- **What changed**: Factual description of the code change
|
|
135
|
+
- **Why it matters**: Impact on users, developers, or system
|
|
136
|
+
- **Key modifications**: Specific functions/classes/lines changed
|
|
137
|
+
|
|
138
|
+
## PR Summary Pseudocode
|
|
139
|
+
|
|
140
|
+
```javascript
|
|
141
|
+
// Generate PR Summary (GitHub Copilot style)
|
|
142
|
+
const prSummary = `
|
|
143
|
+
## PR Overview
|
|
144
|
+
|
|
145
|
+
### What This PR Does
|
|
146
|
+
${generateHighLevelSummary(prMetadata, changedFiles)}
|
|
147
|
+
|
|
148
|
+
### Key Changes
|
|
149
|
+
${categorizeChanges(changedFiles).map(c => `- **${c.category}**: ${c.description}`).join('\n')}
|
|
150
|
+
|
|
151
|
+
## File-by-File Summary
|
|
152
|
+
|
|
153
|
+
| File | Change Type | Summary |
|
|
154
|
+
|------|-------------|---------|
|
|
155
|
+
${changedFiles.map(f => `| \`${f.path}\` | ${f.changeType} | ${f.oneLinerSummary} |`).join('\n')}
|
|
156
|
+
|
|
157
|
+
### Detailed File Changes
|
|
158
|
+
|
|
159
|
+
${changedFiles.map(f => `
|
|
160
|
+
#### \`${f.path}\` (+${f.additions}/-${f.deletions})
|
|
161
|
+
**What changed**: ${f.whatChanged}
|
|
162
|
+
**Why it matters**: ${f.whyItMatters}
|
|
163
|
+
**Key modifications**:
|
|
164
|
+
${f.keyModifications.map(m => `- ${m}`).join('\n')}
|
|
165
|
+
`).join('\n')}
|
|
166
|
+
`;
|
|
167
|
+
```
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Security Patterns
|
|
2
|
+
|
|
3
|
+
## OWASP Top 10 Detection
|
|
4
|
+
|
|
5
|
+
### 1. Injection
|
|
6
|
+
```javascript
|
|
7
|
+
// CRITICAL: SQL Injection
|
|
8
|
+
const query = `SELECT * FROM users WHERE id = ${userId}`;
|
|
9
|
+
|
|
10
|
+
// SECURE: Parameterized query
|
|
11
|
+
const query = 'SELECT * FROM users WHERE id = ?';
|
|
12
|
+
await db.query(query, [userId]);
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### 2. Broken Authentication
|
|
16
|
+
```javascript
|
|
17
|
+
// CRITICAL: Weak hashing
|
|
18
|
+
crypto.createHash('md5').update(password);
|
|
19
|
+
|
|
20
|
+
// SECURE: Strong hashing
|
|
21
|
+
bcrypt.hash(password, 12);
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### 3. XSS
|
|
25
|
+
```javascript
|
|
26
|
+
// CRITICAL: Direct HTML insertion
|
|
27
|
+
element.innerHTML = userInput;
|
|
28
|
+
|
|
29
|
+
// SECURE: Text content
|
|
30
|
+
element.textContent = userInput;
|
|
31
|
+
```
|