GitHub Code Review - System automatycznego review
Przegląd
System działa w dwóch trybach dla procesu code review na GitHub:
MODE A: REVIEW (system recenzuje czyjś kod)
┌─────────────────────────────────────────────┐
│ n8n wykrywa: User przypisany jako reviewer │
│ na PR │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ Ustawia start_commands: github-review │
│ mode=review │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ System: │
│ 1. Pobiera PR (branch, diff, files) │
│ 2. Pobiera kontekst (issue, comments) │
│ 3. Analizuje kod (quality, logic, tests) │
│ 4. Generuje review comments (konstruktywne)│
│ 5. Publikuje w GitHub │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ Author odpowiada na komentarze │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ n8n wykrywa odpowiedź → trigger iteracji │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ System: │
│ 1. Czyta odpowiedzi authora │
│ 2. Weryfikuje zmiany w kodzie │
│ 3. DECYZJA: │
│ • Akceptuje → Approve PR │
│ • Kontynuuje dyskusję → Reply │
│ • Request changes → Kolejne uwagi │
└─────────────────────────────────────────────┘
MODE B: RESPOND (system odpowiada na review swojego kodu)
┌─────────────────────────────────────────────┐
│ n8n wykrywa: Nowy review comment │
│ na PR systemu │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ Ustawia start_commands: github-review │
│ mode=respond │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ System: │
│ 1. Pobiera review comments │
│ 2. Analizuje każdą uwagę │
│ 3. DECYZJA dla każdej uwagi: │
│ • Zasadna → Wprowadź zmiany w kodzie │
│ • Dyskusyjna → Wyjaśnij reasoning │
│ • Niejasna → Poproś o wyjaśnienie │
│ 4. Commit zmian (jeśli konieczne) │
│ 5. Reply na wszystkie komentarze │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ Reviewer weryfikuje odpowiedzi/zmiany │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ Proces powtarza się do: │
│ • PR Approved │
│ • Changes requested (max iteracji) │
└─────────────────────────────────────────────┘Workflow n8n
Trigger 1: User przypisany jako reviewer (MODE A: REVIEW)
Gdy: GitHub webhook: pull_request.review_requested gdzie assignee to system bot
Warunek:
- Reviewer to bot user (np.
code-gen-bot) - PR nie jest draft
- PR jest do review
Akcje n8n:
Utwórz task w systemie (jeśli nie istnieje)
json{ "task_id": "REVIEW-{PR_NUMBER}", "title": "Code Review: {PR_TITLE}", "issue": { "id": "PR-{REPO}-{NUMBER}", "url": "{PR_URL}", "author_id": "{PR_AUTHOR}", "assignee_id": "code-gen-bot" }, "repositories": [{ "folder": "{REPO_NAME}", "git_url": "{REPO_GIT_URL}", "target_branch": "{BASE_BRANCH}", "working_branch": "{HEAD_BRANCH}", "merge_request_id": "{PR_NUMBER}", "merge_request_url": "{PR_URL}" }] }Ustaw start_commands dla MODE A: REVIEW
json{ "ai": { "start_commands": [ { "id": "init_workspace", "catalog": "START", "executor": "bash", "command": "bash /workspace/files/helpers/init_workspace.sh", "dependencies": [] }, { "id": "github_pr_fetch", "catalog": "START", "executor": "bash", "command": "bash /workspace/files/helpers/github_pr_fetch.sh \"{PR_URL}\" \"/task/.spec/github\"", "dependencies": ["init_workspace"] }, { "id": "github_review_perform", "catalog": "START", "executor": "claude", "command": "/plugin-codegen:github-review /task --mode=review --iteration=1", "dependencies": ["github_pr_fetch"] } ] }, "github_review": { "mode": "review", "iteration": 1, "pr_number": 123, "pr_url": "...", "status": "in_progress", "last_review_id": null } }Przenieś task do TODO (system go podejmie)
Powiadomienie Mattermost:
📝 Code Review: PR #{NUMBER} - {TITLE} Reviewer: @code-gen-bot Author: @{AUTHOR} Branch: {HEAD} → {BASE}
Trigger 2: Author odpowiedział na review (MODE A: ITERACJA)
Gdy: GitHub webhook: pull_request_review_comment where:
- Comment jest odpowiedzią na review comment systemu
- PR w którym system jest reviewerem
Akcje n8n:
Odczytaj task.json
Sprawdź status review
javascriptif (task_json.github_review.mode === "review" && task_json.github_review.status === "awaiting_author") { // Przejdź do kolejnej iteracji }Zwiększ iteration counter
json{ "github_review": { "mode": "review", "iteration": 2, "status": "review_iteration", "last_review_id": "...", "last_comment_id": "..." } }Zmień start_commands na iterację
json{ "ai": { "start_commands": [ { "id": "init_workspace", "catalog": "START", "executor": "bash", "command": "bash /workspace/files/helpers/init_workspace.sh", "dependencies": [] }, { "id": "github_pr_refresh", "catalog": "START", "executor": "bash", "command": "bash /workspace/files/helpers/github_pr_fetch.sh \"{PR_URL}\" \"/task/.spec/github\" --refresh", "dependencies": ["init_workspace"] }, { "id": "github_review_iterate", "catalog": "START", "executor": "claude", "command": "/plugin-codegen:github-review /task --mode=review --iteration=2", "dependencies": ["github_pr_refresh"] } ] } }Przenieś task do TODO (wznów review)
Powiadomienie:
💬 Code Review PR #{NUMBER} - Author odpowiedział Wznowienie review (iteracja 2)
Trigger 3: Nowy review comment na PR systemu (MODE B: RESPOND)
Gdy: GitHub webhook: pull_request_review lub pull_request_review_comment where:
- PR stworzony przez system (branch:
claude/{TASK_ID}) - Review od innego usera (nie bota)
Akcje n8n:
Znajdź task dla tego PR (przez
merge_request_urlw task.json)Ustaw start_commands dla MODE B: RESPOND
json{ "ai": { "start_commands": [ { "id": "init_workspace", "catalog": "START", "executor": "bash", "command": "bash /workspace/files/helpers/init_workspace.sh", "dependencies": [] }, { "id": "github_pr_fetch_own", "catalog": "START", "executor": "bash", "command": "bash /workspace/files/helpers/github_pr_fetch.sh \"{PR_URL}\" \"/task/.spec/github\" --own", "dependencies": ["init_workspace"] }, { "id": "github_review_respond", "catalog": "START", "executor": "claude", "command": "/plugin-codegen:github-review /task --mode=respond --iteration=1", "dependencies": ["github_pr_fetch_own"] }, { "id": "github_push_changes", "catalog": "END", "executor": "bash", "command": "bash /workspace/files/helpers/github_push_changes.sh", "dependencies": ["github_review_respond"] } ] }, "github_review": { "mode": "respond", "iteration": 1, "pr_number": 456, "pr_url": "...", "status": "responding", "reviewer_id": "{REVIEWER}", "last_review_id": "..." } }Przenieś task do TODO (jeśli był done - reactive)
Powiadomienie:
📬 Review otrzymany na PR #{NUMBER} Reviewer: @{REVIEWER} Comments: {COUNT} System przygotowuje odpowiedź...
Trigger 4: PR zaakceptowany (COMPLETION)
Gdy: GitHub webhook: pull_request_review where:
- Review state:
approved - PR systemu lub PR gdzie system jest reviewerem
Akcje n8n:
Update task.json
json{ "github_review": { "status": "approved", "approved_at": "2026-01-06T10:00:00Z", "approved_by": "{APPROVER}" } }Powiadomienie:
✅ PR #{NUMBER} zaakceptowany! Approver: @{APPROVER}Jeśli MODE A (system recenzował):
- Zamknij task → done
Jeśli MODE B (system odpowiadał):
- Merge PR (jeśli auto-merge enabled)
- Zamknij task → done
Komenda Claude: /github-review
Parametry
/plugin-codegen:github-review <task_path> --mode=review|respond --iteration=NMode: review (system recenzuje)
Przepływ:
1. READ GitHub PR context:
- /task/.spec/github/PR_CONTEXT.md (opis PR, linked issues)
- /task/.spec/github/pr_diff.patch (pełny diff)
- /task/.spec/github/files_changed.json (lista zmienionych plików)
- /task/.spec/github/review_comments.json (istniejące komentarze)
2. CHECKOUT branch:
- git fetch origin {head_branch}
- git checkout {head_branch}
3. ANALIZA KODU (per file):
For each file in files_changed:
a) READ file content (current state)
b) READ diff for this file
c) ANALYZE:
- Code quality (naming, structure, complexity)
- Logic correctness (bugs, edge cases)
- Best practices (patterns, anti-patterns)
- Tests coverage (czy są testy dla zmian)
- Security (SQL injection, XSS, etc.)
- Performance (N+1, memory leaks, etc.)
d) GENERATE review comments (inline + general)
4. FILTRUJ komentarze:
- Tylko konstruktywne uwagi
- Konkretne sugestie (nie ogólniki)
- Przykłady kodu (jeśli możliwe)
- Priorytet: 🔴 Critical | 🟡 Important | 🟢 Nice-to-have
5. ZAPISZ review:
- /task/.spec/github/REVIEW_iteration_{N}.md
- Format: GitHub review markdown
6. PUBLIKUJ review (przez webhook):
- Event: `github_review_generated`
- Payload: review comments + decision
7. DECYZJA:
- Jeśli CRITICAL issues → REQUEST_CHANGES
- Jeśli tylko IMPORTANT → COMMENT (nie blokuj)
- Jeśli tylko NICE-TO-HAVE lub brak → APPROVEStruktura REVIEW_{iteration}.md:
# Code Review - Iteration {N}
## 📊 Summary
- **Files reviewed:** 5
- **Lines changed:** +234 / -156
- **Comments:** 12 (🔴 2 critical, 🟡 5 important, 🟢 5 nice-to-have)
- **Decision:** REQUEST_CHANGES / COMMENT / APPROVE
## 🔴 Critical Issues (must fix)
### src/app/services/user.service.ts:45
**Issue:** SQL Injection vulnerability
```typescript
// Current (VULNERABLE)
const query = `SELECT * FROM users WHERE id = ${userId}`;
// Suggested fix
const query = `SELECT * FROM users WHERE id = ?`;
db.query(query, [userId]);Reasoning: Direct string interpolation allows SQL injection. Use parameterized queries.
src/app/components/login/login.component.ts:120
Issue: Password stored in plain text
// Current (INSECURE)
localStorage.setItem('password', password);
// Suggested fix
// Don't store passwords client-side at all
// Use token-based authenticationReasoning: Security best practice - never store passwords on client.
🟡 Important Issues (should fix)
src/app/services/api.service.ts:78
Issue: Missing error handling
// Current
async getData() {
const response = await fetch(url);
return response.json();
}
// Suggested
async getData() {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response.json();
} catch (error) {
console.error('API error:', error);
throw error;
}
}Reasoning: Unhandled network errors will crash the app.
🟢 Nice-to-have (optional improvements)
src/app/components/navbar/navbar.component.ts:23
Suggestion: Extract magic number to constant
// Current
if (items.length > 10) { ... }
// Suggested
private readonly MAX_ITEMS = 10;
if (items.length > this.MAX_ITEMS) { ... }Reasoning: Improves maintainability and readability.
✅ Positive Observations
- Good test coverage for user service (85%)
- Clean component structure
- Proper use of TypeScript types
- Consistent code style
📝 General Comments
- Tests missing: No tests for login component - please add
- Documentation: Consider adding JSDoc for public methods
- Performance: Consider lazy loading for heavy modules
🎯 Next Steps
- Fix critical issues (SQL injection, password storage)
- Address important issues (error handling)
- Add tests for login component
- (Optional) Apply nice-to-have suggestions
Review by: @code-gen-bot Date: 2026-01-06 10:00:00 Iteration: 1
**Webhook payload:**
```json
{
"event": "github_review_generated",
"mode": "review",
"iteration": 1,
"pr": {
"number": 123,
"url": "...",
"author": "developer123",
"branch": "feature/user-login"
},
"review": {
"decision": "REQUEST_CHANGES",
"files_reviewed": 5,
"lines_changed": {
"additions": 234,
"deletions": 156
},
"comments": {
"total": 12,
"critical": 2,
"important": 5,
"nice_to_have": 5
},
"critical_issues": [
{
"file": "src/app/services/user.service.ts",
"line": 45,
"issue": "SQL Injection vulnerability",
"severity": "critical"
},
{
"file": "src/app/components/login/login.component.ts",
"line": 120,
"issue": "Password stored in plain text",
"severity": "critical"
}
]
},
"actions_requested": {
"github": {
"create_review": true,
"review_state": "REQUEST_CHANGES",
"review_body": "...",
"inline_comments": [
{
"path": "src/app/services/user.service.ts",
"line": 45,
"body": "🔴 **SQL Injection vulnerability**\n\n..."
}
]
},
"mattermost": {
"send_notification": true,
"message": "📝 Review completed for PR #123\n🔴 2 critical issues found\n🟡 5 important issues\nDecision: REQUEST_CHANGES"
}
}
}Mode: respond (system odpowiada na review)
Przepływ:
1. READ review comments:
- /task/.spec/github/review_comments.json (wszystkie comments)
- /task/.spec/github/last_review_id.txt (ostatni przetworzony review)
2. FILTER nowe comments:
- Gdzie comment_id > last_review_id
- Group by file + line
3. For each comment:
a) READ kontekst:
- Plik którego dotyczy
- Linia kodu
- Thread (jeśli jest odpowiedź)
b) ANALIZA uwagi:
- Czy zasadna? (logic check)
- Czy dotyczy security/performance/correctness?
- Czy to preferencja stylowa?
c) DECYZJA:
IF zasadna (bug/security/logic issue):
→ FIX code
→ Git commit
→ Reply: "✅ Fixed. {explanation}"
ELSE IF warto rozważyć (performance/best practice):
→ EVALUATE: czy improvement znaczący?
→ IF tak:
→ FIX code
→ Reply: "✅ Good point, applied. {explanation}"
→ ELSE:
→ Reply: "🤔 {reasoning why not applied}"
ELSE IF preferencja stylowa (minor):
→ IF easy to apply:
→ FIX code
→ Reply: "✅ Updated"
→ ELSE:
→ Reply: "📝 {explanation of current approach}"
ELSE IF niejasna:
→ Reply: "❓ Could you clarify? {specific question}"
4. COMMIT changes (jeśli były):
- Group related fixes
- Descriptive commit message
- Reference review comments
5. PUSH changes:
- git push origin {head_branch}
6. PUBLIKUJ replies (przez webhook):
- Event: `github_review_responded`
- Payload: replies + commits
7. UPDATE status:
- Mark all comments as addressedPrzykład odpowiedzi:
### Response to @reviewer on user.service.ts:45
✅ **Fixed - SQL Injection vulnerability**
You're absolutely right, this was a critical security issue. Changed to parameterized query:
\`\`\`typescript
const query = `SELECT * FROM users WHERE id = ?`;
const result = await db.query(query, [userId]);
\`\`\`
Commit: `abc123f`
---
### Response to @reviewer on api.service.ts:78
✅ **Good point - Added error handling**
Added try-catch with proper error logging and re-throw:
\`\`\`typescript
async getData() {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
} catch (error) {
this.logger.error('API error:', error);
throw error;
}
}
\`\`\`
Also added unit tests for error scenarios.
Commit: `def456a`
---
### Response to @reviewer on navbar.component.ts:23
🤔 **Regarding magic number extraction**
While I agree constants are generally better, in this specific case the value `10` is:
1. Used only once in the codebase
2. Directly related to UI constraint (visible items)
3. Likely to change based on design (not business logic)
Current approach keeps it co-located with the UI logic. If we need to reuse this value elsewhere, I'll extract it then. What do you think?
---
### Response to @reviewer on login.component.ts (tests)
✅ **Added tests for login component**
Added comprehensive test suite:
- ✅ Successful login flow
- ✅ Failed login (wrong credentials)
- ✅ Network error handling
- ✅ Form validation
Coverage: 92%
Commit: `ghi789b`Webhook payload:
{
"event": "github_review_responded",
"mode": "respond",
"iteration": 1,
"pr": {
"number": 456,
"url": "...",
"reviewer": "tech-lead"
},
"response": {
"comments_addressed": 8,
"commits_made": 3,
"fixes_applied": 5,
"discussions_opened": 1
},
"commits": [
{
"sha": "abc123f",
"message": "fix: Use parameterized queries to prevent SQL injection",
"files_changed": ["src/app/services/user.service.ts"]
},
{
"sha": "def456a",
"message": "feat: Add comprehensive error handling to API service",
"files_changed": ["src/app/services/api.service.ts"]
},
{
"sha": "ghi789b",
"message": "test: Add test suite for login component (92% coverage)",
"files_changed": [
"src/app/components/login/login.component.spec.ts"
]
}
],
"actions_requested": {
"github": {
"reply_to_comments": true,
"replies": [
{
"comment_id": "12345",
"body": "✅ **Fixed - SQL Injection vulnerability**\n\n..."
}
]
},
"mattermost": {
"send_notification": true,
"message": "📬 Responded to review on PR #456\n✅ 5 fixes applied\n💬 1 discussion opened\n📝 3 commits pushed"
}
}
}Skrypty Bash
1. github_pr_fetch.sh
Lokalizacja: docker/{worker}/files/helpers/github_pr_fetch.sh
Użycie:
bash github_pr_fetch.sh <PR_URL> <OUTPUT_DIR> [--refresh|--own]Co robi:
#!/bin/bash
# github_pr_fetch.sh - Pobiera pełny kontekst PR z GitHub
set -e
PR_URL="$1"
OUTPUT_DIR="$2"
MODE="${3:-}" # --refresh, --own, lub empty
# Parse PR URL
# https://github.com/owner/repo/pull/123
REPO_OWNER=$(echo "$PR_URL" | cut -d'/' -f4)
REPO_NAME=$(echo "$PR_URL" | cut -d'/' -f5)
PR_NUMBER=$(echo "$PR_URL" | cut -d'/' -f7)
echo "📥 Fetching PR #$PR_NUMBER from $REPO_OWNER/$REPO_NAME"
mkdir -p "$OUTPUT_DIR"
# 1. Get PR metadata (gh CLI)
gh pr view "$PR_NUMBER" \
--repo "$REPO_OWNER/$REPO_NAME" \
--json number,title,body,state,author,headRefName,baseRefName,commits,files,reviews,comments \
> "$OUTPUT_DIR/pr_metadata.json"
# 2. Get PR diff
gh pr diff "$PR_NUMBER" \
--repo "$REPO_OWNER/$REPO_NAME" \
> "$OUTPUT_DIR/pr_diff.patch"
# 3. Get files changed
gh pr view "$PR_NUMBER" \
--repo "$REPO_OWNER/$REPO_NAME" \
--json files \
| jq '.files' > "$OUTPUT_DIR/files_changed.json"
# 4. Get review comments
gh api "/repos/$REPO_OWNER/$REPO_NAME/pulls/$PR_NUMBER/comments" \
> "$OUTPUT_DIR/review_comments.json"
# 5. Get reviews
gh api "/repos/$REPO_OWNER/$REPO_NAME/pulls/$PR_NUMBER/reviews" \
> "$OUTPUT_DIR/reviews.json"
# 6. Generate PR_CONTEXT.md (markdown summary)
cat > "$OUTPUT_DIR/PR_CONTEXT.md" <<EOF
# Pull Request Context
## PR Information
- **Number:** #$PR_NUMBER
- **Title:** $(jq -r '.title' "$OUTPUT_DIR/pr_metadata.json")
- **Author:** $(jq -r '.author.login' "$OUTPUT_DIR/pr_metadata.json")
- **State:** $(jq -r '.state' "$OUTPUT_DIR/pr_metadata.json")
- **Branch:** $(jq -r '.headRefName' "$OUTPUT_DIR/pr_metadata.json") → $(jq -r '.baseRefName' "$OUTPUT_DIR/pr_metadata.json")
- **URL:** $PR_URL
## Description
$(jq -r '.body' "$OUTPUT_DIR/pr_metadata.json")
## Changes Summary
- **Commits:** $(jq '.commits | length' "$OUTPUT_DIR/pr_metadata.json")
- **Files Changed:** $(jq '.files | length' "$OUTPUT_DIR/pr_metadata.json")
## Files Changed
$(jq -r '.files[] | "- \(.path) (+\(.additions) / -\(.deletions))"' "$OUTPUT_DIR/pr_metadata.json")
## Existing Reviews
$(jq -r '.[] | "- @\(.user.login): \(.state) (\(.submitted_at))"' "$OUTPUT_DIR/reviews.json")
## Review Comments
$(jq -r '.[] | "- @\(.user.login) on \(.path):\(.line): \(.body | split("\n") | join(" "))"' "$OUTPUT_DIR/review_comments.json")
EOF
echo "✅ PR context saved to $OUTPUT_DIR"2. send_review_webhook.sh
Lokalizacja: docker/{worker}/files/helpers/send_review_webhook.sh
Użycie:
bash send_review_webhook.sh <EVENT_TYPE> <PAYLOAD_FILE>Event types:
github_review_generated- System wygenerował reviewgithub_review_responded- System odpowiedział na review
Logika decyzyjna Claude
Review Mode - Kiedy APPROVE vs REQUEST_CHANGES?
def decide_review_action(review_comments):
"""
Decyduje czy zaakceptować PR czy prosić o zmiany
"""
critical_count = count_by_severity(review_comments, 'critical')
important_count = count_by_severity(review_comments, 'important')
# Critical issues = zawsze REQUEST_CHANGES
if critical_count > 0:
return "REQUEST_CHANGES", f"{critical_count} critical issues must be fixed"
# Dużo important issues = REQUEST_CHANGES
if important_count >= 5:
return "REQUEST_CHANGES", f"{important_count} important issues should be addressed"
# Kilka important = COMMENT (nie blokuj ale zaznacz)
if important_count > 0:
return "COMMENT", f"{important_count} suggestions for improvement"
# Tylko nice-to-have lub brak issues = APPROVE
return "APPROVE", "Code looks good!"
def classify_issue_severity(issue_type, impact):
"""
Klasyfikuje severity uwagi
"""
CRITICAL = [
'security_vulnerability',
'data_loss_risk',
'crash_inducing_bug',
'breaking_change_unintentional'
]
IMPORTANT = [
'logic_error',
'missing_error_handling',
'performance_issue',
'missing_tests_for_critical_path',
'race_condition',
'memory_leak'
]
NICE_TO_HAVE = [
'code_style',
'naming_convention',
'missing_comments',
'code_duplication_minor',
'performance_micro_optimization'
]
if issue_type in CRITICAL:
return 'critical'
elif issue_type in IMPORTANT:
return 'important'
else:
return 'nice_to_have'Respond Mode - Kiedy FIX vs DISCUSS?
def decide_response_action(review_comment, code_context):
"""
Decyduje jak odpowiedzieć na review comment
"""
issue_type = classify_comment_type(review_comment)
# Security/Correctness = zawsze fix
if issue_type in ['security', 'correctness', 'bug']:
return "FIX", "Critical issue, fixing immediately"
# Performance = evaluate impact
if issue_type == 'performance':
impact = estimate_performance_impact(review_comment, code_context)
if impact > 10: # > 10% improvement
return "FIX", f"Significant improvement ({impact}%), applying"
else:
return "DISCUSS", f"Minor impact ({impact}%), current approach is acceptable"
# Best practice = evaluate effort vs benefit
if issue_type == 'best_practice':
effort = estimate_implementation_effort(review_comment)
benefit = estimate_benefit(review_comment)
if benefit / effort > 2: # ROI > 2
return "FIX", "Good suggestion, low effort high benefit"
else:
return "DISCUSS", "Trade-off explanation"
# Style preference = evaluate consistency
if issue_type == 'style':
is_project_standard = check_project_coding_standards(review_comment)
if is_project_standard:
return "FIX", "Aligning with project standards"
else:
return "DISCUSS", "Current style is intentional"
# Unclear comment = ask for clarification
if is_unclear(review_comment):
return "ASK", "Could you provide more context?"
return "ACKNOWLEDGE", "Noted for future reference"Format komentarzy review
Zasady konstruktywnego review:
Konkretne, nie ogólnikowe ❌ "This code is bad" ✅ "This function has O(n²) complexity. Consider using a Map for O(1) lookups"
Z przykładem rozwiązania ❌ "Fix the error handling" ✅ "Add try-catch:\n
typescript\ntry { ... } catch (e) { ... }\n"Z wyjaśnieniem "dlaczego" ❌ "Use const instead of let" ✅ "Use const to prevent accidental reassignment and signal immutability"
Priorytet jasno oznaczony 🔴 Critical (must fix) 🟡 Important (should fix) 🟢 Nice-to-have (optional)
Pozytywne feedback też
- ✅ "Good test coverage"
- ✅ "Clean separation of concerns"
- ✅ "Excellent error messages"
Przykład: Pełny proces review
Scenariusz: System recenzuje PR (MODE A)
1. Developer tworzy PR #123
Title: Add user authentication
Branch: feature/user-auth → main
Files: 8 changed (+450 / -120)2. Developer przypisuje @code-gen-bot jako reviewer
3. n8n wykrywa → tworzy task + ustawia start_commands (mode=review)
4. System wykonuje review:
init_workspace
↓
github_pr_fetch (pobiera PR context, diff, files)
↓
github-review --mode=review --iteration=1
├─ Checkout branch feature/user-auth
├─ Analiza każdego pliku:
│ ├─ user.service.ts → SQL injection (🔴)
│ ├─ login.component.ts → Password storage (🔴)
│ ├─ api.service.ts → Missing error handling (🟡)
│ ├─ auth.guard.ts → Missing tests (🟡)
│ └─ navbar.component.ts → Magic number (🟢)
├─ Generuje REVIEW_1.md
└─ Wysyła webhook5. n8n publikuje review w GitHub:
Decision: REQUEST_CHANGES
🔴 2 critical issues
🟡 3 important issues
🟢 2 nice-to-have6. Developer poprawia critical issues i odpowiada:
@code-gen-bot Fixed SQL injection and password storage.
Also added error handling. Tests will be in separate PR.7. n8n wykrywa odpowiedź → trigger iteracji 2
8. System wykonuje review iteration 2:
github_pr_refresh (pobiera nowe zmiany + komentarze)
↓
github-review --mode=review --iteration=2
├─ Czyta poprzedni REVIEW_1.md
├─ Czyta nowe commits
├─ Weryfikuje fixes:
│ ├─ SQL injection → ✅ Fixed (parameterized query)
│ ├─ Password storage → ✅ Fixed (removed)
│ └─ Error handling → ✅ Fixed (try-catch added)
├─ Sprawdza tests → ⚠️ Still missing
├─ DECYZJA:
│ - Critical: 0
│ - Important: 1 (missing tests)
│ - Decision: COMMENT (nie blokuj)
└─ Wysyła webhook9. n8n publikuje review iteration 2:
Decision: COMMENT
✅ Critical issues fixed - great job!
🟡 Tests still missing but not blocking
Suggested: Add tests before merge10. Developer:
@code-gen-bot Agreed, will add tests. Can you approve so we can merge after tests?11. System wykonuje iteration 3:
DECYZJA:
- Critical: 0
- Important: 0 (tests będą dodane)
- Decision: APPROVE ✅12. n8n publikuje approval:
✅ APPROVED
All issues addressed. PR ready to merge after tests are added.Scenariusz: Developer recenzuje kod systemu (MODE B)
1. System tworzy PR #456 (po zakończeniu implementacji taska)
Title: feat(admin): Change admin bar color to dark blue
Branch: claude/DEV-1_10 → master
Files: 3 changed (+25 / -8)2. Tech lead robi review:
Comment 1 on container.component.scss:12:
🔴 Don't hardcode colors. Use design tokens from _colors.scss
Comment 2 on container.component.ts:45:
🟡 Consider adding a service for admin bar configuration
Comment 3 on container.component.spec.ts:
🔴 Missing tests for super admin role verification3. n8n wykrywa review → ustawia start_commands (mode=respond)
4. System odpowiada na review:
github_pr_fetch_own (pobiera review comments)
↓
github-review --mode=respond --iteration=1
├─ Czyta review_comments.json
├─ Dla każdego comment:
│
│ Comment 1 (hardcoded colors):
│ ├─ ANALIZA: Security? No. Correctness? No. Best practice? YES
│ ├─ DECYZJA: FIX (design tokens = standard)
│ ├─ ZMIANA: Dodaj $admin-bar-color do _colors.scss
│ ├─ ZMIANA: Użyj tokena w component.scss
│ └─ COMMIT: "refactor: Use design token for admin bar color"
│
│ Comment 2 (service):
│ ├─ ANALIZA: Over-engineering? Probably (single use case)
│ ├─ DECYZJA: DISCUSS
│ └─ REPLY: "Current approach is simpler. Service would add
│ unnecessary abstraction for single config value.
│ Happy to refactor if we add more admin bar features."
│
│ Comment 3 (missing tests):
│ ├─ ANALIZA: Critical? YES (security verification)
│ ├─ DECYZJA: FIX
│ ├─ ZMIANA: Dodaj testy dla isSuperAdmin flow
│ └─ COMMIT: "test: Add tests for super admin role verification"
│
└─ Wysyła webhook
↓
github_push_changes (push commits)5. n8n publikuje replies + commits:
✅ Fixed - Using design token
Commit: abc123f
🤔 Regarding service extraction
[reasoning...]
✅ Added tests for super admin role
Commit: def456a
Coverage: 92%6. Tech lead weryfikuje:
@code-gen-bot Good reasoning on the service. Approved! ✅7. System merge PR (auto-merge if enabled)
Zasady konstruktywnej dyskusji
Dla systemu recenzującego (MODE A):
Nie lej wody: ❌ "This is interesting approach but I think maybe we could consider..." ✅ "Use Map instead of nested loops (O(n²) → O(n))"
Konkretne przykłady: ❌ "Refactor this" ✅ "Extract to helper:\n
typescript\nfunction validateEmail(email) { ... }\n"Priorytet zawsze:
- 🔴 Must fix (security, bugs, data loss)
- 🟡 Should fix (performance, maintainability)
- 🟢 Nice-to-have (style, naming)
Doceniaj dobre rzeczy:
- Zawsze znajdź min. 1 pozytywny feedback
- ✅ "Excellent test coverage"
- ✅ "Clean separation of concerns"
Dla systemu odpowiadającego (MODE B):
Szybko przyznaj rację gdy zasadne: ✅ "You're absolutely right. Fixed in commit abc123"
Wyjaśniaj reasoning gdy nie zgadzasz się: ✅ "Current approach is simpler because [konkretny powód]"
Nie dyskutuj o preferencjach: ❌ "I prefer this style" ✅ "Aligned with project coding standards (see CONTRIBUTING.md)"
Poproś o wyjaśnienie gdy niejasne: ✅ "Could you clarify what you mean by 'better structure'?"
Max iteracji:
Review mode: 3 iteracje
- Po 3: Automatyczny APPROVE z note: "Remaining items are minor"
Respond mode: 2 iteracje
- Po 2: Final response: "Addressed all major concerns. Open to further discussion in next PR if needed."
FAQ
Q: Co jeśli system i human reviewer się nie zgadzają? A: System zawsze ustępuje human reviewer po 2 iteracjach dyskusji.
Q: Jak system radzi sobie z subiektywnym feedback (np. "to brzydko wygląda")? A: Prosi o konkretny, obiektywny feedback: "Could you specify what makes it unclear? Happy to improve readability."
Q: Co jeśli review dotyczy designu a nie kodu? A: System odpowiada: "Design decisions should be discussed in the issue. This PR implements the agreed spec."
Q: Czy system może merge'ować bez human approval? A: Tylko jeśli PR ma label auto-merge-allowed. Domyślnie wymaga human approval.
Q: Co jeśli system zrobi błąd w review? A: Human może override review. System uczy się z feedback (future: ML feedback loop).