Standaryzuj wcześnie
Ustanów reguły i wzorce przed wzrostem bazy kodu
Narzędzia programistyczne napędzane przez AI osiągają pełny potencjał, gdy całe zespoły używają ich spójnie. Ten przewodnik obejmuje strategie wdrażania Cursor w zespołach, utrzymania spójności i maksymalizacji zbiorowej produktywności.
Stwórz centralne repozytorium dla konfiguracji Cursor całego zespołu:
#!/bin/bash# sync-rules.sh - Dystrybuuj reguły do wszystkich projektów zespołu
REPOS=( "frontend-app" "backend-api" "mobile-app" "admin-dashboard")
for repo in "${REPOS[@]}"; do echo "Synchronizuję reguły do $repo..."
# Sklonuj lub zaktualizuj repo if [ -d "../$repo" ]; then cd "../$repo" && git pull else git clone "git@github.com:company/$repo.git" "../$repo" fi
# Synchronizuj reguły na podstawie typu projektu ./scripts/sync-project-rules.sh "$repo"
# Commituj zmiany cd "../$repo" git add .cursor/ git commit -m "chore: Aktualizuj reguły Cursor z konfiguracji zespołu" git pushdone
{ "mcpServers": { "company-docs": { "command": "npx", "args": ["@company/docs-mcp"], "version": "2.1.0", "env": { "DOCS_URL": "${COMPANY_DOCS_URL}", "API_KEY": "${DOCS_API_KEY}" } }, "jira-integration": { "command": "npx", "args": ["@atlassian/jira-mcp"], "version": "1.5.0", "config": { "instance": "company.atlassian.net", "project": "${JIRA_PROJECT}" } }, "design-system": { "command": "node", "args": ["./mcp/design-system-server.js"], "localPath": true } }}
// Współdzielona pamięć projektuclass ProjectMemoryManager { async syncMemories() { // Zbierz zatwierdzone wspomnienia od wszystkich deweloperów const memories = await this.collectTeamMemories();
// Deduplikuj i waliduj const validated = await this.validateMemories(memories);
// Stwórz skonsolidowany plik pamięci const consolidated = { version: "1.0", updated: new Date().toISOString(), memories: validated, contributors: this.getContributors(memories) };
// Dystrybuuj do zespołu await this.distributeMemories(consolidated); }
private async validateMemories(memories: Memory[]) { // Usuń konflikty const deduped = this.deduplicateMemories(memories);
// Zapewnij dokładność const verified = await this.verifyAgainstCode(deduped);
// Kategoryzuj według pewności return this.categorizeByConfidence(verified); }}
# Baza wiedzy zespołu
## Decyzje architektoniczne
### Decyzja: komunikacja mikroserwisów- **Data**: 2024-03-15- **Zdecydował**: Zespół architektury- **Kontekst**: Potrzeba niezawodnej komunikacji między serwisami- **Decyzja**: Używaj gRPC dla wewnętrznych, REST dla zewnętrznych- **Konsekwencje**: - Wszystkie serwisy muszą implementować interfejsy gRPC - Współdzielone definicje protobuf w centralnym repo - Adaptery REST dla publicznych API
### Decyzja: zarządzanie stanem- **Data**: 2024-04-20- **Zdecydował**: Zespół frontendowy- **Kontekst**: Złożony stan w wielu widokach- **Decyzja**: Zustand dla klienta, React Query dla serwera- **Uzasadnienie**: Proste API, dobry DevEx, właściwa separacja
## Wzorce wyuczone
### Wzorzec: optymistyczne aktualizacje```typescript// Zawsze używaj tego wzorca dla mutacjiconst mutation = useMutation({ mutationFn: updateUser, onMutate: async (newData) => { // Anuluj zapytania w locie await queryClient.cancelQueries(['user', id]);
// Zrób snapshot poprzedniej wartości const previousUser = queryClient.getQueryData(['user', id]);
// Optymistycznie aktualizuj queryClient.setQueryData(['user', id], newData);
// Zwróć kontekst do rollback return { previousUser }; }, onError: (err, newData, context) => { // Rollback przy błędzie queryClient.setQueryData(['user', id], context.previousUser); }, onSettled: () => { // Odśwież niezależnie queryClient.invalidateQueries(['user', id]); }});
// Integruj spostrzeżenia Cursor do przeglądu koduclass CursorReviewAssistant { async enhanceCodeReview(pr: PullRequest) { const enhancements = { aiSuggestions: await this.getAISuggestions(pr), ruleViolations: await this.checkRuleCompliance(pr), performanceImpact: await this.analyzePerformance(pr), securityIssues: await this.runSecurityScan(pr), testCoverage: await this.assessTestCoverage(pr), };
// Wygeneruj komentarz do przeglądu const comment = this.formatReviewComment(enhancements);
// Opublikuj do PR await github.createReviewComment({ pull_number: pr.number, body: comment, event: 'COMMENT', }); }
private formatReviewComment(enhancements: ReviewEnhancements): string { return `## Asystent przeglądu Cursor AI
### Zgodność z regułami${this.formatRuleViolations(enhancements.ruleViolations)}
### Sugestie AI${this.formatSuggestions(enhancements.aiSuggestions)}
### Analiza wydajności${this.formatPerformance(enhancements.performanceImpact)}
### Skanowanie bezpieczeństwa${this.formatSecurity(enhancements.securityIssues)}
### Pokrycie testami${this.formatCoverage(enhancements.testCoverage)} `; }}
Skonfiguruj agentów w tle
# Skonfiguruj integrację Slackcursor slack setup
# Połącz z workspacecursor slack link --workspace=company.slack.com
# Skonfiguruj kanałycursor slack configure --channel=#dev-team --notify=all
Stwórz przepływy pracy współpracy
// Handlery komend Slack używające Cursor CLIimport { exec } from 'child_process';import { promisify } from 'util';
const execAsync = promisify(exec);
const slackCommands = { '/cursor-explain': async (code: string) => { // Zapisz kod do pliku tymczasowego i użyj Cursor do wyjaśnienia await fs.writeFileSync('/tmp/code-to-explain.ts', code); const { stdout } = await execAsync( 'cursor /tmp/code-to-explain.ts -p "Wyjaśnij ten kod w prostych słowach"' ); return formatExplanation(stdout); },
'/cursor-review': async (prUrl: string) => { // Użyj Cursor do przeglądu PR const { stdout } = await execAsync( `cursor . -p "Przejrzyj PR z ${prUrl} pod kątem jakości kodu i najlepszych praktyk"` ); return formatReview(stdout); },
'/cursor-debug': async (error: string) => { // Użyj Cursor do debugowania błędu const { stdout } = await execAsync( `cursor . -p "Debuguj ten błąd i zasugeruj rozwiązania: ${error}"` ); return formatSolution(stdout); },};
Monitoruj aktywność zespołu
// Dashboard aktywności zespołuclass TeamActivityMonitor { async generateDailyReport() { const activities = await this.collectActivities();
return { codeGenerated: activities.linesGenerated, bugsFixed: activities.issuesResolved, testsWritten: activities.testsCreated, refactorings: activities.refactorCount, topContributors: activities.mostActive, aiUsageStats: activities.modelUsage, }; }}
// Integracja Cursor + Live Shareclass CollaborativeSession { async startPairProgramming(sessionConfig: SessionConfig) { // Uruchom VS Code Live Share const session = await vscode.liveshare.share();
// Stwórz współdzieloną konfigurację Cursor const cursorConfig = { // Współdzielone reguły dla sesji rulesPath: '.cursor/team-rules', // Współdzielone pliki kontekstu contextFiles: ['CLAUDE.md', 'docs/architecture.md'], // Preferencje modelu model: 'claude-3.5-sonnet', };
// Zapisz konfigurację dla wszystkich uczestników await fs.writeFileSync( '.cursor/collaborative-session.json', JSON.stringify(cursorConfig, null, 2) );
// Ustaw synchronizację w czasie rzeczywistym session.onDidChangeParticipants((participants) => { // Powiadom uczestników o przeładowaniu konfiguracji Cursor this.notifyConfigUpdate(participants); });
return { sessionUrl: session.url, accessCode: session.accessCode, instructions: 'Wszyscy uczestnicy powinni otworzyć Cursor ze współdzieloną konfiguracją', }; }}
#!/bin/bashecho "Witaj w zespole! Konfiguruję twoje środowisko Cursor..."
# 1. Zainstaluj Cursorif ! command -v cursor &> /dev/null; then echo "Instaluję Cursor..." brew install --cask cursorfi
# 2. Sklonuj konfigurację zespoługit clone git@github.com:company/cursor-team-config.git ~/.cursor-team
# 3. Skonfiguruj uwierzytelnianieecho "Konfiguruję SSO..."cursor auth login --sso --domain=company.com
# 4. Zainstaluj serwery MCP zespołuecho "Instaluję serwery MCP zespołu..."cd ~/.cursor-team && npm install
# 5. Synchronizuj regułyecho "Synchronizuję reguły zespołu..."./scripts/sync-rules.sh --user
# 6. Skonfiguruj workspaceecho "Konfiguruję workspace..."cursor config set --team-defaults
# 7. Uruchom weryfikacjęecho "Weryfikuję konfigurację..."./scripts/verify-setup.sh
echo "Konfiguracja zakończona! Jesteś gotowy do rozpoczęcia kodowania z zespołem."
// Metryki wydajności zespołu w czasie rzeczywistymclass TeamMetricsDashboard { metrics = { productivity: { codeGenerated: new MetricCollector('lines_generated'), tasksCompleted: new MetricCollector('tasks_completed'), bugsFixed: new MetricCollector('bugs_fixed'), testsWritten: new MetricCollector('tests_written'), }, efficiency: { timeToComplete: new MetricCollector('task_duration'), aiAcceptanceRate: new MetricCollector('ai_acceptance'), refactorSuccess: new MetricCollector('refactor_success'), reviewTurnaround: new MetricCollector('review_time'), }, quality: { bugRate: new MetricCollector('bugs_per_kloc'), testCoverage: new MetricCollector('coverage_percent'), codeComplexity: new MetricCollector('complexity_score'), ruleCompliance: new MetricCollector('rule_adherence'), }, };
async generateTeamReport(): Promise<TeamReport> { const period = { start: lastWeek(), end: now() };
return { summary: await this.calculateSummary(period), trends: await this.analyzeTrends(period), recommendations: await this.generateRecommendations(), individualMetrics: await this.getIndividualStats(period), }; }}
// Alokacja zasobów całego zespołu{ "cursor.team.resources": { "tokenAllocation": { "method": "dynamic", "baseAllocation": 100000, "bonusPool": 500000, "allocationRules": { "priority": "task-based", "weights": { "feature-development": 0.4, "bug-fixes": 0.3, "refactoring": 0.2, "documentation": 0.1 } } }, "modelAccess": { "default": "claude-4-sonnet", "elevated": { "criteria": "complexity > 8 || priority === 'critical'", "model": "claude-4.1-opus" } } }}
// Automatyczne rozwiązywanie konfliktówclass RuleConflictResolver { async resolveConflicts(conflicts: RuleConflict[]) { for (const conflict of conflicts) { const resolution = await this.determineResolution(conflict);
switch (resolution.type) { case 'merge': await this.mergeRules(conflict.rules); break;
case 'prioritize': await this.prioritizeRule(resolution.winner); break;
case 'escalate': await this.escalateToTeam(conflict); break; } } }
private async determineResolution(conflict: RuleConflict) { // Sprawdź, czy reguły można połączyć if (this.areMergeable(conflict.rules)) { return { type: 'merge' }; }
// Sprawdź poziomy priorytetów const priorities = conflict.rules.map((r) => r.priority); if (Math.max(...priorities) > Math.min(...priorities)) { return { type: 'prioritize', winner: conflict.rules.find((r) => r.priority === Math.max(...priorities)), }; }
// Eskaluj do zespołu return { type: 'escalate' }; }}
// Asystent rozwiązywania konfliktów merge wspomagany przez AIclass MergeConflictAssistant { async resolveMergeConflict(conflictFile: string) { // Stwórz strukturalny prompt dla Cursor const mergePrompt = ` Przeanalizuj ten konflikt merge i zasugeruj najlepsze rozwiązanie: 1. Zrozum intencję obu zmian 2. Zachowaj funkcjonalność z obu gałęzi 3. Wyjaśnij swoje rozumowanie 4. Podaj alternatywne rozwiązania, jeśli to stosowne
Użyj @Git, aby zobaczyć znaczniki konfliktów i historię Użyj @Files, aby zrozumieć szerszy kontekst `;
// Otwórz plik konfliktu w Cursor await execAsync(`cursor "${conflictFile}"`);
// Przewodnik ręcznego rozwiązania return { instructions: [ '1. Otwórz plik konfliktu w Cursor', '2. Użyj trybu Agent (Ctrl+I) z promptem merge', '3. Przejrzyj sugerowane rozwiązanie', '4. Zastosuj zmiany używając przycisku Apply', '5. Przetestuj rozwiązany kod przed commitowaniem', ], prompt: mergePrompt, tips: [ 'Użyj @Git, aby zrozumieć historię zmian', 'Sprawdź @Recent Changes dla kontekstu', 'Uruchom testy po rozwiązaniu', ], }; }}
Standaryzuj wcześnie
Ustanów reguły i wzorce przed wzrostem bazy kodu
Dokumentuj decyzje
Przechwytuj decyzje architektoniczne i wzorce we współdzielonych regułach
Regularna synchronizacja
Zaplanuj cotygodniowe przeglądy i aktualizacje reguł
Monitoruj użycie
Śledź wzorce użycia AI, aby optymalizować przepływy pracy zespołu
## Daily standup wzmocniony przez AI
### Wczoraj- Zakończone: [Podsumowanie commitów Cursor]- Pomoc AI: 85% wskaźnik akceptacji- Rozwiązane blokery: Błąd uwierzytelniania przez tryb Agent
### Dzisiaj- Plan: Zaimplementuj dashboard użytkownika- Podejście: TDD z generowaniem testów Cursor- Zależności: Potrzebuję tokenów designu z Figma MCP
### Blokery- Czekam na dokumentację API- Cursor sugeruje przestarzałe wzorce - potrzeba aktualizacji reguł
## Lista kontrolna przeglądu kodu wspomaganego przez AI- [ ] Zgodność z regułami Cursor zweryfikowana- [ ] Sugestie AI przejrzane i zastosowane- [ ] Pokrycie testami spełnia standardy- [ ] Wpływ na wydajność przeanalizowany- [ ] Skanowanie bezpieczeństwa przeszło- [ ] Dokumentacja zaktualizowana
### Spostrzeżenia AI- Sugerowane optymalizacje: 3 zastosowane, 1 odrzucona- Naruszenia wzorców: Brak- Wynik złożoności: 4.2 (akceptowalny)
2-5 deweloperów
6-20 deweloperów
20-50 deweloperów
50+ deweloperów
Metryka | Cel | Pomiar |
---|---|---|
Wskaźnik akceptacji AI | >80% | Zaakceptowane sugestie / Wszystkie sugestie |
Czas do funkcji | -40% | Średni czas ukończenia funkcji |
Wskaźnik wprowadzania błędów | -60% | Błędy na 1000 linii kodu |
Czas przeglądu kodu | -50% | Średni czas przeglądu PR |
Czas wdrożenia | -70% | Czas do pierwszego commit produkcyjnego |
Pamiętaj: współpraca zespołowa z AI polega na wzmacnianiu zbiorowej inteligencji. Gdy jest dobrze wykonana, zespół staje się czymś więcej niż sumą swoich części.