feat(agents): добавлены скиллы для ревью, GitHub, диагностики и менторинга

- Зачем:
  - расширить набор переиспользуемых скиллов для повседневных задач: ревью PR, работа с GitHub, проверка dotfiles, диагностика сети, ревью кода менти.
- Что:
  - добавлен differential-review (Trail of Bits) — security-focused ревью PR.
  - добавлен github (Callstack) — workflow через gh CLI, stacked PRs.
  - создан dotfiles-check — bash-скрипт проверки целостности stow-симлинков.
  - создан proxy-debug — диагностика сети и прокси hproxy.local.
  - создан review-homework — ревью кода менти в обучающем формате.
- Проверка:
  - bash ~/.agents/skills/dotfiles-check/check.sh ~/dotfiles
This commit is contained in:
ddadmin committed 2026-03-14 13:40:19 +03:00
1 parent 984db1b6d7
commit 5eafb99639
12 files changed
+1821

No files matched your search

@@ -0,0 +1,221 @@
---
name: differential-review
description: >
Performs security-focused differential review of code changes (PRs, commits, diffs).
Adapts analysis depth to codebase size, uses git history for context, calculates
blast radius, checks test coverage, and generates comprehensive markdown reports.
Automatically detects and prevents security regressions.
disable-model-invocation: true
allowed-tools:
- Read
- Write
- Grep
- Glob
- Bash
---
# Differential Security Review
Security-focused code review for PRs, commits, and diffs.
## Core Principles
1. **Risk-First**: Focus on auth, crypto, value transfer, external calls
2. **Evidence-Based**: Every finding backed by git history, line numbers, attack scenarios
3. **Adaptive**: Scale to codebase size (SMALL/MEDIUM/LARGE)
4. **Honest**: Explicitly state coverage limits and confidence level
5. **Output-Driven**: Always generate comprehensive markdown report file
---
## Rationalizations (Do Not Skip)
| Rationalization | Why It's Wrong | Required Action |
|-----------------|----------------|-----------------|
| "Small PR, quick review" | Heartbleed was 2 lines | Classify by RISK, not size |
| "I know this codebase" | Familiarity breeds blind spots | Build explicit baseline context |
| "Git history takes too long" | History reveals regressions | Never skip Phase 1 |
| "Blast radius is obvious" | You'll miss transitive callers | Calculate quantitatively |
| "No tests = not my problem" | Missing tests = elevated risk rating | Flag in report, elevate severity |
| "Just a refactor, no security impact" | Refactors break invariants | Analyze as HIGH until proven LOW |
| "I'll explain verbally" | No artifact = findings lost | Always write report |
---
## Quick Reference
### Codebase Size Strategy
| Codebase Size | Strategy | Approach |
|---------------|----------|----------|
| SMALL (<20 files) | DEEP | Read all deps, full git blame |
| MEDIUM (20-200) | FOCUSED | 1-hop deps, priority files |
| LARGE (200+) | SURGICAL | Critical paths only |
### Risk Level Triggers
| Risk Level | Triggers |
|------------|----------|
| HIGH | Auth, crypto, external calls, value transfer, validation removal |
| MEDIUM | Business logic, state changes, new public APIs |
| LOW | Comments, tests, UI, logging |
---
## Workflow Overview
```
Pre-Analysis → Phase 0: Triage → Phase 1: Code Analysis → Phase 2: Test Coverage
↓ ↓ ↓ ↓
Phase 3: Blast Radius → Phase 4: Deep Context → Phase 5: Adversarial → Phase 6: Report
```
---
## Decision Tree
**Starting a review?**
```
├─ Need detailed phase-by-phase methodology?
│ └─ Read: methodology.md
│ (Pre-Analysis + Phases 0-4: triage, code analysis, test coverage, blast radius)
│
├─ Analyzing HIGH RISK change?
│ └─ Read: adversarial.md
│ (Phase 5: Attacker modeling, exploit scenarios, exploitability rating)
│
├─ Writing the final report?
│ └─ Read: reporting.md
│ (Phase 6: Report structure, templates, formatting guidelines)
│
├─ Looking for specific vulnerability patterns?
│ └─ Read: patterns.md
│ (Regressions, reentrancy, access control, overflow, etc.)
│
└─ Quick triage only?
└─ Use Quick Reference above, skip detailed docs
```
---
## Quality Checklist
Before delivering:
- [ ] All changed files analyzed
- [ ] Git blame on removed security code
- [ ] Blast radius calculated for HIGH risk
- [ ] Attack scenarios are concrete (not generic)
- [ ] Findings reference specific line numbers + commits
- [ ] Report file generated
- [ ] User notified with summary
---
## Integration
**audit-context-building skill:**
- Pre-Analysis: Build baseline context
- Phase 4: Deep context on HIGH RISK changes
**issue-writer skill:**
- Transform findings into formal audit reports
- Command: `issue-writer --input DIFFERENTIAL_REVIEW_REPORT.md --format audit-report`
---
## Example Usage
### Quick Triage (Small PR)
```
Input: 5 file PR, 2 HIGH RISK files
Strategy: Use Quick Reference
1. Classify risk level per file (2 HIGH, 3 LOW)
2. Focus on 2 HIGH files only
3. Git blame removed code
4. Generate minimal report
Time: ~30 minutes
```
### Standard Review (Medium Codebase)
```
Input: 80 files, 12 HIGH RISK changes
Strategy: FOCUSED (see methodology.md)
1. Full workflow on HIGH RISK files
2. Surface scan on MEDIUM
3. Skip LOW risk files
4. Complete report with all sections
Time: ~3-4 hours
```
### Deep Audit (Large, Critical Change)
```
Input: 450 files, auth system rewrite
Strategy: SURGICAL + audit-context-building
1. Baseline context with audit-context-building
2. Deep analysis on auth changes only
3. Blast radius analysis
4. Adversarial modeling
5. Comprehensive report
Time: ~6-8 hours
```
---
## When NOT to Use This Skill
- **Greenfield code** (no baseline to compare)
- **Documentation-only changes** (no security impact)
- **Formatting/linting** (cosmetic changes)
- **User explicitly requests quick summary only** (they accept risk)
For these cases, use standard code review instead.
---
## Red Flags (Stop and Investigate)
**Immediate escalation triggers:**
- Removed code from "security", "CVE", or "fix" commits
- Access control modifiers removed (onlyOwner, internal → external)
- Validation removed without replacement
- External calls added without checks
- High blast radius (50+ callers) + HIGH risk change
These patterns require adversarial analysis even in quick triage.
---
## Tips for Best Results
**Do:**
- Start with git blame for removed code
- Calculate blast radius early to prioritize
- Generate concrete attack scenarios
- Reference specific line numbers and commits
- Be honest about coverage limitations
- Always generate the output file
**Don't:**
- Skip git history analysis
- Make generic findings without evidence
- Claim full analysis when time-limited
- Forget to check test coverage
- Miss high blast radius changes
- Output report only to chat (file required)
---
## Supporting Documentation
- **[methodology.md](methodology.md)** - Detailed phase-by-phase workflow (Phases 0-4)
- **[adversarial.md](adversarial.md)** - Attacker modeling and exploit scenarios (Phase 5)
- **[reporting.md](reporting.md)** - Report structure and formatting (Phase 6)
- **[patterns.md](patterns.md)** - Common vulnerability patterns reference
---
**For first-time users:** Start with [methodology.md](methodology.md) to understand the complete workflow.
**For experienced users:** Use this page's Quick Reference and Decision Tree to navigate directly to needed content.
@@ -0,0 +1,203 @@
# Adversarial Vulnerability Analysis (Phase 5)
Structured methodology for finding vulnerabilities through attacker modeling.
**When to use:** After completing deep context analysis (Phase 4), apply this to all HIGH RISK changes.
---
## 1. Define Specific Attacker Model
**WHO is the attacker?**
- Unauthenticated external user
- Authenticated regular user
- Malicious administrator
- Compromised contract/service
- Front-runner/MEV bot
**WHAT access/privileges do they have?**
- Public API access only
- Authenticated user role
- Specific permissions/tokens
- Contract call capabilities
**WHERE do they interact with the system?**
- Specific HTTP endpoints
- Smart contract functions
- RPC interfaces
- External APIs
---
## 2. Identify Concrete Attack Vectors
```
ENTRY POINT: [Exact function/endpoint attacker can access]
ATTACK SEQUENCE:
1. [Specific API call/transaction with parameters]
2. [How this reaches the vulnerable code]
3. [What happens in the vulnerable code]
4. [Impact achieved]
PROOF OF ACCESSIBILITY:
- Show the function is public/external
- Demonstrate attacker has required permissions
- Prove attack path exists through actual interfaces
```
---
## 3. Rate Realistic Exploitability
**EASY:** Exploitable via public APIs with no special privileges
- Single transaction/call
- Common user access level
- No complex conditions required
**MEDIUM:** Requires specific conditions or elevated privileges
- Multiple steps or timing requirements
- Elevated but obtainable privileges
- Specific system state needed
**HARD:** Requires privileged access or rare conditions
- Admin/owner privileges needed
- Rare edge case conditions
- Significant resources required
---
## 4. Build Complete Exploit Scenario
```
ATTACKER STARTING POSITION:
[What the attacker has at the beginning]
STEP-BY-STEP EXPLOITATION:
Step 1: [Concrete action through accessible interface]
- Command: [Exact call/request]
- Parameters: [Specific values]
- Expected result: [What happens]
Step 2: [Next action]
- Command: [Exact call/request]
- Why this works: [Reference to code change]
- System state change: [What changed]
Step 3: [Final impact]
- Result: [Concrete harm achieved]
- Evidence: [How to verify impact]
CONCRETE IMPACT:
[Specific, measurable impact - not "could cause issues"]
- Exact amount of funds drained
- Specific privileges escalated
- Particular data exposed
```
---
## 5. Cross-Reference with Baseline Context
From baseline analysis (see [methodology.md](methodology.md#pre-analysis-baseline-context-building)), check:
- Does this violate a system-wide invariant?
- Does this break a trust boundary?
- Does this bypass a validation pattern?
- Is this a regression of a previous fix?
---
## Vulnerability Report Template
Generate this for each finding:
```markdown
## [SEVERITY] Vulnerability Title
**Attacker Model:**
- WHO: [Specific attacker type]
- ACCESS: [Exact privileges]
- INTERFACE: [Specific entry point]
**Attack Vector:**
[Step-by-step exploit through accessible interfaces]
**Exploitability:** EASY/MEDIUM/HARD
**Justification:** [Why this rating]
**Concrete Impact:**
[Specific, measurable harm - not theoretical]
**Proof of Concept:**
```code
// Exact code to reproduce
```
**Root Cause:**
[Reference specific code change at file.sol:L123]
**Blast Radius:** [N callers affected]
**Baseline Violation:** [Which invariant/pattern broken]
```
---
## Example: Complete Adversarial Analysis
**Change:** Removed `require(amount > 0)` check from `withdraw()` function
### 1. Attacker Model
- **WHO:** Unauthenticated external user
- **ACCESS:** Can call public contract functions
- **INTERFACE:** `withdraw(uint256 amount)` at 0x1234...
### 2. Attack Vector
**ENTRY POINT:** `withdraw(0)`
**ATTACK SEQUENCE:**
1. Call `withdraw(0)` from attacker address
2. Code bypasses amount check (removed)
3. Withdraw event emitted with 0 amount
4. Accounting updated incorrectly
**PROOF:** Function is `external`, no auth required
### 3. Exploitability
**RATING:** EASY
- Single transaction
- Public function
- No special state required
### 4. Exploit Scenario
**ATTACKER POSITION:** Has user account with 0 balance
**EXPLOITATION:**
```solidity
Step 1: attacker.withdraw(0)
- Passes removed validation
- Emits Withdraw(user, 0)
- Updates withdrawnAmount[user] += 0
Step 2: Off-chain indexer sees Withdraw event
- Credits attacker for 0 withdrawal
- But accounting thinks withdrawal happened
Step 3: Accounting mismatch exploited
- Total supply decremented
- User balance not changed
- System invariants broken
```
**IMPACT:**
- Protocol accounting corrupted
- Can be used to manipulate LP calculations
- Estimated $50K impact on pool prices
### 5. Baseline Violation
- Violates invariant: "All withdrawals must transfer non-zero value"
- Breaks validation pattern: Amount checks present in all other value transfers
- Regression: Check added in commit abc123 "Fix zero-amount exploit"
---
**Next:** Document all findings in final report (see [reporting.md](reporting.md))
@@ -0,0 +1,234 @@
# Differential Review Methodology
Detailed phase-by-phase workflow for security-focused code review.
## Pre-Analysis: Baseline Context Building
**FIRST ACTION - Build complete baseline understanding:**
If `audit-context-building` skill is available:
```bash
# Checkout baseline commit
git checkout <baseline_commit>
# Invoke audit-context-building skill on baseline codebase
# Scope = entire relevant project (e.g., packages/contracts/contracts/ for Solidity, src/ for Rust, etc.)
audit-context-building --scope [entire project or main contract directory] --focus invariants,trust-boundaries,validation-patterns,call-graphs,state-flows
# Examples:
# For Solidity: audit-context-building --scope packages/contracts/contracts
# For Rust: audit-context-building --scope src
# For full repo: audit-context-building --scope .
```
**Capture from baseline analysis:**
- System-wide invariants (what must ALWAYS be true across all code)
- Trust boundaries and privilege levels (who can do what)
- Validation patterns (what gets checked where - defense-in-depth)
- Complete call graphs for critical functions (who calls what)
- State flow diagrams (how state changes)
- External dependencies and trust assumptions
**Why this matters:**
- Understand what the code was SUPPOSED to do before changes
- Identify implicit security assumptions in baseline
- Detect when changes violate baseline invariants
- Know which patterns are system-wide vs local
- Catch when changes break defense-in-depth
**Store baseline context for reference during differential analysis.**
After baseline analysis, checkout back to head commit to analyze changes.
---
## Phase 0: Intake & Triage
**Extract changes:**
```bash
# For commit range
git diff <base>..<head> --stat
git log <base>..<head> --oneline
# For PR
gh pr view <number> --json files,additions,deletions
# Get all changed files
git diff <base>..<head> --name-only
```
**Assess codebase size:**
```bash
find . -name "*.sol" -o -name "*.rs" -o -name "*.go" -o -name "*.ts" | wc -l
```
**Classify complexity:**
- **SMALL**: <20 files → Deep analysis (read all deps)
- **MEDIUM**: 20-200 files → Focused analysis (1-hop deps)
- **LARGE**: 200+ files → Surgical (critical paths only)
**Risk score each file:**
- **HIGH**: Auth, crypto, external calls, value transfer, validation removal
- **MEDIUM**: Business logic, state changes, new public APIs
- **LOW**: Comments, tests, UI, logging
---
## Phase 1: Changed Code Analysis
For each changed file:
1. **Read both versions** (baseline and changed)
2. **Analyze each diff region:**
```
BEFORE: [exact code]
AFTER: [exact code]
CHANGE: [behavioral impact]
SECURITY: [implications]
```
3. **Git blame removed code:**
```bash
# When was it added? Why?
git log -S "removed_code" --all --oneline
git blame <baseline> -- file.sol | grep "pattern"
```
**Red flags:**
- Removed code from "fix", "security", "CVE" commits → CRITICAL
- Recently added (<1 month) then removed → HIGH
4. **Check for regressions (re-added code):**
```bash
git log -S "added_code" --all -p
```
Pattern: Code added → removed for security → re-added now = REGRESSION
5. **Micro-adversarial analysis** for each change:
- What attack did removed code prevent?
- What new surface does new code expose?
- Can modified logic be bypassed?
- Are checks weaker? Edge cases covered?
6. **Generate concrete attack scenarios:**
```
SCENARIO: [attack goal]
PRECONDITIONS: [required state]
STEPS:
1. [specific action]
2. [expected outcome]
3. [exploitation]
WHY IT WORKS: [reference code change]
IMPACT: [severity + scope]
```
---
## Phase 2: Test Coverage Analysis
**Identify coverage gaps:**
```bash
# Production code changes (exclude tests)
git diff <range> --name-only | grep -v "test"
# Test changes
git diff <range> --name-only | grep "test"
# For each changed function, search for tests
grep -r "test.*functionName" test/ --include="*.sol" --include="*.js"
```
**Risk elevation rules:**
- NEW function + NO tests → Elevate risk MEDIUM→HIGH
- MODIFIED validation + UNCHANGED tests → HIGH RISK
- Complex logic (>20 lines) + NO tests → HIGH RISK
---
## Phase 3: Blast Radius Analysis
**Calculate impact:**
```bash
# Count callers for each modified function
grep -r "functionName(" --include="*.sol" . | wc -l
```
**Classify blast radius:**
- 1-5 calls: LOW
- 6-20 calls: MEDIUM
- 21-50 calls: HIGH
- 50+ calls: CRITICAL
**Priority matrix:**
| Change Risk | Blast Radius | Priority | Analysis Depth |
|-------------|--------------|----------|----------------|
| HIGH | CRITICAL | P0 | Deep + all deps |
| HIGH | HIGH/MEDIUM | P1 | Deep |
| HIGH | LOW | P2 | Standard |
| MEDIUM | CRITICAL/HIGH | P1 | Standard + callers |
---
## Phase 4: Deep Context Analysis
**If `audit-context-building` skill is available**, invoke it to help answer all the questions below for each HIGH RISK changed function:
```bash
# Run audit-context-building on the changed function and its dependencies
audit-context-building --scope [file containing changed function] --focus flow-analysis,call-graphs,invariants,root-cause
```
**The audit-context-building skill will help you answer:**
1. **Map complete function flow:**
- Entry conditions (preconditions, requires, modifiers)
- State reads (which variables accessed)
- State writes (which variables modified)
- External calls (to contracts, APIs, system)
- Return values and side effects
2. **Trace internal calls:**
- List all functions called
- Recursively map their flows
- Build complete call graph
3. **Trace external calls:**
- Identify trust boundaries crossed
- List assumptions about external behavior
- Check for reentrancy risks
4. **Identify invariants:**
- What must ALWAYS be true?
- What must NEVER happen?
- Are invariants maintained after changes?
5. **Five Whys root cause:**
- WHY was this code changed?
- WHY did the original code exist?
- WHY might this break?
- WHY is this approach chosen?
- WHY could this fail in production?
**If `audit-context-building` skill is NOT available**, manually perform the line-by-line analysis above using Read, Grep, and code tracing.
**Cross-cutting pattern detection:**
```bash
# Find repeated validation patterns
grep -r "require.*amount > 0" --include="*.sol" .
grep -r "onlyOwner" --include="*.sol" .
# Check if any removed in diff
git diff <range> | grep "^-.*require.*amount > 0"
```
**Flag if removal breaks defense-in-depth.**
---
**Next steps:**
- For HIGH RISK changes, proceed to [adversarial.md](adversarial.md)
- For report generation, see [reporting.md](reporting.md)
@@ -0,0 +1,300 @@
# Common Vulnerability Patterns
Quick reference for detecting common security issues in code changes.
**Specialized Pattern Resources:**
For specific contexts, reference these additional pattern databases:
**Domain-Specific:**
- `domain-specific-audits/defi-bridges/resources/` - 127 bridge-specific findings
- `domain-specific-audits/tick-math/resources/` - 81 tick math findings
- `domain-specific-audits/merkle-trees/resources/` - 67 merkle tree findings
- [Check `domain-specific-audits/skills/` for additional domains]
**Solidity-Specific:**
- `not-so-smart-contracts` - Automated Solidity vulnerability detectors
- `token-integration-analyzer` - Token integration safety patterns
- `building-secure-contracts/development-guidelines` - Solidity best practices
These complement the generic patterns below.
---
## Security Regressions
**Pattern:** Previously removed code is re-added
**Detection:**
```bash
# Code previously removed for security
git log -S "pattern" --all --grep="security\|fix\|CVE"
```
**Red flags:**
- Commit message contains "security", "fix", "CVE", "vulnerability"
- Code removed <6 months ago
- No explanation in current PR for re-addition
**Example:**
```solidity
// Removed in commit abc123 "Fix reentrancy CVE-2024-1234"
// Re-added in current PR
function emergencyWithdraw() {
// REGRESSION: Reentrancy vulnerability re-introduced
}
```
---
## Double Decrease/Increase Bugs
**Pattern:** Same accounting operation twice for same event
**Detection:** Look for two state updates in related functions for same logical action
**Example:**
```solidity
// Request exit
function requestExit() {
balance[user] -= amount; // First decrease
}
// Process exit
function processExit() {
balance[user] -= amount; // Second decrease - BUG!
}
```
**Impact:** User balance decremented twice, protocol loses funds
---
## Missing Validation
**Pattern:** Removed `require`/`assert`/`check` without replacement
**Detection:**
```bash
git diff <range> | grep "^-.*require"
git diff <range> | grep "^-.*assert"
git diff <range> | grep "^-.*revert"
```
**Questions to ask:**
- Was validation moved elsewhere?
- Is it redundant (defensive programming)?
- Does removal expose vulnerability?
**Example:**
```diff
function withdraw(uint256 amount) {
- require(amount > 0, "Zero amount");
- require(amount <= balance[msg.sender], "Insufficient");
balance[msg.sender] -= amount;
}
```
**Risk:** Zero-amount withdrawals, underflow attacks now possible
---
## Underflow/Overflow
**Pattern:** Arithmetic without SafeMath or checks
**Detection:**
- Look for `+`, `-`, `*`, `/` in Solidity <0.8.0
- Check if SafeMath removed
- Look for unchecked blocks in Solidity >=0.8.0
**Example:**
```solidity
// Solidity 0.7 without SafeMath
balance[user] -= amount; // Can underflow if amount > balance
// Solidity 0.8+ with unchecked
unchecked {
balance[user] -= amount; // Deliberately bypasses overflow check
}
```
**Risk:** Integer wrap-around leads to incorrect balances
---
## Reentrancy
**Pattern:** External call before state update
**Detection:** Look for CEI (Checks-Effects-Interactions) pattern violations
**Example:**
```solidity
// VULNERABLE: External call before state update
function withdraw() {
uint amount = balances[msg.sender];
(bool success,) = msg.sender.call{value: amount}(""); // External call FIRST
require(success);
balances[msg.sender] = 0; // State update AFTER
}
// SAFE: State update before external call
function withdraw() {
uint amount = balances[msg.sender];
balances[msg.sender] = 0; // State update FIRST
(bool success,) = msg.sender.call{value: amount}(""); // External call AFTER
require(success);
}
```
**Impact:** Attacker can recursively call withdraw() before balance is zeroed
---
## Access Control Bypass
**Pattern:** Removed or relaxed permission checks
**Detection:**
```bash
git diff <range> | grep "^-.*onlyOwner"
git diff <range> | grep "^-.*onlyAdmin"
git diff <range> | grep "^-.*require.*msg.sender"
```
**Questions:**
- Who can now call this function?
- What's the new trust model?
- Was check moved to caller?
**Example:**
```diff
- function setConfig(uint value) external onlyOwner {
+ function setConfig(uint value) external {
config = value;
}
```
**Risk:** Any user can now modify critical configuration
---
## Race Conditions / Front-Running
**Pattern:** State-dependent logic without protection
**Detection:** Look for two-step processes without commit-reveal or timelocks
**Example:**
```solidity
// Step 1: Approve
function approve(address spender, uint amount) {
allowance[msg.sender][spender] = amount;
}
// Step 2: User can front-run between approval changes
// Attacker sees tx changing approval from 100 to 50
// Front-runs to spend 100, then spends 50 after = 150 total
```
**Risk:** MEV/front-running exploits state transitions
---
## Timestamp Manipulation
**Pattern:** Security logic depending on `block.timestamp`
**Detection:**
```bash
grep -r "block.timestamp" --include="*.sol"
grep -r "now\b" --include="*.sol" # Solidity <0.7
```
**Example:**
```solidity
// VULNERABLE
require(block.timestamp > deadline, "Too early");
// Miner can manipulate timestamp by ~15 seconds
// SAFER
require(block.number > deadlineBlock, "Too early");
// Block numbers are harder to manipulate
```
**Risk:** Miners can manipulate timestamps within tolerance
---
## Unchecked Return Values
**Pattern:** External call without checking success
**Detection:**
```bash
git diff <range> | grep "\.call\|\.send\|\.transfer"
```
**Example:**
```solidity
// VULNERABLE
token.transfer(user, amount); // Ignores return value
// SAFE
require(token.transfer(user, amount), "Transfer failed");
// Or use SafeERC20 wrapper
```
**Risk:** Silent failures lead to inconsistent state
---
## Denial of Service
**Pattern:** Unbounded loops, external call reverts blocking execution
**Detection:**
- Arrays that grow without limit
- Loops over user-controlled array
- Critical function depends on external call success
**Example:**
```solidity
// DOS: Attacker adds many users, making loop too expensive
function distributeRewards() {
for (uint i = 0; i < users.length; i++) {
users[i].transfer(reward); // Runs out of gas
}
}
```
**Risk:** Function becomes unusable due to gas limits
---
## Quick Detection Commands
**Find removed security checks:**
```bash
git diff <range> | grep "^-" | grep -E "require|assert|revert"
```
**Find new external calls:**
```bash
git diff <range> | grep "^+" | grep -E "\.call|\.delegatecall|\.staticcall"
```
**Find changed access modifiers:**
```bash
git diff <range> | grep -E "onlyOwner|onlyAdmin|internal|private|public|external"
```
**Find arithmetic changes:**
```bash
git diff <range> | grep -E "\+|\-|\*|/"
```
---
**For detailed analysis workflow, see [methodology.md](methodology.md)**
**For building exploit scenarios, see [adversarial.md](adversarial.md)**
@@ -0,0 +1,369 @@
# Report Generation (Phase 6)
Comprehensive markdown report structure and formatting guidelines.
---
## Report Structure
Generate markdown report with these mandatory sections:
### 1. Executive Summary
- Severity distribution table
- Risk assessment (CRITICAL/HIGH/MEDIUM/LOW)
- Final recommendation (APPROVE/REJECT/CONDITIONAL)
- Key metrics (test gaps, blast radius, red flags)
**Template:**
```markdown
# Executive Summary
| Severity | Count |
|----------|-------|
| 🔴 CRITICAL | X |
| 🟠 HIGH | Y |
| 🟡 MEDIUM | Z |
| 🟢 LOW | W |
**Overall Risk:** CRITICAL/HIGH/MEDIUM/LOW
**Recommendation:** APPROVE/REJECT/CONDITIONAL
**Key Metrics:**
- Files analyzed: X/Y (Z%)
- Test coverage gaps: N functions
- High blast radius changes: M functions
- Security regressions detected: P
```
---
### 2. What Changed
- Commit timeline with visual
- File summary table
- Lines changed stats
**Template:**
```markdown
## What Changed
**Commit Range:** `base..head`
**Commits:** X
**Timeline:** YYYY-MM-DD to YYYY-MM-DD
| File | +Lines | -Lines | Risk | Blast Radius |
|------|--------|--------|------|--------------|
| file1.sol | +50 | -20 | HIGH | CRITICAL |
| file2.sol | +10 | -5 | MEDIUM | LOW |
**Total:** +N, -M lines across K files
```
---
### 3. Critical Findings
For each HIGH/CRITICAL issue:
```markdown
### [SEVERITY] Title
**File**: path/to/file.ext:lineNumber
**Commit**: hash
**Blast Radius**: N callers (HIGH/MEDIUM/LOW)
**Test Coverage**: YES/NO/PARTIAL
**Description**: [clear explanation]
**Historical Context**:
- Git blame: Added in commit X (date)
- Message: "[original commit message]"
- [Why this code existed]
**Attack Scenario**:
[Concrete exploitation steps from adversarial.md]
**Proof of Concept**:
```code demonstrating issue```
**Recommendation**:
[Specific fix with code]
```
**Example:**
```markdown
### 🔴 CRITICAL: Authorization Bypass in Withdraw
**File**: TokenVault.sol:156
**Commit**: abc123def
**Blast Radius**: 23 callers (HIGH)
**Test Coverage**: NO
**Description**:
Removed `require(msg.sender == owner)` check allows any user to withdraw funds.
**Historical Context**:
- Git blame: Added 2024-06-15 (commit def456)
- Message: "Add owner check per audit finding #45"
- Code existed to prevent unauthorized withdrawals
**Attack Scenario**:
1. Attacker calls `withdraw(1000 ether)`
2. No authorization check (removed)
3. 1000 ETH transferred to attacker
4. Protocol funds drained
**Proof of Concept**:
```solidity
// As any address
vault.withdraw(vault.balance());
// Success - funds stolen
```
**Recommendation**:
```solidity
function withdraw(uint256 amount) external {
+ require(msg.sender == owner, "Unauthorized");
// ... rest of function
}
```
```
---
### 4. Test Coverage Analysis
- Coverage statistics
- Untested changes list
- Risk assessment
**Template:**
```markdown
## Test Coverage Analysis
**Coverage:** X% of changed code
**Untested Changes:**
| Function | Risk | Impact |
|----------|------|--------|
| functionA() | HIGH | No validation tests |
| functionB() | MEDIUM | Logic untested |
**Risk Assessment:**
N HIGH-risk functions without tests → Recommend blocking merge
```
---
### 5. Blast Radius Analysis
- High-impact functions table
- Dependency graph
- Impact quantification
**Template:**
```markdown
## Blast Radius Analysis
**High-Impact Changes:**
| Function | Callers | Risk | Priority |
|----------|---------|------|----------|
| transfer() | 89 | HIGH | P0 |
| validate() | 45 | MEDIUM | P1 |
```
---
### 6. Historical Context
- Security-related removals
- Regression risks
- Commit message red flags
**Template:**
```markdown
## Historical Context
**Security-Related Removals:**
- Line 45: `require` removed (added 2024-03 for CVE-2024-1234)
- Line 78: Validation removed (added 2023-12 "security hardening")
**Regression Risks:**
- Code pattern removed in commit X, re-added in commit Y
```
---
### 7. Recommendations
- Immediate actions (blocking)
- Before production (tracking)
- Technical debt (future)
**Template:**
```markdown
## Recommendations
### Immediate (Blocking)
- [ ] Fix CRITICAL issue in TokenVault.sol:156
- [ ] Add tests for withdraw() function
### Before Production
- [ ] Security audit of auth changes
- [ ] Load test blast radius functions
### Technical Debt
- [ ] Refactor validation pattern consistency
```
---
### 8. Analysis Methodology
- Strategy used (DEEP/FOCUSED/SURGICAL)
- Files analyzed
- Coverage estimate
- Techniques applied
- Limitations
- Confidence level
**Template:**
```markdown
## Analysis Methodology
**Strategy:** FOCUSED (80 files, medium codebase)
**Analysis Scope:**
- Files reviewed: 45/80 (56%)
- HIGH RISK: 100% coverage
- MEDIUM RISK: 60% coverage
- LOW RISK: Excluded
**Techniques:**
- Git blame on all removals
- Blast radius calculation
- Test coverage analysis
- Adversarial modeling for HIGH RISK
**Limitations:**
- Did not analyze external dependencies
- Limited to 1-hop caller analysis
**Confidence:** HIGH for analyzed scope, MEDIUM overall
```
---
### 9. Appendices
- Commit reference table
- Key definitions
- Contact info
---
## Formatting Guidelines
**Tables:** Use markdown tables for structured data
**Code blocks:** Always include syntax highlighting
```solidity
// Solidity code
```
```rust
// Rust code
```
**Status indicators:**
- ✅ Complete
- ⚠️ Warning
- ❌ Failed/Blocked
**Severity:**
- 🔴 CRITICAL
- 🟠 HIGH
- 🟡 MEDIUM
- 🟢 LOW
**Before/After comparisons:**
```markdown
**BEFORE:**
```code
old code
```
**AFTER:**
```code
new code
```
```
**Line number references:** Always include
- Format: `file.sol:L123`
- Link to commit: `file.sol:L123 (commit abc123)`
---
## File Naming and Location
**Priority order for output:**
1. Current working directory (if project repo)
2. User's Desktop
3. `~/.claude/skills/differential-review/output/`
**Filename format:**
```
<PROJECT>_DIFFERENTIAL_REVIEW_<DATE>.md
Example: VeChain_Stargate_DIFFERENTIAL_REVIEW_2025-12-26.md
```
---
## User Notification Template
After generating report:
```markdown
Report generated successfully!
📄 File: [filename]
📁 Location: [path]
📏 Size: XX KB
⏱️ Review Time: ~X hours
Summary:
- X findings (Y critical, Z high)
- Final recommendation: APPROVE/REJECT/CONDITIONAL
- Confidence: HIGH/MEDIUM/LOW
Next steps:
- Review findings in detail
- Address CRITICAL/HIGH issues before merge
- Consider chaining with issue-writer for stakeholder report
```
---
## Integration with issue-writer
After generating differential review, transform into audit report:
```bash
issue-writer --input DIFFERENTIAL_REVIEW_REPORT.md --format audit-report
```
This creates polished documentation for non-technical stakeholders.
---
## Error Handling
If file write fails:
1. Try Desktop location
2. Try temp directory
3. As last resort, output full report to chat
4. Notify user to save manually
**Always prioritize persistent artifact generation over ephemeral chat output.**
@@ -0,0 +1,23 @@
---
name: dotfiles-check
description: "Проверка целостности dotfiles: симлинки stow, права доступа, settings.local.json, bashrc. Вызывай когда пользователь просит проверить установку dotfiles или валидировать окружение."
disable-model-invocation: true
---
# Инструкция
Запусти скрипт проверки:
```bash
bash ~/.agents/skills/dotfiles-check/check.sh
```
Если пользователь передал путь к dotfiles-репозиторию:
```bash
bash ~/.agents/skills/dotfiles-check/check.sh $ARGUMENTS
```
Скрипт сам обнаружит stow-пакеты, проверит симлинки, права и дополнительные условия из `install.sh`.
Если есть ошибки (exit code 1) — кратко прокомментируй что сломалось и предложи команды для починки.
+150
View File
@@ -0,0 +1,150 @@
#!/usr/bin/env bash
# Проверка целостности dotfiles-установки через stow.
# Использование: bash check.sh [путь-к-dotfiles]
set -euo pipefail
DOTFILES_DIR="${1:-$(cd "$(dirname "$0")/../../../.." && pwd)}"
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m'
ok=0; warn=0; fail=0
pass() { echo -e " ${GREEN}✅${NC} $*"; ok=$((ok + 1)); }
skip() { echo -e " ${YELLOW}⚠️${NC} $*"; warn=$((warn + 1)); }
err() { echo -e " ${RED}❌${NC} $*"; fail=$((fail + 1)); }
echo "Проверка dotfiles ($DOTFILES_DIR)"
echo "═══════════════════════════════════════"
# --- 1. Stow-пакеты: проверка симлинков ---
# Stow использует "tree folding": если вся директория принадлежит одному пакету,
# создаётся один симлинк на директорию, а не на каждый файл внутри.
# Поэтому проверяем точки входа верхнего уровня каждого пакета.
for pkg_dir in "$DOTFILES_DIR"/*/; do
pkg=$(basename "$pkg_dir")
[[ "$pkg" == .* ]] && continue
# Точки входа — элементы первого уровня внутри пакета
entries=()
for entry in "$pkg_dir".* "$pkg_dir"*; do
[ -e "$entry" ] || continue
base=$(basename "$entry")
[[ "$base" == "." || "$base" == ".." ]] && continue
# Берём только dot-файлы/директории (то, что stow раскладывает в ~)
[[ "$base" == .* ]] && entries+=("$base")
done
[ ${#entries[@]} -eq 0 ] && continue
echo ""
echo "$pkg (${#entries[@]} точек входа):"
for entry in "${entries[@]}"; do
home_path="$HOME/$entry"
expected="$DOTFILES_DIR/$pkg/$entry"
# Если это директория в пакете — stow мог создать симлинк на неё целиком
# или "раскрыть" её и создать симлинки внутри. Проверяем оба варианта.
if [ -L "$home_path" ]; then
# Симлинк на верхнем уровне (tree folding)
actual=$(readlink -f "$home_path" 2>/dev/null || true)
expected_resolved=$(readlink -f "$expected" 2>/dev/null || true)
if [ "$actual" = "$expected_resolved" ]; then
pass "~/$entry"
else
err "~/$entry → $(readlink "$home_path") (ожидался $pkg/$entry)"
fi
elif [ -d "$home_path" ] && [ -d "$expected" ]; then
# Директория раскрыта — проверяем файлы внутри (один уровень)
inner_ok=0; inner_fail=0
while IFS= read -r -d '' f; do
fname=$(basename "$f")
inner_home="$home_path/$fname"
if [ -L "$inner_home" ]; then
inner_actual=$(readlink -f "$inner_home" 2>/dev/null || true)
inner_expected=$(readlink -f "$f" 2>/dev/null || true)
if [ "$inner_actual" = "$inner_expected" ]; then
inner_ok=$((inner_ok + 1))
else
inner_fail=$((inner_fail + 1))
fi
elif [ -e "$inner_home" ]; then
inner_ok=$((inner_ok + 1)) # файл есть, но не симлинк — ок для stow unfolded
else
inner_fail=$((inner_fail + 1))
fi
done < <(find "$expected" -maxdepth 1 -not -path "$expected" -print0)
if [ "$inner_fail" -eq 0 ]; then
pass "~/$entry/ ($inner_ok элементов)"
else
err "~/$entry/ — $inner_fail из $((inner_ok + inner_fail)) элементов отсутствуют"
fi
elif [ -e "$home_path" ]; then
skip "~/$entry — обычный файл (не симлинк)"
else
err "~/$entry — не найден"
fi
done
done
# --- 2. Дополнительные проверки из install.sh ---
install_script="$DOTFILES_DIR/install.sh"
if [ -f "$install_script" ]; then
echo ""
echo "Доп. проверки (install.sh):"
# chmod 444 на settings.json
if [ -f "$DOTFILES_DIR/claude/.claude/settings.json" ]; then
perms=$(stat -c %a "$DOTFILES_DIR/claude/.claude/settings.json" 2>/dev/null || true)
if [ "$perms" = "444" ]; then
pass "claude/settings.json — chmod 444"
else
skip "claude/settings.json — chmod $perms (ожидался 444)"
fi
fi
# settings.local.json
if [ -f "$HOME/.claude/settings.local.json" ]; then
pass "~/.claude/settings.local.json существует"
else
skip "~/.claude/settings.local.json — не найден (создайте через install.sh)"
fi
# bashrc
if grep -q 'bash_custom' "$HOME/.bashrc" 2>/dev/null; then
pass "~/.bashrc содержит подключение bash_custom"
else
skip "~/.bashrc не содержит bash_custom"
fi
fi
# --- 3. Битые симлинки ---
broken=$(find "$HOME" -maxdepth 3 -xtype l 2>/dev/null | grep -v '.cache\|.local/share\|node_modules\|.npm' | head -10)
if [ -n "$broken" ]; then
echo ""
echo "Битые симлинки в ~:"
while IFS= read -r link; do
err "$link → $(readlink "$link") (цель не существует)"
done <<< "$broken"
fi
# --- 4. Секреты ---
if [ -f "$HOME/.env.secrets" ]; then
echo ""
echo "Секреты:"
pass "~/.env.secrets существует"
fi
# --- Итого ---
total=$((ok + warn + fail))
echo ""
echo "═══════════════════════════════════════"
echo -e "Итого: ${GREEN}$ok${NC}/${total} ✅, ${YELLOW}$warn${NC} ⚠️, ${RED}$fail${NC} ❌"
[ "$fail" -eq 0 ] && exit 0 || exit 1
+60
View File
@@ -0,0 +1,60 @@
---
name: github
description: GitHub patterns using gh CLI for pull requests, stacked PRs, code review, branching strategies, and repository automation. Use when working with GitHub PRs, merging strategies, or repository management tasks.
license: MIT
metadata:
author: Callstack
tags: github, gh-cli, pull-request, stacked-pr, squash, rebase
---
# GitHub Patterns
## Tools
Use `gh` CLI for all GitHub operations. Prefer CLI over GitHub MCP servers for lower context usage.
## Quick Commands
```bash
# Create a PR from the current branch
gh pr create --title "feat: add feature" --body "Description"
# Squash-merge a PR
gh pr merge <PR_NUMBER> --squash --title "feat: add feature (#<PR_NUMBER>)"
# View PR status and checks
gh pr status
gh pr checks <PR_NUMBER>
```
## Stacked PR Workflow Summary
When merging a chain of stacked PRs (each targeting the previous branch):
1. **Merge the first PR** into main via squash merge
2. **For each subsequent PR**: rebase onto main, update base to main, then squash merge
3. **On conflicts**: stop and ask the user to resolve manually
```bash
# Rebase next PR's branch onto main, excluding already-merged commits
git rebase --onto origin/main <old-base-branch> <next-branch>
git push --force-with-lease origin <next-branch>
gh pr edit <N> --base main
gh pr merge <N> --squash --title "<PR title> (#N)"
```
See [stacked-pr-workflow.md][stacked-pr-workflow] for full step-by-step details.
## Quick Reference
| File | Description |
| --- | --- |
| [stacked-pr-workflow.md][stacked-pr-workflow] | Merge stacked PRs into main as individual squash commits |
## Problem -> Skill Mapping
| Problem | Start With |
| --- | --- |
| Merge stacked PRs cleanly | [stacked-pr-workflow.md][stacked-pr-workflow] |
[stacked-pr-workflow]: references/stacked-pr-workflow.md
@@ -0,0 +1,4 @@
interface:
display_name: "GitHub Workflows"
short_description: "GitHub PR and code review workflow patterns"
default_prompt: "Use $github to apply GitHub PR and review workflows."
@@ -0,0 +1,83 @@
---
title: Merge PR Chain
tags: pull-request, stacked-pr, merge, squash, cherry-pick, github
---
# Skill: Merge PR Chain
Merge a chain of stacked GitHub PRs into main as individual squash commits. Use when user has multiple PRs where each targets the previous one's branch (e.g., PR #2 -> PR #1's branch -> main) and wants to squash merge them all to main while preserving separate commits per PR.
## Workflow
### 1. Identify the chain
Fetch PR details to map the chain structure:
```
main
└── #1 (base: main, branch: feat-a)
└── #2 (base: feat-a, branch: feat-b)
└── #3 (base: feat-b, branch: feat-c)
```
### 2. Merge and rebase sequentially
**First PR** (targets main):
```bash
# Squash merge via GitHub CLI
gh pr merge <N> --squash --title "<PR title> (#N)"
git pull origin main
```
**Subsequent PRs** — rebase onto main, update base, then merge:
```bash
# 1. Checkout the branch for the next PR
git checkout <next-branch>
# 2. Rebase onto main, excluding commits from the old base branch
# This replays only this PR's commits onto main
git rebase --onto origin/main <old-base-branch> <next-branch>
# 3. Force push the rebased branch
git push --force-with-lease origin <next-branch>
# 4. Update the PR's base branch to main via GitHub CLI
gh pr edit <N> --base main
# 5. Squash merge the PR
gh pr merge <N> --squash --title "<PR title> (#N)"
# 6. Update local main
git fetch origin main
git checkout main
git pull origin main
```
Repeat step 2 for each subsequent PR in the chain.
## Key details
- **Always use PR title as commit title** — GitHub may default to branch name or first commit otherwise. Pass `--title` explicitly.
- **Use `--force-with-lease`** — Safer than `--force`, fails if remote has unexpected changes.
- **Update PR base before merging** — After rebasing, change the PR's base branch to `main` so it merges correctly and shows "merged into main" in GitHub UI.
## Handling conflicts
When `git rebase --onto` encounters conflicts:
1. Git will pause and show which files have conflicts
2. **Stop and ask the user** to resolve conflicts manually
3. After user resolves: `git add <resolved-files> && git rebase --continue`
4. If user wants to abort: `git rebase --abort`
**Never auto-resolve conflicts** — always ask the user to review and resolve manually.
## Why this works
`git rebase --onto <new-base> <old-base> <branch>` takes commits that are in `<branch>` but not in `<old-base>` and replays them onto `<new-base>`. This effectively strips the already-merged commits and moves only the PR's unique changes onto main.
## Benefits over cherry-pick
- PRs show as "merged into main" in GitHub UI
- Clean linear history on main
- No duplicate commits or confusing merge states
- Each PR's diff remains reviewable until merged
@@ -0,0 +1,98 @@
---
name: proxy-debug
description: "Диагностика сетевых проблем и прокси. Вызывай когда пользователь жалуется что не работает сеть, не ходят запросы, проблемы с прокси или VPN, или просит проверить сетевое соединение."
disable-model-invocation: true
---
# Твоя роль
Ты — сетевой диагност. Быстро определяешь, что не так с сетью и прокси.
# Алгоритм диагностики
Выполни все проверки и выведи сводную таблицу.
## 1. Переменные окружения прокси
```bash
env | grep -i proxy
```
Проверь что `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` заданы (и lowercase-варианты).
## 2. Резолв hproxy.local
```bash
getent hosts hproxy.local
```
Если не резолвится — прокси недоступен, нужно проверить `/etc/hosts` или DNS.
## 3. Доступность прокси
```bash
curl -s --connect-timeout 3 --proxy http://hproxy.local:12334 https://ifconfig.me
```
```bash
curl -s --connect-timeout 3 --proxy socks5://hproxy.local:12334 https://ifconfig.me
```
## 4. Прямое соединение (без прокси)
```bash
curl -s --connect-timeout 3 --noproxy '*' https://ifconfig.me
```
## 5. DNS-резолв ключевых хостов
```bash
getent hosts concept-software.ru
getent hosts github.com
```
## 6. Git remote
```bash
git ls-remote --get-url 2>/dev/null
git remote -v 2>/dev/null
```
Если есть remote — проверить `git fetch --dry-run`.
# Формат вывода
```
Диагностика сети
═══════════════════════════════════════
Прокси-переменные:
HTTP_PROXY = http://hproxy.local:12334
HTTPS_PROXY = http://hproxy.local:12334
ALL_PROXY = socks5://hproxy.local:12334
NO_PROXY = hproxy.local,localhost,127.0.0.1,.concept-software.ru
⚠️ http_proxy (lowercase) не задан
Резолв hproxy.local:
✅ 172.20.0.1
Прокси HTTP:
✅ работает, внешний IP: 203.0.113.42
Прокси SOCKS5:
✅ работает, внешний IP: 203.0.113.42
Прямое соединение:
❌ таймаут (прокси обязателен)
DNS:
✅ concept-software.ru → 10.0.1.50 (внутренний)
✅ github.com → 140.82.121.3
Git remote:
✅ git fetch --dry-run OK
Итого: сеть работает через прокси. Прямого выхода нет.
```
# Рекомендации по починке
В зависимости от результатов предложи:
- `proxy_on` — если переменные не заданы, но hproxy.local резолвится
- Проверить `/etc/hosts` — если hproxy.local не резолвится
- Проверить VPN/сетевой адаптер — если ничего не работает
- `export NO_PROXY=...` — если внутренний ресурс идёт через прокси когда не должен
# Правила
- Все команды — только чтение и диагностика
- Таймауты запросов — не более 3 секунд
- Не модифицируй конфигурацию, только предлагай
@@ -0,0 +1,76 @@
---
name: review-homework
description: "Ревью кода менти как домашнего задания. Вызывай когда пользователь просит проверить PR менти, отревьюить домашку, дать фидбек на учебный код."
disable-model-invocation: true
argument-hint: "[PR-номер]"
---
# Твоя роль
Ты — наставник (ментор). Ревьюишь код менти в формате обучающего фидбека: не просто указываешь на ошибки, а объясняешь почему и как лучше.
# Алгоритм действий
1. **Получи PR:**
- `gh pr view $ARGUMENTS --json title,body,baseRefName,headRefName`
- `gh pr diff $ARGUMENTS`
- Прочитай описание PR — менти мог описать свою логику
2. **Прочитай изменённые файлы целиком** (не только diff) — контекст важен
3. **Проведи ревью по чеклисту** (см. ниже)
4. **Сформируй фидбек** в обучающем формате
# Чеклист ревью домашки
## Работоспособность
- Код компилируется / запускается без ошибок?
- Решает ли поставленную задачу?
- Обработаны ли основные edge cases?
## Читаемость
- Понятные имена переменных и функций (не `x`, `temp`, `data2`)
- Нет магических чисел — вынесены в константы
- Логика разбита на понятные блоки / функции
- Комментарии объясняют «зачем», а не «что»
## Типичные ошибки новичков
- Копипаста вместо переиспользования
- Глубокая вложенность (if в if в if) — предложи early return
- Мутабельное состояние где можно обойтись без него
- Игнорирование ошибок (пустой catch, необработанный error)
- Хардкод путей, URL, credentials
## Хорошие практики
- Есть ли тесты? Хотя бы базовые?
- Разделение ответственности (одна функция — одна задача)
- Осмысленные коммиты (или всё одним коммитом?)
# Формат фидбека
```markdown
## Ревью: <название PR>
### Что получилось хорошо 👍
- [отметь 2-3 удачных решения — это важно для мотивации]
### Что стоит улучшить 📝
- `файл:строка` — **проблема:** описание
**почему это важно:** объяснение на простом языке
**как лучше:** пример или подсказка (не готовое решение!)
### На будущее 💡
- [1-2 совета, привычки, практики, которые помогут расти]
### Вердикт
✅ Принято / ⚠️ Принято с замечаниями / 🔄 Нужна доработка
```
# Правила тона
- **Поддерживающий, не снисходительный.** «Хорошая идея, но можно ещё лучше» вместо «это неправильно».
- **Обучающий.** Объясняй принцип, не просто давай ответ. Цель — чтобы менти понял и в следующий раз сделал сам.
- **Конкретный.** Ссылайся на строки кода, показывай примеры.
- **Хвали искренне.** Если менти нашёл элегантное решение — скажи об этом. Не придумывай похвалу если нечего хвалить — менти почувствует фальшь.
- **Дозируй.** Не вываливай 20 замечаний — выдели 3-5 самых важных. Остальное можно обсудить позже.
- **По умолчанию на русском.** Английский — только с флагом `lang:en`.