diff --git a/.agents/skills/coding-standards/SKILL.md b/.agents/skills/coding-standards/SKILL.md index 741136f6..bed853ad 100644 --- a/.agents/skills/coding-standards/SKILL.md +++ b/.agents/skills/coding-standards/SKILL.md @@ -414,8 +414,9 @@ export async function searchMarkets( import { useMemo, useCallback } from 'react' // PASS: GOOD: Memoize expensive computations +// Copy before sorting - Array.prototype.sort mutates in place const sortedMarkets = useMemo(() => { - return markets.sort((a, b) => b.volume - a.volume) + return [...markets].sort((a, b) => b.volume - a.volume) }, [markets]) // PASS: GOOD: Memoize callbacks diff --git a/.agents/skills/frontend-patterns/SKILL.md b/.agents/skills/frontend-patterns/SKILL.md index 1caf1e40..1c6115f4 100644 --- a/.agents/skills/frontend-patterns/SKILL.md +++ b/.agents/skills/frontend-patterns/SKILL.md @@ -174,28 +174,41 @@ export function useQuery( const [error, setError] = useState(null) const [loading, setLoading] = useState(false) + // Keep the latest fetcher/options in refs so refetch stays referentially + // stable even when callers pass inline functions and object literals. + // Without this, every render creates a new refetch, and the effect below + // re-runs after each state update - an infinite fetch loop. + const fetcherRef = useRef(fetcher) + const optionsRef = useRef(options) + useEffect(() => { + fetcherRef.current = fetcher + optionsRef.current = options + }) + const refetch = useCallback(async () => { setLoading(true) setError(null) try { - const result = await fetcher() + const result = await fetcherRef.current() setData(result) - options?.onSuccess?.(result) + optionsRef.current?.onSuccess?.(result) } catch (err) { const error = err as Error setError(error) - options?.onError?.(error) + optionsRef.current?.onError?.(error) } finally { setLoading(false) } - }, [fetcher, options]) + }, []) + + const enabled = options?.enabled !== false useEffect(() => { - if (options?.enabled !== false) { + if (enabled) { refetch() } - }, [key, refetch, options?.enabled]) + }, [key, enabled, refetch]) return { data, error, loading, refetch } } @@ -300,8 +313,9 @@ export function useMarkets() { ```typescript // PASS: useMemo for expensive computations +// Copy before sorting - Array.prototype.sort mutates in place const sortedMarkets = useMemo(() => { - return markets.sort((a, b) => b.volume - a.volume) + return [...markets].sort((a, b) => b.volume - a.volume) }, [markets]) // PASS: useCallback for functions passed to children diff --git a/.cursor/rules/common-performance.md b/.cursor/rules/common-performance.md index dc65dccb..ec0f93a2 100644 --- a/.cursor/rules/common-performance.md +++ b/.cursor/rules/common-performance.md @@ -16,7 +16,7 @@ alwaysApply: true - Orchestrating multi-agent workflows - Complex coding tasks -**Opus 4.5** (Deepest reasoning): +**Opus 4.6** (Deepest reasoning): - Complex architectural decisions - Maximum reasoning requirements - Research and analysis tasks @@ -41,7 +41,7 @@ Extended thinking is enabled by default, reserving up to 31,999 tokens for inter Control extended thinking via: - **Toggle**: Option+T (macOS) / Alt+T (Windows/Linux) - **Config**: Set `alwaysThinkingEnabled` in `~/.claude/settings.json` -- **Budget cap**: `export MAX_THINKING_TOKENS=10000` +- **Budget cap**: `export MAX_THINKING_TOKENS=10000` (bash) or `$env:MAX_THINKING_TOKENS = "10000"` (PowerShell) - **Verbose mode**: Ctrl+O to see thinking output For complex tasks requiring deep reasoning: diff --git a/.kiro/skills/coding-standards/SKILL.md b/.kiro/skills/coding-standards/SKILL.md index 100f15c8..63770703 100644 --- a/.kiro/skills/coding-standards/SKILL.md +++ b/.kiro/skills/coding-standards/SKILL.md @@ -398,8 +398,9 @@ export async function searchMarkets( import { useMemo, useCallback } from 'react' // PASS: GOOD: Memoize expensive computations +// Copy before sorting - Array.prototype.sort mutates in place const sortedMarkets = useMemo(() => { - return markets.sort((a, b) => b.volume - a.volume) + return [...markets].sort((a, b) => b.volume - a.volume) }, [markets]) // PASS: GOOD: Memoize callbacks diff --git a/.kiro/skills/frontend-patterns/SKILL.md b/.kiro/skills/frontend-patterns/SKILL.md index 0c87affb..18e1a0d2 100644 --- a/.kiro/skills/frontend-patterns/SKILL.md +++ b/.kiro/skills/frontend-patterns/SKILL.md @@ -171,28 +171,41 @@ export function useQuery( const [error, setError] = useState(null) const [loading, setLoading] = useState(false) + // Keep the latest fetcher/options in refs so refetch stays referentially + // stable even when callers pass inline functions and object literals. + // Without this, every render creates a new refetch, and the effect below + // re-runs after each state update - an infinite fetch loop. + const fetcherRef = useRef(fetcher) + const optionsRef = useRef(options) + useEffect(() => { + fetcherRef.current = fetcher + optionsRef.current = options + }) + const refetch = useCallback(async () => { setLoading(true) setError(null) try { - const result = await fetcher() + const result = await fetcherRef.current() setData(result) - options?.onSuccess?.(result) + optionsRef.current?.onSuccess?.(result) } catch (err) { const error = err as Error setError(error) - options?.onError?.(error) + optionsRef.current?.onError?.(error) } finally { setLoading(false) } - }, [fetcher, options]) + }, []) + + const enabled = options?.enabled !== false useEffect(() => { - if (options?.enabled !== false) { + if (enabled) { refetch() } - }, [key, refetch, options?.enabled]) + }, [key, enabled, refetch]) return { data, error, loading, refetch } } @@ -297,8 +310,9 @@ export function useMarkets() { ```typescript // PASS: useMemo for expensive computations +// Copy before sorting - Array.prototype.sort mutates in place const sortedMarkets = useMemo(() => { - return markets.sort((a, b) => b.volume - a.volume) + return [...markets].sort((a, b) => b.volume - a.volume) }, [markets]) // PASS: useCallback for functions passed to children diff --git a/.kiro/steering/performance.md b/.kiro/steering/performance.md index c15dd048..c4733810 100644 --- a/.kiro/steering/performance.md +++ b/.kiro/steering/performance.md @@ -12,12 +12,12 @@ description: Performance optimization guidelines including model selection strat - Pair programming and code generation - Worker agents in multi-agent systems -**Claude Sonnet 4.5** (Best coding model): +**Claude Sonnet 4.6** (Best coding model): - Main development work - Orchestrating multi-agent workflows - Complex coding tasks -**Claude Opus 4.5** (Deepest reasoning): +**Claude Opus 4.6** (Deepest reasoning): - Complex architectural decisions - Maximum reasoning requirements - Research and analysis tasks diff --git a/agents/performance-optimizer.md b/agents/performance-optimizer.md index 83410c8c..84d4e302 100644 --- a/agents/performance-optimizer.md +++ b/agents/performance-optimizer.md @@ -362,14 +362,14 @@ npx lighthouse https://your-app.com --only-categories=performance ### Web Vitals Monitoring ```typescript -// Track Core Web Vitals -import { getCLS, getFID, getLCP, getFCP, getTTFB } from 'web-vitals'; +// Track Core Web Vitals (web-vitals v4 API) +import { onCLS, onINP, onLCP, onFCP, onTTFB } from 'web-vitals'; -getCLS(console.log); // Cumulative Layout Shift -getFID(console.log); // First Input Delay -getLCP(console.log); // Largest Contentful Paint -getFCP(console.log); // First Contentful Paint -getTTFB(console.log); // Time to First Byte +onCLS(console.log); // Cumulative Layout Shift +onINP(console.log); // Interaction to Next Paint +onLCP(console.log); // Largest Contentful Paint +onFCP(console.log); // First Contentful Paint +onTTFB(console.log); // Time to First Byte ``` ## Performance Report Template @@ -393,7 +393,7 @@ getTTFB(console.log); // Time to First Byte | Metric | Current | Target | Status | |--------|---------|--------|--------| | LCP | X.Xs | < 2.5s | PASS: | -| FID | XXms | < 100ms | PASS: | +| INP | XXms | < 200ms | PASS: | | CLS | X.XX | < 0.1 | WARNING: | ## Critical Issues diff --git a/docs/ja-JP/agents/performance-optimizer.md b/docs/ja-JP/agents/performance-optimizer.md index 1f134af9..fae0ee9d 100644 --- a/docs/ja-JP/agents/performance-optimizer.md +++ b/docs/ja-JP/agents/performance-optimizer.md @@ -362,14 +362,14 @@ npx lighthouse https://your-app.com --only-categories=performance ### Web Vitalsモニタリング ```typescript -// Core Web Vitalsの追跡 -import { getCLS, getFID, getLCP, getFCP, getTTFB } from 'web-vitals'; +// Track Core Web Vitals (web-vitals v4 API) +import { onCLS, onINP, onLCP, onFCP, onTTFB } from 'web-vitals'; -getCLS(console.log); // Cumulative Layout Shift -getFID(console.log); // First Input Delay -getLCP(console.log); // Largest Contentful Paint -getFCP(console.log); // First Contentful Paint -getTTFB(console.log); // Time to First Byte +onCLS(console.log); // Cumulative Layout Shift +onINP(console.log); // Interaction to Next Paint +onLCP(console.log); // Largest Contentful Paint +onFCP(console.log); // First Contentful Paint +onTTFB(console.log); // Time to First Byte ``` ## パフォーマンスレポートテンプレート @@ -393,7 +393,7 @@ getTTFB(console.log); // Time to First Byte | メトリクス | 現在 | 目標 | ステータス | |-----------|------|------|----------| | LCP | X.X秒 | < 2.5秒 | PASS: | -| FID | XXms | < 100ms | PASS: | +| INP | XXms | < 200ms | PASS: | | CLS | X.XX | < 0.1 | WARNING: | ## 重大な問題 diff --git a/docs/ja-JP/rules/common/performance.md b/docs/ja-JP/rules/common/performance.md index 43934dbf..c97ed1b0 100644 --- a/docs/ja-JP/rules/common/performance.md +++ b/docs/ja-JP/rules/common/performance.md @@ -7,12 +7,12 @@ - ペアプログラミングとコード生成 - マルチ agent システムのワーカー agent -**Sonnet 4.5**(最高のコーディングモデル): +**Sonnet 4.6**(最高のコーディングモデル): - メイン開発作業 - マルチ agent ワークフローのオーケストレーション - 複雑なコーディングタスク -**Opus 4.5**(最も深い推論): +**Opus 4.6**(最も深い推論): - 複雑なアーキテクチャの意思決定 - 最大限の推論要件 - 調査と分析タスク @@ -37,7 +37,7 @@ 拡張思考の制御: - **トグル**: Option+T(macOS)/ Alt+T(Windows/Linux) - **設定**: `~/.claude/settings.json` で `alwaysThinkingEnabled` を設定 -- **予算上限**: `export MAX_THINKING_TOKENS=10000` +- **予算上限**: `export MAX_THINKING_TOKENS=10000`(bash)または `$env:MAX_THINKING_TOKENS = "10000"`(PowerShell) - **詳細モード**: Ctrl+O で思考出力を表示 深い推論を必要とする複雑なタスクの場合: diff --git a/docs/ja-JP/rules/typescript/security.md b/docs/ja-JP/rules/typescript/security.md index 84cfa2ae..4e61705b 100644 --- a/docs/ja-JP/rules/typescript/security.md +++ b/docs/ja-JP/rules/typescript/security.md @@ -16,10 +16,10 @@ paths: const apiKey = "sk-proj-xxxxx" // 常に: 環境変数 -const apiKey = process.env.OPENAI_API_KEY +const apiKey = process.env.API_KEY if (!apiKey) { - throw new Error('OPENAI_API_KEY not configured') + throw new Error('API_KEY not configured') } ``` diff --git a/docs/ja-JP/skills/frontend-patterns/SKILL.md b/docs/ja-JP/skills/frontend-patterns/SKILL.md index e196d65a..621e29d2 100644 --- a/docs/ja-JP/skills/frontend-patterns/SKILL.md +++ b/docs/ja-JP/skills/frontend-patterns/SKILL.md @@ -158,28 +158,41 @@ export function useQuery( const [error, setError] = useState(null) const [loading, setLoading] = useState(false) + // Keep the latest fetcher/options in refs so refetch stays referentially + // stable even when callers pass inline functions and object literals. + // Without this, every render creates a new refetch, and the effect below + // re-runs after each state update - an infinite fetch loop. + const fetcherRef = useRef(fetcher) + const optionsRef = useRef(options) + useEffect(() => { + fetcherRef.current = fetcher + optionsRef.current = options + }) + const refetch = useCallback(async () => { setLoading(true) setError(null) try { - const result = await fetcher() + const result = await fetcherRef.current() setData(result) - options?.onSuccess?.(result) + optionsRef.current?.onSuccess?.(result) } catch (err) { const error = err as Error setError(error) - options?.onError?.(error) + optionsRef.current?.onError?.(error) } finally { setLoading(false) } - }, [fetcher, options]) + }, []) + + const enabled = options?.enabled !== false useEffect(() => { - if (options?.enabled !== false) { + if (enabled) { refetch() } - }, [key, refetch, options?.enabled]) + }, [key, enabled, refetch]) return { data, error, loading, refetch } } @@ -284,8 +297,9 @@ export function useMarkets() { ```typescript // PASS: useMemo for expensive computations +// Copy before sorting - Array.prototype.sort mutates in place const sortedMarkets = useMemo(() => { - return markets.sort((a, b) => b.volume - a.volume) + return [...markets].sort((a, b) => b.volume - a.volume) }, [markets]) // PASS: useCallback for functions passed to children diff --git a/docs/ja-JP/skills/python-patterns/SKILL.md b/docs/ja-JP/skills/python-patterns/SKILL.md index 7c28891a..a1e2b04c 100644 --- a/docs/ja-JP/skills/python-patterns/SKILL.md +++ b/docs/ja-JP/skills/python-patterns/SKILL.md @@ -56,14 +56,14 @@ Pythonは条件チェックよりも例外処理を好みます。 ```python # Good: EAFP style -def get_value(dictionary: dict, key: str) -> Any: +def get_value(dictionary: dict, key: str, default_value: Any = None) -> Any: try: return dictionary[key] except KeyError: return default_value # Bad: LBYL (Look Before You Leap) style -def get_value(dictionary: dict, key: str) -> Any: +def get_value(dictionary: dict, key: str, default_value: Any = None) -> Any: if key in dictionary: return dictionary[key] else: diff --git a/docs/ko-KR/rules/performance.md b/docs/ko-KR/rules/performance.md index 3252da8e..931925b6 100644 --- a/docs/ko-KR/rules/performance.md +++ b/docs/ko-KR/rules/performance.md @@ -12,7 +12,7 @@ - 멀티 에이전트 워크플로우 오케스트레이션 - 복잡한 코딩 작업 -**Opus 4.5** (가장 깊은 추론): +**Opus 4.6** (가장 깊은 추론): - 복잡한 아키텍처 의사결정 - 최대 추론 요구사항 - 리서치 및 분석 작업 @@ -37,7 +37,7 @@ 확장 사고 제어 방법: - **전환**: Option+T (macOS) / Alt+T (Windows/Linux) - **설정**: `~/.claude/settings.json`에서 `alwaysThinkingEnabled` 설정 -- **예산 제한**: `export MAX_THINKING_TOKENS=10000` +- **예산 제한**: `export MAX_THINKING_TOKENS=10000` (bash) 또는 `$env:MAX_THINKING_TOKENS = "10000"` (PowerShell) - **상세 모드**: Ctrl+O로 사고 출력 확인 깊은 추론이 필요한 복잡한 작업: diff --git a/docs/pt-BR/rules/performance.md b/docs/pt-BR/rules/performance.md index 064efd40..07f5cd34 100644 --- a/docs/pt-BR/rules/performance.md +++ b/docs/pt-BR/rules/performance.md @@ -12,7 +12,7 @@ - Orquestrando fluxos de trabalho multi-agente - Tarefas de codificação complexas -**Opus 4.5** (Raciocínio mais profundo): +**Opus 4.6** (Raciocínio mais profundo): - Decisões arquiteturais complexas - Requisitos máximos de raciocínio - Pesquisa e análise @@ -37,7 +37,7 @@ O pensamento estendido está habilitado por padrão, reservando até 31.999 toke Controle o pensamento estendido via: - **Toggle**: Option+T (macOS) / Alt+T (Windows/Linux) - **Config**: Defina `alwaysThinkingEnabled` em `~/.claude/settings.json` -- **Limite de orçamento**: `export MAX_THINKING_TOKENS=10000` +- **Limite de orçamento**: `export MAX_THINKING_TOKENS=10000` (bash) ou `$env:MAX_THINKING_TOKENS = "10000"` (PowerShell) - **Modo verbose**: Ctrl+O para ver a saída de pensamento Para tarefas complexas que requerem raciocínio profundo: diff --git a/docs/tr/rules/common/performance.md b/docs/tr/rules/common/performance.md index 736385d4..2312099b 100644 --- a/docs/tr/rules/common/performance.md +++ b/docs/tr/rules/common/performance.md @@ -12,7 +12,7 @@ - Multi-agent iş akışlarını orkestrasyon - Karmaşık kodlama görevleri -**Opus 4.5** (En derin akıl yürütme): +**Opus 4.6** (En derin akıl yürütme): - Karmaşık mimari kararlar - Maksimum akıl yürütme gereksinimleri - Araştırma ve analiz görevleri @@ -37,7 +37,7 @@ Extended thinking varsayılan olarak etkindir ve dahili akıl yürütme için 31 Extended thinking kontrolü: - **Toggle**: Option+T (macOS) / Alt+T (Windows/Linux) - **Config**: `~/.claude/settings.json` içinde `alwaysThinkingEnabled` ayarla -- **Budget cap**: `export MAX_THINKING_TOKENS=10000` +- **Budget cap**: `export MAX_THINKING_TOKENS=10000` (bash) veya `$env:MAX_THINKING_TOKENS = "10000"` (PowerShell) - **Verbose mode**: Thinking çıktısını görmek için Ctrl+O Derin akıl yürütme gerektiren karmaşık görevler için: diff --git a/docs/tr/rules/typescript/security.md b/docs/tr/rules/typescript/security.md index f338fa2d..d6d976e9 100644 --- a/docs/tr/rules/typescript/security.md +++ b/docs/tr/rules/typescript/security.md @@ -16,10 +16,10 @@ paths: const apiKey = "sk-proj-xxxxx" // DAIMA: Environment variable'lar -const apiKey = process.env.OPENAI_API_KEY +const apiKey = process.env.API_KEY if (!apiKey) { - throw new Error('OPENAI_API_KEY not configured') + throw new Error('API_KEY not configured') } ``` diff --git a/docs/tr/skills/frontend-patterns/SKILL.md b/docs/tr/skills/frontend-patterns/SKILL.md index 8a0ecc8f..86c62520 100644 --- a/docs/tr/skills/frontend-patterns/SKILL.md +++ b/docs/tr/skills/frontend-patterns/SKILL.md @@ -169,28 +169,42 @@ export function useQuery( const [error, setError] = useState(null) const [loading, setLoading] = useState(false) + // Çağıranlar satır içi fonksiyonlar ve nesne literalleri geçirse bile + // refetch'in referans olarak kararlı kalması için en güncel fetcher/options + // değerlerini ref'lerde tutun. Bu olmadan her render yeni bir refetch + // oluşturur ve aşağıdaki effect her state güncellemesinden sonra yeniden + // çalışır - sonsuz bir fetch döngüsü. + const fetcherRef = useRef(fetcher) + const optionsRef = useRef(options) + useEffect(() => { + fetcherRef.current = fetcher + optionsRef.current = options + }) + const refetch = useCallback(async () => { setLoading(true) setError(null) try { - const result = await fetcher() + const result = await fetcherRef.current() setData(result) - options?.onSuccess?.(result) + optionsRef.current?.onSuccess?.(result) } catch (err) { const error = err as Error setError(error) - options?.onError?.(error) + optionsRef.current?.onError?.(error) } finally { setLoading(false) } - }, [fetcher, options]) + }, []) + + const enabled = options?.enabled !== false useEffect(() => { - if (options?.enabled !== false) { + if (enabled) { refetch() } - }, [key, refetch, options?.enabled]) + }, [key, enabled, refetch]) return { data, error, loading, refetch } } @@ -295,8 +309,9 @@ export function useMarkets() { ```typescript // PASS: Pahalı hesaplamalar için useMemo +// Sıralamadan önce kopyalayın - Array.prototype.sort yerinde değiştirir const sortedMarkets = useMemo(() => { - return markets.sort((a, b) => b.volume - a.volume) + return [...markets].sort((a, b) => b.volume - a.volume) }, [markets]) // PASS: Alt bileşenlere geçirilen fonksiyonlar için useCallback diff --git a/docs/tr/skills/python-patterns/SKILL.md b/docs/tr/skills/python-patterns/SKILL.md index b020f246..75e95b14 100644 --- a/docs/tr/skills/python-patterns/SKILL.md +++ b/docs/tr/skills/python-patterns/SKILL.md @@ -57,14 +57,14 @@ Python, koşulları kontrol etmek yerine exception handling'i tercih eder. ```python # İyi: EAFP stili -def get_value(dictionary: dict, key: str) -> Any: +def get_value(dictionary: dict, key: str, default_value: Any = None) -> Any: try: return dictionary[key] except KeyError: return default_value # Kötü: LBYL (Atlamadan Önce Bak) stili -def get_value(dictionary: dict, key: str) -> Any: +def get_value(dictionary: dict, key: str, default_value: Any = None) -> Any: if key in dictionary: return dictionary[key] else: diff --git a/docs/zh-CN/agents/performance-optimizer.md b/docs/zh-CN/agents/performance-optimizer.md index 3554ca6d..c203ae41 100644 --- a/docs/zh-CN/agents/performance-optimizer.md +++ b/docs/zh-CN/agents/performance-optimizer.md @@ -353,14 +353,14 @@ npx lighthouse https://your-app.com --only-categories=performance ### Web Vitals 监控 ```typescript -// Track Core Web Vitals -import { getCLS, getFID, getLCP, getFCP, getTTFB } from 'web-vitals'; +// Track Core Web Vitals (web-vitals v4 API) +import { onCLS, onINP, onLCP, onFCP, onTTFB } from 'web-vitals'; -getCLS(console.log); // Cumulative Layout Shift -getFID(console.log); // First Input Delay -getLCP(console.log); // Largest Contentful Paint -getFCP(console.log); // First Contentful Paint -getTTFB(console.log); // Time to First Byte +onCLS(console.log); // Cumulative Layout Shift +onINP(console.log); // Interaction to Next Paint +onLCP(console.log); // Largest Contentful Paint +onFCP(console.log); // First Contentful Paint +onTTFB(console.log); // Time to First Byte ``` ## 性能报告模板 @@ -384,7 +384,7 @@ getTTFB(console.log); // Time to First Byte | 指标 | 当前值 | 目标值 | 状态 | |--------|---------|--------|--------| | LCP | X.X秒 | < 2.5秒 | 通过: | -| FID | XX毫秒 | < 100毫秒 | 通过: | +| INP | XX毫秒 | < 200毫秒 | 通过: | | CLS | X.XX | < 0.1 | 警告: | ## 关键问题 diff --git a/docs/zh-CN/rules/common/performance.md b/docs/zh-CN/rules/common/performance.md index c171e61d..7dcf4d89 100644 --- a/docs/zh-CN/rules/common/performance.md +++ b/docs/zh-CN/rules/common/performance.md @@ -14,7 +14,7 @@ * 编排多智能体工作流 * 复杂的编码任务 -**Opus 4.5** (最深的推理能力): +**Opus 4.6** (最深的推理能力): * 复杂的架构决策 * 最高级别的推理需求 @@ -43,7 +43,7 @@ * **切换**:Option+T (macOS) / Alt+T (Windows/Linux) * **配置**:在 `~/.claude/settings.json` 中设置 `alwaysThinkingEnabled` -* **预算上限**:`export MAX_THINKING_TOKENS=10000` +* **预算上限**:`export MAX_THINKING_TOKENS=10000`(bash)或 `$env:MAX_THINKING_TOKENS = "10000"`(PowerShell) * **详细模式**:Ctrl+O 查看思考输出 对于需要深度推理的复杂任务: diff --git a/docs/zh-CN/rules/typescript/security.md b/docs/zh-CN/rules/typescript/security.md index 87e17448..7849aee0 100644 --- a/docs/zh-CN/rules/typescript/security.md +++ b/docs/zh-CN/rules/typescript/security.md @@ -17,10 +17,10 @@ paths: const apiKey = "sk-proj-xxxxx" // ALWAYS: Environment variables -const apiKey = process.env.OPENAI_API_KEY +const apiKey = process.env.API_KEY if (!apiKey) { - throw new Error('OPENAI_API_KEY not configured') + throw new Error('API_KEY not configured') } ``` diff --git a/docs/zh-CN/skills/coding-standards/SKILL.md b/docs/zh-CN/skills/coding-standards/SKILL.md index 4fc45089..2d5fb86b 100644 --- a/docs/zh-CN/skills/coding-standards/SKILL.md +++ b/docs/zh-CN/skills/coding-standards/SKILL.md @@ -400,8 +400,9 @@ export async function searchMarkets( import { useMemo, useCallback } from 'react' // PASS: GOOD: Memoize expensive computations +// Copy before sorting - Array.prototype.sort mutates in place const sortedMarkets = useMemo(() => { - return markets.sort((a, b) => b.volume - a.volume) + return [...markets].sort((a, b) => b.volume - a.volume) }, [markets]) // PASS: GOOD: Memoize callbacks diff --git a/docs/zh-CN/skills/frontend-patterns/SKILL.md b/docs/zh-CN/skills/frontend-patterns/SKILL.md index 2ba29cdb..99af5f46 100644 --- a/docs/zh-CN/skills/frontend-patterns/SKILL.md +++ b/docs/zh-CN/skills/frontend-patterns/SKILL.md @@ -169,28 +169,41 @@ export function useQuery( const [error, setError] = useState(null) const [loading, setLoading] = useState(false) + // Keep the latest fetcher/options in refs so refetch stays referentially + // stable even when callers pass inline functions and object literals. + // Without this, every render creates a new refetch, and the effect below + // re-runs after each state update - an infinite fetch loop. + const fetcherRef = useRef(fetcher) + const optionsRef = useRef(options) + useEffect(() => { + fetcherRef.current = fetcher + optionsRef.current = options + }) + const refetch = useCallback(async () => { setLoading(true) setError(null) try { - const result = await fetcher() + const result = await fetcherRef.current() setData(result) - options?.onSuccess?.(result) + optionsRef.current?.onSuccess?.(result) } catch (err) { const error = err as Error setError(error) - options?.onError?.(error) + optionsRef.current?.onError?.(error) } finally { setLoading(false) } - }, [fetcher, options]) + }, []) + + const enabled = options?.enabled !== false useEffect(() => { - if (options?.enabled !== false) { + if (enabled) { refetch() } - }, [key, refetch, options?.enabled]) + }, [key, enabled, refetch]) return { data, error, loading, refetch } } @@ -295,8 +308,9 @@ export function useMarkets() { ```typescript // PASS: useMemo for expensive computations +// Copy before sorting - Array.prototype.sort mutates in place const sortedMarkets = useMemo(() => { - return markets.sort((a, b) => b.volume - a.volume) + return [...markets].sort((a, b) => b.volume - a.volume) }, [markets]) // PASS: useCallback for functions passed to children diff --git a/docs/zh-CN/skills/python-patterns/SKILL.md b/docs/zh-CN/skills/python-patterns/SKILL.md index ed66ce33..57719507 100644 --- a/docs/zh-CN/skills/python-patterns/SKILL.md +++ b/docs/zh-CN/skills/python-patterns/SKILL.md @@ -57,14 +57,14 @@ Python 倾向于使用异常处理而非检查条件。 ```python # Good: EAFP style -def get_value(dictionary: dict, key: str) -> Any: +def get_value(dictionary: dict, key: str, default_value: Any = None) -> Any: try: return dictionary[key] except KeyError: return default_value # Bad: LBYL (Look Before You Leap) style -def get_value(dictionary: dict, key: str) -> Any: +def get_value(dictionary: dict, key: str, default_value: Any = None) -> Any: if key in dictionary: return dictionary[key] else: diff --git a/docs/zh-TW/rules/performance.md b/docs/zh-TW/rules/performance.md index 577612eb..78f85c6b 100644 --- a/docs/zh-TW/rules/performance.md +++ b/docs/zh-TW/rules/performance.md @@ -7,12 +7,12 @@ - 配對程式設計和程式碼產生 - 多 agent 系統中的 worker agents -**Sonnet 4.5**(最佳程式碼模型): +**Sonnet 4.6**(最佳程式碼模型): - 主要開發工作 - 協調多 agent 工作流程 - 複雜程式碼任務 -**Opus 4.5**(最深度推理): +**Opus 4.6**(最深度推理): - 複雜架構決策 - 最大推理需求 - 研究和分析任務 diff --git a/docs/zh-TW/skills/frontend-patterns/SKILL.md b/docs/zh-TW/skills/frontend-patterns/SKILL.md index 252854a3..accce837 100644 --- a/docs/zh-TW/skills/frontend-patterns/SKILL.md +++ b/docs/zh-TW/skills/frontend-patterns/SKILL.md @@ -158,28 +158,41 @@ export function useQuery( const [error, setError] = useState(null) const [loading, setLoading] = useState(false) + // 將最新的 fetcher/options 保存在 ref 中,讓 refetch 即使在呼叫端 + // 傳入行內函式與物件字面值時也能保持參照穩定。 + // 若沒有這麼做,每次渲染都會建立新的 refetch,下方的 effect 會在 + // 每次狀態更新後重新執行,造成無限取得迴圈。 + const fetcherRef = useRef(fetcher) + const optionsRef = useRef(options) + useEffect(() => { + fetcherRef.current = fetcher + optionsRef.current = options + }) + const refetch = useCallback(async () => { setLoading(true) setError(null) try { - const result = await fetcher() + const result = await fetcherRef.current() setData(result) - options?.onSuccess?.(result) + optionsRef.current?.onSuccess?.(result) } catch (err) { const error = err as Error setError(error) - options?.onError?.(error) + optionsRef.current?.onError?.(error) } finally { setLoading(false) } - }, [fetcher, options]) + }, []) + + const enabled = options?.enabled !== false useEffect(() => { - if (options?.enabled !== false) { + if (enabled) { refetch() } - }, [key, refetch, options?.enabled]) + }, [key, enabled, refetch]) return { data, error, loading, refetch } } @@ -284,8 +297,9 @@ export function useMarkets() { ```typescript // PASS: useMemo 用於昂貴計算 +// 排序前先複製 - Array.prototype.sort 會就地修改陣列 const sortedMarkets = useMemo(() => { - return markets.sort((a, b) => b.volume - a.volume) + return [...markets].sort((a, b) => b.volume - a.volume) }, [markets]) // PASS: useCallback 用於傳遞給子元件的函式 diff --git a/rules/common/performance.md b/rules/common/performance.md index 3ffff1b8..f0407aa1 100644 --- a/rules/common/performance.md +++ b/rules/common/performance.md @@ -12,7 +12,7 @@ - Orchestrating multi-agent workflows - Complex coding tasks -**Opus 4.5** (Deepest reasoning): +**Opus 4.6** (Deepest reasoning): - Complex architectural decisions - Maximum reasoning requirements - Research and analysis tasks @@ -37,7 +37,7 @@ Extended thinking is enabled by default, reserving up to 31,999 tokens for inter Control extended thinking via: - **Toggle**: Option+T (macOS) / Alt+T (Windows/Linux) - **Config**: Set `alwaysThinkingEnabled` in `~/.claude/settings.json` -- **Budget cap**: `export MAX_THINKING_TOKENS=10000` +- **Budget cap**: `export MAX_THINKING_TOKENS=10000` (bash) or `$env:MAX_THINKING_TOKENS = "10000"` (PowerShell) - **Verbose mode**: Ctrl+O to see thinking output For complex tasks requiring deep reasoning: diff --git a/rules/typescript/security.md b/rules/typescript/security.md index 98ba4008..e2b01d8c 100644 --- a/rules/typescript/security.md +++ b/rules/typescript/security.md @@ -16,10 +16,10 @@ paths: const apiKey = "sk-proj-xxxxx" // ALWAYS: Environment variables -const apiKey = process.env.OPENAI_API_KEY +const apiKey = process.env.API_KEY if (!apiKey) { - throw new Error('OPENAI_API_KEY not configured') + throw new Error('API_KEY not configured') } ``` diff --git a/skills/coding-standards/SKILL.md b/skills/coding-standards/SKILL.md index 48a62811..7fa61987 100644 --- a/skills/coding-standards/SKILL.md +++ b/skills/coding-standards/SKILL.md @@ -415,8 +415,9 @@ export async function searchMarkets( import { useMemo, useCallback } from 'react' // PASS: GOOD: Memoize expensive computations +// Copy before sorting - Array.prototype.sort mutates in place const sortedMarkets = useMemo(() => { - return markets.sort((a, b) => b.volume - a.volume) + return [...markets].sort((a, b) => b.volume - a.volume) }, [markets]) // PASS: GOOD: Memoize callbacks diff --git a/skills/frontend-patterns/SKILL.md b/skills/frontend-patterns/SKILL.md index ef0de63f..7c5aa11a 100644 --- a/skills/frontend-patterns/SKILL.md +++ b/skills/frontend-patterns/SKILL.md @@ -169,28 +169,41 @@ export function useQuery( const [error, setError] = useState(null) const [loading, setLoading] = useState(false) + // Keep the latest fetcher/options in refs so refetch stays referentially + // stable even when callers pass inline functions and object literals. + // Without this, every render creates a new refetch, and the effect below + // re-runs after each state update - an infinite fetch loop. + const fetcherRef = useRef(fetcher) + const optionsRef = useRef(options) + useEffect(() => { + fetcherRef.current = fetcher + optionsRef.current = options + }) + const refetch = useCallback(async () => { setLoading(true) setError(null) try { - const result = await fetcher() + const result = await fetcherRef.current() setData(result) - options?.onSuccess?.(result) + optionsRef.current?.onSuccess?.(result) } catch (err) { const error = err as Error setError(error) - options?.onError?.(error) + optionsRef.current?.onError?.(error) } finally { setLoading(false) } - }, [fetcher, options]) + }, []) + + const enabled = options?.enabled !== false useEffect(() => { - if (options?.enabled !== false) { + if (enabled) { refetch() } - }, [key, refetch, options?.enabled]) + }, [key, enabled, refetch]) return { data, error, loading, refetch } } @@ -295,8 +308,9 @@ export function useMarkets() { ```typescript // PASS: useMemo for expensive computations +// Copy before sorting - Array.prototype.sort mutates in place const sortedMarkets = useMemo(() => { - return markets.sort((a, b) => b.volume - a.volume) + return [...markets].sort((a, b) => b.volume - a.volume) }, [markets]) // PASS: useCallback for functions passed to children diff --git a/skills/python-patterns/SKILL.md b/skills/python-patterns/SKILL.md index ba1156dc..f103c069 100644 --- a/skills/python-patterns/SKILL.md +++ b/skills/python-patterns/SKILL.md @@ -57,14 +57,14 @@ Python prefers exception handling over checking conditions. ```python # Good: EAFP style -def get_value(dictionary: dict, key: str) -> Any: +def get_value(dictionary: dict, key: str, default_value: Any = None) -> Any: try: return dictionary[key] except KeyError: return default_value # Bad: LBYL (Look Before You Leap) style -def get_value(dictionary: dict, key: str) -> Any: +def get_value(dictionary: dict, key: str, default_value: Any = None) -> Any: if key in dictionary: return dictionary[key] else: