@nano-step/skill-manager 5.6.0 → 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.
Files changed (44) hide show
  1. package/dist/utils.d.ts +1 -1
  2. package/dist/utils.js +1 -1
  3. package/package.json +1 -1
  4. package/private-catalog.json +5 -0
  5. package/skills/deep-design/SKILL.md +402 -0
  6. package/skills/deep-design/evals/evals.json +23 -0
  7. package/skills/deep-design/skill.json +7 -0
  8. package/skills/feature-analysis/SKILL.md +290 -0
  9. package/skills/feature-analysis/skill.json +15 -0
  10. package/skills/nano-brain/AGENTS_SNIPPET.md +0 -9
  11. package/skills/nano-brain/skill.json +7 -0
  12. package/skills/pr-code-reviewer/CHANGELOG.md +287 -0
  13. package/skills/pr-code-reviewer/RESEARCH.md +60 -0
  14. package/skills/pr-code-reviewer/SKILL.md +530 -0
  15. package/skills/pr-code-reviewer/assets/config.json +47 -0
  16. package/skills/pr-code-reviewer/checklists/backend-express.md +357 -0
  17. package/skills/pr-code-reviewer/checklists/ci-cd.md +428 -0
  18. package/skills/pr-code-reviewer/checklists/consumer-search-matrix.md +339 -0
  19. package/skills/pr-code-reviewer/checklists/database.md +382 -0
  20. package/skills/pr-code-reviewer/checklists/frontend-vue-nuxt.md +426 -0
  21. package/skills/pr-code-reviewer/checklists/review-checklist.md +116 -0
  22. package/skills/pr-code-reviewer/references/framework-rules/express.md +39 -0
  23. package/skills/pr-code-reviewer/references/framework-rules/nestjs.md +41 -0
  24. package/skills/pr-code-reviewer/references/framework-rules/typeorm.md +52 -0
  25. package/skills/pr-code-reviewer/references/framework-rules/typescript.md +50 -0
  26. package/skills/pr-code-reviewer/references/framework-rules/vue-nuxt.md +53 -0
  27. package/skills/pr-code-reviewer/references/nano-brain-integration.md +61 -0
  28. package/skills/pr-code-reviewer/references/performance-patterns.md +26 -0
  29. package/skills/pr-code-reviewer/references/quality-patterns.md +25 -0
  30. package/skills/pr-code-reviewer/references/report-template.md +167 -0
  31. package/skills/pr-code-reviewer/references/security-patterns.md +31 -0
  32. package/skills/pr-code-reviewer/references/subagent-prompts.md +323 -0
  33. package/skills/pr-code-reviewer/skill.json +15 -0
  34. package/skills/rri-t-testing/SKILL.md +224 -0
  35. package/skills/rri-t-testing/assets/rri-t-coverage-dashboard.md +138 -0
  36. package/skills/rri-t-testing/assets/rri-t-memory-protocol.md +271 -0
  37. package/skills/rri-t-testing/assets/rri-t-persona-interview.md +249 -0
  38. package/skills/rri-t-testing/assets/rri-t-quality-scorecard.md +122 -0
  39. package/skills/rri-t-testing/assets/rri-t-risk-matrix.md +87 -0
  40. package/skills/rri-t-testing/assets/rri-t-stress-matrix.md +100 -0
  41. package/skills/rri-t-testing/assets/rri-t-test-case.md +181 -0
  42. package/skills/rri-t-testing/assets/rri-t-testability-gate.md +131 -0
  43. package/skills/rri-t-testing/assets/rri-t-traceability-matrix.md +105 -0
  44. package/skills/rri-t-testing/skill.json +9 -0
@@ -0,0 +1,426 @@
1
+ # Frontend Vue/Nuxt Checklist
2
+
3
+ Comprehensive review checklist for Vue 3/Nuxt 3 frontend PRs (tradeit, tradeit-admin, audit-dashboard-frontend, etc.)
4
+
5
+ ---
6
+
7
+ ## 1. State Management
8
+
9
+ ### CRITICAL - Must Check
10
+
11
+ | Check | Pattern | Why |
12
+ |-------|---------|-----|
13
+ | Vuex vs Pinia correct | `rootState.x` vs `useXStore()` | Vuex can't access Pinia |
14
+ | Store registered | Module in `store/index.js` | Undefined state |
15
+ | Computed get/set pattern | `computed({ get, set })` | Two-way binding |
16
+ | storeToRefs for destructuring | `storeToRefs(store)` | Maintains reactivity |
17
+
18
+ ### Detection Patterns
19
+
20
+ ```javascript
21
+ // CRITICAL: Vuex accessing Pinia store (will be undefined)
22
+ // In Vuex action:
23
+ const rate = rootState.currency.selectedRate // currency is Pinia!
24
+
25
+ // SECURE: Use Pinia directly
26
+ import { useCurrencyStore } from '~/store/useCurrencyStore'
27
+ const currencyStore = useCurrencyStore()
28
+ const rate = currencyStore.selectedRate
29
+
30
+ // CRITICAL: Store not registered
31
+ // store/index.js missing:
32
+ modules: {
33
+ // currency: currencyModule // MISSING!
34
+ }
35
+
36
+ // WARNING: Destructuring loses reactivity
37
+ const { items, loading } = useInventoryStore() // Not reactive!
38
+
39
+ // SECURE: Use storeToRefs
40
+ const store = useInventoryStore()
41
+ const { items, loading } = storeToRefs(store)
42
+
43
+ // CRITICAL: Direct mutation (Vuex)
44
+ state.items.push(newItem) // Mutation outside mutation handler!
45
+
46
+ // SECURE: Use mutation
47
+ commit('ADD_ITEM', newItem)
48
+ ```
49
+
50
+ ---
51
+
52
+ ## 2. Reactivity
53
+
54
+ ### CRITICAL - Must Check
55
+
56
+ | Check | Pattern | Why |
57
+ |-------|---------|-----|
58
+ | ref() for primitives | `ref(0)` not `reactive(0)` | reactive() doesn't work on primitives |
59
+ | .value in script | `count.value++` | Required for refs in script |
60
+ | toRefs for destructuring | `toRefs(props)` | Maintains reactivity |
61
+ | No direct prop mutation | `emit('update:x', newVal)` | One-way data flow |
62
+
63
+ ### Detection Patterns
64
+
65
+ ```javascript
66
+ // WARNING: reactive() on primitive
67
+ const count = reactive(0) // Won't work!
68
+
69
+ // SECURE: ref() for primitives
70
+ const count = ref(0)
71
+
72
+ // CRITICAL: Missing .value in script
73
+ const count = ref(0)
74
+ count++ // Wrong! count is a ref object
75
+
76
+ // SECURE: Use .value
77
+ count.value++
78
+
79
+ // CRITICAL: Mutating prop directly
80
+ props.items.push(newItem) // Mutating parent state!
81
+
82
+ // SECURE: Emit event
83
+ emit('add-item', newItem)
84
+
85
+ // WARNING: Destructuring props loses reactivity
86
+ const { modelValue } = defineProps(['modelValue'])
87
+ watch(modelValue, ...) // Won't trigger!
88
+
89
+ // SECURE: Use toRefs or computed
90
+ const props = defineProps(['modelValue'])
91
+ watch(() => props.modelValue, ...)
92
+ ```
93
+
94
+ ---
95
+
96
+ ## 3. Network Calls
97
+
98
+ ### CRITICAL - Must Check
99
+
100
+ | Check | Pattern | Why |
101
+ |-------|---------|-----|
102
+ | Use getAxiosInstance() | Not raw axios | Includes auth, base URL |
103
+ | Error handling | try/catch or .catch() | User feedback |
104
+ | Loading state managed | `loading.value = true/false` | UX |
105
+ | Response fields validated | Check before access | Defensive coding |
106
+
107
+ ### Detection Patterns
108
+
109
+ ```javascript
110
+ // WARNING: Raw axios
111
+ import axios from 'axios'
112
+ const { data } = await axios.get('/api/user')
113
+
114
+ // SECURE: Use instance
115
+ import { getAxiosInstance } from '~/network/axiosInstance'
116
+ const axios = getAxiosInstance()
117
+ const { data } = await axios.get('/api/user')
118
+
119
+ // CRITICAL: No error handling
120
+ const fetchData = async () => {
121
+ const { data } = await axios.get('/api/items')
122
+ items.value = data.items
123
+ }
124
+
125
+ // SECURE: With error handling
126
+ const fetchData = async () => {
127
+ try {
128
+ loading.value = true
129
+ const { data } = await axios.get('/api/items')
130
+ items.value = data.items
131
+ } catch (e) {
132
+ error.value = e.message
133
+ } finally {
134
+ loading.value = false
135
+ }
136
+ }
137
+
138
+ // CRITICAL: Assuming response field exists (PR #1101 issue!)
139
+ const imgUrl = item.imgURL // undefined if backend changed!
140
+
141
+ // SECURE: Defensive access
142
+ const imgUrl = item.imgURL ?? getFallbackImage(item.groupId)
143
+ ```
144
+
145
+ ---
146
+
147
+ ## 4. Component Patterns
148
+
149
+ ### CRITICAL - Must Check
150
+
151
+ | Check | Pattern | Why |
152
+ |-------|---------|-----|
153
+ | Props typed | `defineProps<{ x: string }>()` | Type safety |
154
+ | Emits declared | `defineEmits(['update:x'])` | Documentation |
155
+ | v-if/v-for not on same element | Use template wrapper | Vue limitation |
156
+ | Key on v-for | `:key="item.id"` | Efficient updates |
157
+
158
+ ### Detection Patterns
159
+
160
+ ```vue
161
+ <!-- CRITICAL: v-if and v-for on same element -->
162
+ <div v-for="item in items" v-if="item.active"> <!-- Wrong! -->
163
+
164
+ <!-- SECURE: Use template -->
165
+ <template v-for="item in items" :key="item.id">
166
+ <div v-if="item.active">...</div>
167
+ </template>
168
+
169
+ <!-- WARNING: Missing key -->
170
+ <div v-for="item in items"> <!-- No key! -->
171
+
172
+ <!-- SECURE: With key -->
173
+ <div v-for="item in items" :key="item.id">
174
+
175
+ <!-- WARNING: Untyped props -->
176
+ const props = defineProps(['modelValue', 'items'])
177
+
178
+ <!-- SECURE: Typed props -->
179
+ interface Props {
180
+ modelValue: string
181
+ items: Item[]
182
+ }
183
+ const props = defineProps<Props>()
184
+ ```
185
+
186
+ ---
187
+
188
+ ## 5. Composables
189
+
190
+ ### CRITICAL - Must Check
191
+
192
+ | Check | Pattern | Why |
193
+ |-------|---------|-----|
194
+ | Returns reactive refs | `return { items, loading }` | Reactivity preserved |
195
+ | No `this` usage | Composables don't have `this` | Runtime error |
196
+ | Cleanup on unmount | `onUnmounted(() => ...)` | Memory leaks |
197
+ | Named exports | `export function useX()` | Tree shaking |
198
+
199
+ ### Detection Patterns
200
+
201
+ ```javascript
202
+ // CRITICAL: Using this in composable
203
+ export function useInventory() {
204
+ this.items = [] // TypeError! No 'this' in composables
205
+ }
206
+
207
+ // SECURE: Use refs
208
+ export function useInventory() {
209
+ const items = ref([])
210
+ return { items }
211
+ }
212
+
213
+ // WARNING: Not returning reactive
214
+ export function useCounter() {
215
+ let count = 0 // Not reactive!
216
+ return { count }
217
+ }
218
+
219
+ // SECURE: Return refs
220
+ export function useCounter() {
221
+ const count = ref(0)
222
+ return { count }
223
+ }
224
+
225
+ // WARNING: No cleanup
226
+ export function useWebSocket() {
227
+ const ws = new WebSocket(url)
228
+ // Never closed!
229
+ }
230
+
231
+ // SECURE: Cleanup on unmount
232
+ export function useWebSocket() {
233
+ const ws = new WebSocket(url)
234
+ onUnmounted(() => ws.close())
235
+ return { ws }
236
+ }
237
+ ```
238
+
239
+ ---
240
+
241
+ ## 6. Nuxt-Specific
242
+
243
+ ### CRITICAL - Must Check
244
+
245
+ | Check | Pattern | Why |
246
+ |-------|---------|-----|
247
+ | Client-only code guarded | `import.meta.client` | SSR errors |
248
+ | Auto-imports from composables/ | Not utils/ | Only composables auto-imported |
249
+ | useFetch for SSR data | Not axios in setup | SSR hydration |
250
+ | definePageMeta for layouts | `definePageMeta({ layout: 'x' })` | Nuxt convention |
251
+
252
+ ### Detection Patterns
253
+
254
+ ```javascript
255
+ // CRITICAL: Browser API in SSR
256
+ const width = window.innerWidth // ReferenceError on server!
257
+
258
+ // SECURE: Guard with import.meta.client
259
+ const width = import.meta.client ? window.innerWidth : 0
260
+
261
+ // Or use onMounted
262
+ onMounted(() => {
263
+ width.value = window.innerWidth
264
+ })
265
+
266
+ // CRITICAL: Using function from utils/ without import
267
+ // In component:
268
+ stripImageSizeFromUrl(url) // undefined! utils/ not auto-imported
269
+
270
+ // SECURE: Import explicitly
271
+ import { stripImageSizeFromUrl } from '~/utils/helpers'
272
+
273
+ // WARNING: axios in setup (SSR issues)
274
+ const { data } = await axios.get('/api/items')
275
+
276
+ // SECURE: useFetch for SSR
277
+ const { data } = await useFetch('/api/items')
278
+ ```
279
+
280
+ ---
281
+
282
+ ## 7. i18n / Localization
283
+
284
+ ### WARNING - Should Check
285
+
286
+ | Check | Pattern | Why |
287
+ |-------|---------|-----|
288
+ | No hardcoded strings | Use `$t('key')` | Localization |
289
+ | Keys exist in locale files | Check en.js | Runtime errors |
290
+ | Interpolation correct | `$t('key', { name })` | Dynamic content |
291
+
292
+ ### Detection Patterns
293
+
294
+ ```vue
295
+ <!-- WARNING: Hardcoded string -->
296
+ <button>Submit</button>
297
+
298
+ <!-- SECURE: Use i18n -->
299
+ <button>{{ $t('common.submit') }}</button>
300
+
301
+ <!-- WARNING: Missing interpolation -->
302
+ <p>{{ $t('welcome') }}</p> <!-- "Welcome, {name}" shows literally -->
303
+
304
+ <!-- SECURE: With interpolation -->
305
+ <p>{{ $t('welcome', { name: user.name }) }}</p>
306
+ ```
307
+
308
+ ---
309
+
310
+ ## 8. Images & CDN
311
+
312
+ ### CRITICAL - Must Check
313
+
314
+ | Check | Pattern | Why |
315
+ |-------|---------|-----|
316
+ | Use useCDNImage() | Not raw URLs | CDN optimization |
317
+ | ImageWithFallback component | For item images | Handles missing images |
318
+ | Lazy loading | `loading="lazy"` | Performance |
319
+
320
+ ### Detection Patterns
321
+
322
+ ```vue
323
+ <!-- WARNING: Raw image URL -->
324
+ <img :src="item.imgURL"> <!-- No fallback if undefined! -->
325
+
326
+ <!-- SECURE: Use ImageWithFallback -->
327
+ <ImageWithFallback :src="item.imgURL" :fallback="getFallback(item)" />
328
+
329
+ <!-- WARNING: No lazy loading -->
330
+ <img :src="url">
331
+
332
+ <!-- SECURE: Lazy load -->
333
+ <img :src="url" loading="lazy">
334
+ ```
335
+
336
+ ---
337
+
338
+ ## 9. Breaking Change Detection
339
+
340
+ ### Auto-Flag These Changes
341
+
342
+ | Signal | Severity | Action |
343
+ |--------|----------|--------|
344
+ | Store module removed | CRITICAL | Search all consumers |
345
+ | Composable return value changed | CRITICAL | Search all usages |
346
+ | Network function signature changed | CRITICAL | Search all callers |
347
+ | Component prop removed | WARNING | Search all usages |
348
+ | Emit event renamed | WARNING | Search parent listeners |
349
+
350
+ ### Consumer Search Required
351
+
352
+ ```bash
353
+ # For store changes
354
+ grep -rn "useXStore" ./
355
+ grep -rn "rootState.x" ./
356
+
357
+ # For composable changes
358
+ grep -rn "useComposable" ./
359
+
360
+ # For component changes
361
+ grep -rn "<ComponentName" ./
362
+ ```
363
+
364
+ ---
365
+
366
+ ## 10. Performance Checks
367
+
368
+ ### WARNING - Should Check
369
+
370
+ | Check | Pattern | Why |
371
+ |-------|---------|-----|
372
+ | Large lists virtualized | `vue-virtual-scroller` | Memory |
373
+ | Computed for derived state | Not methods | Caching |
374
+ | v-once for static content | `<div v-once>` | Skip re-renders |
375
+ | Async components for heavy | `defineAsyncComponent` | Code splitting |
376
+
377
+ ---
378
+
379
+ ## Quick Checklist
380
+
381
+ Copy this for PR reviews:
382
+
383
+ ```markdown
384
+ ## Vue/Nuxt Frontend Review
385
+
386
+ ### State Management
387
+ - [ ] Vuex/Pinia used correctly (not mixed)
388
+ - [ ] Store modules registered
389
+ - [ ] storeToRefs used for destructuring
390
+ - [ ] No direct state mutation
391
+
392
+ ### Reactivity
393
+ - [ ] ref() for primitives, reactive() for objects
394
+ - [ ] .value used in script
395
+ - [ ] Props not mutated directly
396
+
397
+ ### Network
398
+ - [ ] getAxiosInstance() used (not raw axios)
399
+ - [ ] Error handling present
400
+ - [ ] Loading states managed
401
+ - [ ] Response fields validated (defensive)
402
+
403
+ ### Components
404
+ - [ ] Props typed with TypeScript
405
+ - [ ] Emits declared
406
+ - [ ] v-if/v-for not on same element
407
+ - [ ] Keys on v-for
408
+
409
+ ### Nuxt-Specific
410
+ - [ ] Client-only code guarded (import.meta.client)
411
+ - [ ] Auto-imports only from composables/
412
+ - [ ] useFetch for SSR data
413
+
414
+ ### i18n
415
+ - [ ] No hardcoded user-facing strings
416
+ - [ ] $t() keys exist in locale files
417
+
418
+ ### Images
419
+ - [ ] useCDNImage() or ImageWithFallback used
420
+ - [ ] Fallbacks for missing images
421
+
422
+ ### Breaking Changes
423
+ - [ ] No store modules removed without consumer check
424
+ - [ ] No composable signatures changed without search
425
+ - [ ] No component props removed without search
426
+ ```
@@ -0,0 +1,116 @@
1
+ # PR Review Checklist
2
+
3
+ Use this checklist for every PR review. Check off each item as you complete it.
4
+
5
+ ## Resume Detection (Phase -1)
6
+
7
+ - [ ] Look for existing checkpoint: `find /tmp -maxdepth 1 -type d -name "pr-review-${repo}-${pr_number}-*"`
8
+ - [ ] If found: read `manifest.json` from `.checkpoints/`
9
+ - [ ] Validate checkpoint: check PR number and head SHA match
10
+ - [ ] Ask user: "Resume from phase {next_phase}? (y/n)"
11
+ - [ ] If yes: load manifest + phase files, jump to `next_phase`
12
+ - [ ] If no or invalid: delete old directory, start fresh from Phase 0
13
+
14
+ ## Pre-Review (Phase 0)
15
+
16
+ - [ ] Extract repo info: `owner/repo`, `pr_number`, `head_branch`
17
+ - [ ] Create unique temp dir: `/tmp/pr-review-{repo}-{pr}-{timestamp}`
18
+ - [ ] Clone repo to temp dir (shallow clone with `--depth=50`)
19
+ - [ ] Verify correct branch is checked out (`git log --oneline -1`)
20
+ - [ ] Record `$REVIEW_DIR` path for all subsequent phases
21
+ - [ ] Print confirmation with path and branch name
22
+ - [ ] Save checkpoint: `.checkpoints/phase-0-clone.json`
23
+ - [ ] Update manifest: `completed_phase: 0`, `next_phase: 1`
24
+
25
+ ## Context Gathering (Phase 1)
26
+
27
+ - [ ] Get PR metadata: title, description, author, base branch
28
+ - [ ] Get changed files with diff
29
+ - [ ] Read full file context from `$REVIEW_DIR` (not workspace repo)
30
+ - [ ] Classify each file: LOGIC / STYLE / REFACTOR / NEW
31
+ - [ ] Query nano-brain for past context on changed modules
32
+ - [ ] Save checkpoint: `.checkpoints/phase-1-context.json`
33
+ - [ ] Update manifest: `completed_phase: 1`, `next_phase: 1.5`
34
+
35
+ ## Linear Ticket Context (Phase 1.5)
36
+
37
+ - [ ] Extract ticket ID from branch name, PR description, or PR title
38
+ - [ ] If found: `linear_get_issue(id)` → fetch ticket details
39
+ - [ ] If found: `linear_list_comments(issueId)` → fetch discussion
40
+ - [ ] Extract acceptance criteria from ticket description
41
+ - [ ] If images in description: `linear_extract_images(description)`
42
+ - [ ] If not found: skip silently, continue without ticket context
43
+ - [ ] Save checkpoint: `.checkpoints/phase-1.5-linear.json`
44
+ - [ ] Update manifest: `completed_phase: 1.5`, `next_phase: 2`
45
+
46
+ ## Smart Tracing (Phase 2)
47
+
48
+ - [ ] LOGIC changes: trace callers, callees, tests, types, data flow
49
+ - [ ] STYLE changes: verify no hidden logic changes
50
+ - [ ] REFACTOR changes: verify behavior preservation
51
+ - [ ] Query nano-brain for known issues on changed functions
52
+ - [ ] Save checkpoint: `.checkpoints/phase-2-tracing.json`
53
+ - [ ] Update manifest: `completed_phase: 2`, `next_phase: 2.5`
54
+
55
+ ## PR Summary (Phase 2.5)
56
+
57
+ - [ ] Write "What This PR Does" (1-3 sentences)
58
+ - [ ] Categorize key changes (Feature/Bugfix/Refactor/etc.)
59
+ - [ ] File-by-file summary with line numbers
60
+ - [ ] Save checkpoint: `.checkpoints/phase-2.5-summary.json`
61
+ - [ ] Update manifest: `completed_phase: 2.5`, `next_phase: 3`
62
+
63
+ ## Subagent Execution (Phase 3)
64
+
65
+ - [ ] Include `$REVIEW_DIR` path in ALL subagent prompts
66
+ - [ ] Launch Code Quality agent (explore)
67
+ - [ ] After Code Quality completes: update `.checkpoints/phase-3-subagents.json` + manifest subagent_status
68
+ - [ ] Launch Security & Logic agent (oracle)
69
+ - [ ] After Security & Logic completes: update `.checkpoints/phase-3-subagents.json` + manifest subagent_status
70
+ - [ ] Launch Docs & Best Practices agent (librarian)
71
+ - [ ] After Docs & Best Practices completes: update `.checkpoints/phase-3-subagents.json` + manifest subagent_status
72
+ - [ ] Launch Tests & Integration agent (general/quick)
73
+ - [ ] After Tests & Integration completes: update `.checkpoints/phase-3-subagents.json` + manifest subagent_status
74
+ - [ ] Collect ALL results (especially Oracle — never skip)
75
+ - [ ] Update manifest: `completed_phase: 3`, `next_phase: 4`
76
+
77
+ ## Refinement (Phase 4)
78
+
79
+ - [ ] Merge and deduplicate findings across agents
80
+ - [ ] Apply severity filter (critical/warning keep, suggestion count-only)
81
+ - [ ] Gap analysis — any subagent fail? Unreviewed files?
82
+ - [ ] Second pass on gaps if needed
83
+ - [ ] Save checkpoint: `.checkpoints/phase-4-refined.json`
84
+ - [ ] Update manifest: `completed_phase: 4`, `next_phase: 5`
85
+
86
+ ## Report (Phase 5)
87
+
88
+ - [ ] Save to `.opencode/reviews/{type}_{identifier}_{date}.md`
89
+ - [ ] TL;DR with verdict and counts
90
+ - [ ] Critical issues with full detail
91
+ - [ ] Warnings with full detail
92
+ - [ ] Improvements as one-liners
93
+ - [ ] File summary table
94
+ - [ ] Save checkpoint: `.checkpoints/phase-5-report.md`
95
+ - [ ] Update manifest: `completed_phase: 5`, `next_phase: 5.5`
96
+
97
+ ## Save to Memory (Phase 5.5)
98
+
99
+ - [ ] Write key findings to nano-brain with tags: review, {repo}
100
+ - [ ] Verify searchable (`npx nano-brain search "PR {number}"`)
101
+ - [ ] Update manifest: `completed_phase: 5.5`, `next_phase: 6`
102
+
103
+ ## Cleanup (Phase 6)
104
+
105
+ - [ ] Show temp folder path and size to user
106
+ - [ ] **ASK user** before removing (NEVER auto-delete)
107
+ - [ ] If user confirms → `rm -rf "$REVIEW_DIR"` (also removes `.checkpoints/`)
108
+ - [ ] If user declines → remind them to clean up later
109
+ - [ ] For multiple PRs: ask about each temp folder individually
110
+ - [ ] Note: Checkpoints auto-removed with clone dir (PR reviews) or remain in `.checkpoints/` (local reviews)
111
+
112
+ ## Final Notification
113
+
114
+ - [ ] Report path shown to user
115
+ - [ ] Issue counts (critical/warning/suggestion) displayed
116
+ - [ ] Temp folder cleanup status communicated
@@ -0,0 +1,39 @@
1
+ # Express Code Review Rules
2
+
3
+ ## Critical Rules
4
+ - Unhandled async errors in route handlers → use express-async-handler or try-catch
5
+ - SQL injection in raw queries → use parameterized queries
6
+ - Missing authentication middleware on protected routes
7
+ - Exposing sensitive data in error responses
8
+
9
+ ## Warning Rules
10
+ - Missing input validation → use express-validator or joi
11
+ - Exposing stack traces in production → check NODE_ENV
12
+ - Missing rate limiting on public endpoints
13
+ - No request body size limit → use express.json({ limit: '10kb' })
14
+
15
+ ## Suggestions
16
+ - Use helmet for security headers
17
+ - Use compression middleware
18
+ - Centralize error handling middleware
19
+ - Use router.param() for parameter validation
20
+
21
+ ## Detection Patterns
22
+
23
+ ```javascript
24
+ // CRITICAL: Unhandled async
25
+ app.get('/api', async (req, res) => {
26
+ const data = await fetchData() // if throws, crashes server
27
+ })
28
+
29
+ // SECURE: Wrapped async
30
+ app.get('/api', asyncHandler(async (req, res) => {
31
+ const data = await fetchData()
32
+ }))
33
+
34
+ // CRITICAL: SQL injection
35
+ db.query(`SELECT * FROM users WHERE id = ${req.params.id}`)
36
+
37
+ // SECURE: Parameterized
38
+ db.query('SELECT * FROM users WHERE id = ?', [req.params.id])
39
+ ```
@@ -0,0 +1,41 @@
1
+ # NestJS Code Review Rules
2
+
3
+ ## Critical Rules
4
+ - Missing `@Injectable()` decorator on service class
5
+ - Circular dependency without `forwardRef()`
6
+ - Missing guards on sensitive endpoints → use `@UseGuards()`
7
+ - Raw SQL without parameterization in repositories
8
+
9
+ ## Warning Rules
10
+ - Missing DTO validation → use `class-validator` decorators
11
+ - Missing `@ApiTags()` / `@ApiOperation()` for Swagger docs
12
+ - Injecting repository directly in controller → use service layer
13
+ - Missing `@Transactional()` on multi-step database operations
14
+
15
+ ## Suggestions
16
+ - Use `ConfigService` instead of `process.env` directly
17
+ - Use custom exceptions extending `HttpException`
18
+ - Use interceptors for response transformation
19
+ - Use pipes for input transformation
20
+
21
+ ## Detection Patterns
22
+
23
+ ```typescript
24
+ // CRITICAL: Missing Injectable
25
+ class UserService { // should be @Injectable()
26
+ constructor(private repo: UserRepository) {}
27
+ }
28
+
29
+ // WARNING: Missing validation
30
+ @Post()
31
+ create(@Body() dto: CreateUserDto) {} // dto needs class-validator decorators
32
+
33
+ // CRITICAL: Circular dependency
34
+ @Injectable()
35
+ export class ServiceA {
36
+ constructor(private serviceB: ServiceB) {} // if B also injects A
37
+ }
38
+
39
+ // SECURE: Forward ref
40
+ constructor(@Inject(forwardRef(() => ServiceB)) private serviceB: ServiceB) {}
41
+ ```
@@ -0,0 +1,52 @@
1
+ # TypeORM Code Review Rules
2
+
3
+ ## Critical Rules
4
+ - Raw SQL with string interpolation → SQL injection risk
5
+ - Missing `@Transaction()` on multi-entity operations
6
+ - Forgetting to `await` repository methods → silent failures
7
+ - Using `save()` in loops → N+1 writes, use `save([entities])`
8
+
9
+ ## Warning Rules
10
+ - N+1 query pattern → use `relations` option or `leftJoinAndSelect`
11
+ - Missing indexes on frequently queried columns
12
+ - Using `find()` without `take` limit on large tables
13
+ - Eager loading too many relations → performance hit
14
+
15
+ ## Suggestions
16
+ - Use QueryBuilder for complex queries
17
+ - Use `@Index()` decorator for query optimization
18
+ - Use `createQueryBuilder().insert()` for bulk inserts
19
+ - Consider `@DeleteDateColumn()` for soft deletes
20
+
21
+ ## Detection Patterns
22
+
23
+ ```typescript
24
+ // CRITICAL: SQL injection
25
+ repository.query(`SELECT * FROM users WHERE name = '${name}'`)
26
+
27
+ // SECURE: Parameterized
28
+ repository.query('SELECT * FROM users WHERE name = ?', [name])
29
+
30
+ // CRITICAL: N+1 in loop
31
+ for (const user of users) {
32
+ await userRepo.save(user) // N writes
33
+ }
34
+
35
+ // SECURE: Batch save
36
+ await userRepo.save(users) // 1 write
37
+
38
+ // WARNING: N+1 query
39
+ const users = await userRepo.find()
40
+ for (const user of users) {
41
+ const posts = await postRepo.find({ where: { userId: user.id } })
42
+ }
43
+
44
+ // SECURE: Eager load
45
+ const users = await userRepo.find({ relations: ['posts'] })
46
+
47
+ // WARNING: Missing limit
48
+ await userRepo.find({ where: { status: 'active' } }) // could return millions
49
+
50
+ // SECURE: With limit
51
+ await userRepo.find({ where: { status: 'active' }, take: 100 })
52
+ ```