autosnippet 3.0.3 → 3.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +85 -240
  2. package/dashboard/dist/assets/{icons-Cdq22n2i.js → icons-eQ_rWCus.js} +97 -102
  3. package/dashboard/dist/assets/index-B3Nnkdxi.js +133 -0
  4. package/dashboard/dist/assets/index-BFNDAqh3.css +1 -0
  5. package/dashboard/dist/index.html +3 -3
  6. package/lib/core/AstAnalyzer.js +2 -2
  7. package/lib/core/ast/ensure-grammars.js +2 -0
  8. package/lib/core/ast/index.js +8 -0
  9. package/lib/core/ast/lang-rust.js +695 -0
  10. package/lib/core/discovery/PythonDiscoverer.js +3 -0
  11. package/lib/core/discovery/RustDiscoverer.js +467 -0
  12. package/lib/core/discovery/index.js +3 -0
  13. package/lib/core/enhancement/django-enhancement.js +169 -3
  14. package/lib/core/enhancement/fastapi-enhancement.js +149 -3
  15. package/lib/core/enhancement/go-grpc-enhancement.js +4 -0
  16. package/lib/core/enhancement/go-web-enhancement.js +6 -0
  17. package/lib/core/enhancement/index.js +5 -0
  18. package/lib/core/enhancement/langchain-enhancement.js +233 -0
  19. package/lib/core/enhancement/ml-enhancement.js +265 -0
  20. package/lib/core/enhancement/nextjs-enhancement.js +219 -0
  21. package/lib/core/enhancement/node-server-enhancement.js +178 -4
  22. package/lib/core/enhancement/react-enhancement.js +165 -4
  23. package/lib/core/enhancement/rust-tokio-enhancement.js +231 -0
  24. package/lib/core/enhancement/rust-web-enhancement.js +256 -0
  25. package/lib/core/enhancement/spring-enhancement.js +2 -0
  26. package/lib/core/enhancement/vue-enhancement.js +143 -2
  27. package/lib/external/ai/AiProvider.js +45 -6
  28. package/lib/external/mcp/handlers/bootstrap/skills.js +2 -0
  29. package/lib/external/mcp/handlers/bootstrap.js +33 -9
  30. package/lib/external/mcp/handlers/guard.js +42 -0
  31. package/lib/http/routes/candidates.js +7 -1
  32. package/lib/service/chat/ChatAgent.js +1 -0
  33. package/lib/service/chat/tools.js +5 -1
  34. package/lib/service/guard/ComplianceReporter.js +20 -7
  35. package/lib/service/guard/GuardCheckEngine.js +156 -5
  36. package/lib/service/guard/SourceFileCollector.js +15 -0
  37. package/package.json +28 -6
  38. package/skills/autosnippet-coldstart/SKILL.md +4 -2
  39. package/skills/autosnippet-concepts/SKILL.md +5 -3
  40. package/skills/autosnippet-reference-rust/SKILL.md +401 -0
  41. package/skills/autosnippet-structure/SKILL.md +1 -1
  42. package/templates/recipes-setup/README.md +2 -2
  43. package/templates/recipes-setup/_template.md +1 -1
  44. package/dashboard/dist/assets/index-ClkyPkDX.js +0 -133
  45. package/dashboard/dist/assets/index-t4QrJwv1.css +0 -1
@@ -0,0 +1,219 @@
1
+ /**
2
+ * Next.js 15 Enhancement Pack
3
+ * 条件: { languages: ['typescript', 'javascript'], frameworks: ['nextjs'] }
4
+ *
5
+ * 覆盖 Next.js 15 App Router 生态:
6
+ * - App Router 文件约定 (layout/page/loading/error/not-found/route)
7
+ * - Server Actions ("use server")
8
+ * - Metadata API (generateMetadata / export metadata)
9
+ * - Middleware (middleware.ts)
10
+ * - RSC 数据获取模式 (async Server Components / fetch cache)
11
+ * - Parallel Routes / Intercepting Routes
12
+ */
13
+
14
+ import { EnhancementPack } from './EnhancementPack.js';
15
+
16
+ class NextjsEnhancement extends EnhancementPack {
17
+ get id() {
18
+ return 'nextjs';
19
+ }
20
+ get displayName() {
21
+ return 'Next.js 15 App Router Enhancement';
22
+ }
23
+ get conditions() {
24
+ return { languages: ['typescript', 'javascript'], frameworks: ['nextjs'] };
25
+ }
26
+
27
+ getExtraDimensions() {
28
+ return [
29
+ {
30
+ id: 'nextjs-app-router-scan',
31
+ label: 'App Router 结构分析',
32
+ guide:
33
+ 'Next.js App Router 文件约定分析 — layout.tsx/page.tsx/loading.tsx/error.tsx/not-found.tsx 分布、Route Groups、Parallel Routes (@folder)、Intercepting Routes (..)、generateStaticParams 使用',
34
+ knowledgeTypes: ['architecture'],
35
+ skillWorthy: true,
36
+ dualOutput: true,
37
+ skillMeta: {
38
+ name: 'project-nextjs-app-router',
39
+ description:
40
+ 'Next.js App Router file conventions, route groups and parallel routes (auto-generated by enhancement)',
41
+ },
42
+ },
43
+ {
44
+ id: 'nextjs-server-actions-scan',
45
+ label: 'Server Actions 分析',
46
+ guide:
47
+ 'Server Actions 分析 — "use server" 函数分布、表单绑定 (action={})、useFormState/useFormStatus 配合、revalidatePath/revalidateTag 缓存策略',
48
+ knowledgeTypes: ['architecture', 'code-pattern'],
49
+ skillWorthy: true,
50
+ dualOutput: true,
51
+ skillMeta: {
52
+ name: 'project-nextjs-server-actions',
53
+ description:
54
+ 'Next.js Server Actions, form bindings and revalidation patterns (auto-generated by enhancement)',
55
+ },
56
+ },
57
+ {
58
+ id: 'nextjs-data-fetching-scan',
59
+ label: '数据获取模式分析',
60
+ guide:
61
+ 'Next.js 数据获取模式 — async Server Component 直接 fetch/DB 查询、fetch() cache/revalidate 选项、generateStaticParams、Streaming + Suspense 加载策略',
62
+ knowledgeTypes: ['code-pattern'],
63
+ skillWorthy: true,
64
+ dualOutput: true,
65
+ skillMeta: {
66
+ name: 'project-nextjs-data-fetching',
67
+ description:
68
+ 'Next.js data fetching — Server Component queries, fetch caching and streaming (auto-generated by enhancement)',
69
+ },
70
+ },
71
+ ];
72
+ }
73
+
74
+ getGuardRules() {
75
+ return [
76
+ {
77
+ ruleId: 'nextjs-no-client-in-server-action',
78
+ category: 'correctness',
79
+ dimension: 'file',
80
+ severity: 'error',
81
+ languages: ['typescript', 'javascript'],
82
+ pattern: /['"]use server['"]\s*;?\s*\n[\s\S]*?(?:useState|useEffect|useRef|useContext)\s*\(/,
83
+ message: '"use server" 文件/函数中不能使用 React Hooks — Server Actions 运行在服务端',
84
+ },
85
+ {
86
+ ruleId: 'nextjs-use-server-top-level',
87
+ category: 'correctness',
88
+ dimension: 'file',
89
+ severity: 'warning',
90
+ languages: ['typescript', 'javascript'],
91
+ pattern: /(?:function|const)\s+\w+[\s\S]*?\{[\s\S]*?['"]use server['"]/,
92
+ message:
93
+ '"use server" 指令应放在文件顶部(标记整个文件为 Server Actions)或 async 函数体开头',
94
+ },
95
+ {
96
+ ruleId: 'nextjs-no-window-in-server',
97
+ category: 'correctness',
98
+ dimension: 'file',
99
+ severity: 'error',
100
+ languages: ['typescript', 'javascript'],
101
+ pattern: /(?:^(?!.*['"]use client['"])[\s\S]*?)\b(?:window|document|localStorage|sessionStorage)\b/,
102
+ message: 'Server Component 中不能访问 window/document 等浏览器 API — 添加 "use client" 或检查运行环境',
103
+ },
104
+ {
105
+ ruleId: 'nextjs-metadata-with-use-client',
106
+ category: 'correctness',
107
+ dimension: 'file',
108
+ severity: 'error',
109
+ languages: ['typescript', 'javascript'],
110
+ pattern: /['"]use client['"][\s\S]*?export\s+(?:const\s+metadata|async\s+function\s+generateMetadata)/,
111
+ message: 'metadata / generateMetadata 只能在 Server Component 中导出 — 不能与 "use client" 共存',
112
+ },
113
+ {
114
+ ruleId: 'nextjs-fetch-no-store',
115
+ category: 'performance',
116
+ dimension: 'file',
117
+ severity: 'info',
118
+ languages: ['typescript', 'javascript'],
119
+ pattern: /fetch\s*\([^)]+\)\s*(?![\s\S]*?(?:cache|revalidate|next))/,
120
+ message: 'Next.js 15 默认不缓存 fetch,明确指定 { cache: "force-cache" } 或 { next: { revalidate: N } } 以启用缓存',
121
+ },
122
+ ];
123
+ }
124
+
125
+ detectPatterns(astSummary) {
126
+ const patterns = [];
127
+
128
+ // ── App Router file conventions ──
129
+ for (const m of astSummary.methods || []) {
130
+ if (!m.className && m.isExported) {
131
+ // Default export in page/layout files
132
+ if (m.name === 'default' || /^(?:Page|Layout|Loading|Error|NotFound)$/.test(m.name)) {
133
+ patterns.push({
134
+ type: 'nextjs-app-router-component',
135
+ methodName: m.name,
136
+ line: m.line,
137
+ confidence: 0.8,
138
+ });
139
+ }
140
+ // generateMetadata / generateStaticParams
141
+ if (m.name === 'generateMetadata' || m.name === 'generateStaticParams') {
142
+ patterns.push({
143
+ type: 'nextjs-metadata-generator',
144
+ methodName: m.name,
145
+ line: m.line,
146
+ confidence: 0.95,
147
+ });
148
+ }
149
+ }
150
+ }
151
+
152
+ // ── Server Actions (async functions with "use server") ──
153
+ for (const m of astSummary.methods || []) {
154
+ if (m.isAsync && !m.className) {
155
+ const nameLower = m.name?.toLowerCase() || '';
156
+ if (
157
+ nameLower.startsWith('create') ||
158
+ nameLower.startsWith('update') ||
159
+ nameLower.startsWith('delete') ||
160
+ nameLower.startsWith('submit') ||
161
+ nameLower.includes('action')
162
+ ) {
163
+ patterns.push({
164
+ type: 'nextjs-server-action',
165
+ methodName: m.name,
166
+ line: m.line,
167
+ confidence: 0.65,
168
+ });
169
+ }
170
+ }
171
+ }
172
+
173
+ // ── Route Handlers (GET/POST/PUT/DELETE/PATCH exports) ──
174
+ for (const m of astSummary.methods || []) {
175
+ if (m.isExported && !m.className && /^(?:GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)$/.test(m.name)) {
176
+ patterns.push({
177
+ type: 'nextjs-route-handler',
178
+ methodName: m.name,
179
+ line: m.line,
180
+ confidence: 0.95,
181
+ });
182
+ }
183
+ }
184
+
185
+ // ── Middleware ──
186
+ for (const m of astSummary.methods || []) {
187
+ if (m.isExported && m.name === 'middleware') {
188
+ patterns.push({
189
+ type: 'nextjs-middleware',
190
+ methodName: m.name,
191
+ line: m.line,
192
+ confidence: 0.9,
193
+ });
194
+ }
195
+ }
196
+
197
+ // ── Next.js specific imports ──
198
+ const nextImports = (astSummary.imports || []).filter(
199
+ (imp) =>
200
+ imp.includes('next/') ||
201
+ imp.includes('next/server') ||
202
+ imp.includes('next/navigation') ||
203
+ imp.includes('next/image') ||
204
+ imp.includes('next/link') ||
205
+ imp.includes('next/font')
206
+ );
207
+ if (nextImports.length > 0) {
208
+ patterns.push({
209
+ type: 'nextjs-framework-usage',
210
+ importCount: nextImports.length,
211
+ confidence: 0.9,
212
+ });
213
+ }
214
+
215
+ return patterns;
216
+ }
217
+ }
218
+
219
+ export const pack = new NextjsEnhancement();
@@ -1,6 +1,12 @@
1
1
  /**
2
2
  * Node.js Server Enhancement Pack
3
3
  * 条件: { languages: ['typescript', 'javascript'], frameworks: ['node-server', 'nestjs'] }
4
+ *
5
+ * 覆盖 Node.js 后端生态:
6
+ * - Express / Koa / Hono 中间件链
7
+ * - Fastify 插件体系 + Schema Validation
8
+ * - NestJS Module / DI / Guard / Pipe / Interceptor
9
+ * - 错误处理与日志中间件
4
10
  */
5
11
 
6
12
  import { EnhancementPack } from './EnhancementPack.js';
@@ -10,7 +16,7 @@ class NodeServerEnhancement extends EnhancementPack {
10
16
  return 'node-server';
11
17
  }
12
18
  get displayName() {
13
- return 'Node.js Server (Express/NestJS) Enhancement';
19
+ return 'Node.js Server (Express/Fastify/NestJS) Enhancement';
14
20
  }
15
21
  get conditions() {
16
22
  return { languages: ['typescript', 'javascript'], frameworks: ['node-server', 'nestjs'] };
@@ -21,7 +27,7 @@ class NodeServerEnhancement extends EnhancementPack {
21
27
  {
22
28
  id: 'middleware-analysis',
23
29
  label: '中间件链分析',
24
- guide: 'Middleware 链路分析、错误处理中间件、路由守卫、认证/鉴权中间件',
30
+ guide: 'Middleware 链路分析、错误处理中间件、路由守卫、认证/鉴权中间件、中间件执行顺序',
25
31
  knowledgeTypes: ['architecture', 'code-pattern'],
26
32
  skillWorthy: true,
27
33
  dualOutput: true,
@@ -31,6 +37,34 @@ class NodeServerEnhancement extends EnhancementPack {
31
37
  'Node.js middleware chain and error handling patterns (auto-generated by enhancement)',
32
38
  },
33
39
  },
40
+ {
41
+ id: 'nestjs-module-scan',
42
+ label: 'NestJS 模块 DI 分析',
43
+ guide:
44
+ 'NestJS 模块拓扑分析 — @Module imports/exports/providers/controllers 依赖图、Dynamic Module (forRoot/forRootAsync)、Custom Provider (useClass/useFactory/useValue)、Scope (DEFAULT/REQUEST/TRANSIENT)',
45
+ knowledgeTypes: ['architecture'],
46
+ skillWorthy: true,
47
+ dualOutput: true,
48
+ skillMeta: {
49
+ name: 'project-nestjs-modules',
50
+ description:
51
+ 'NestJS module dependency topology, DI providers and scopes (auto-generated by enhancement)',
52
+ },
53
+ },
54
+ {
55
+ id: 'node-validation-scan',
56
+ label: '请求验证模式分析',
57
+ guide:
58
+ '请求验证模式分析 — Zod/Joi/class-validator schema 定义、Fastify JSON Schema、NestJS ValidationPipe、DTO 类与验证装饰器',
59
+ knowledgeTypes: ['code-pattern', 'code-standard'],
60
+ skillWorthy: true,
61
+ dualOutput: true,
62
+ skillMeta: {
63
+ name: 'project-node-validation',
64
+ description:
65
+ 'Node.js request validation patterns — Zod/Joi/class-validator schemas (auto-generated by enhancement)',
66
+ },
67
+ },
34
68
  ];
35
69
  }
36
70
 
@@ -38,6 +72,8 @@ class NodeServerEnhancement extends EnhancementPack {
38
72
  return [
39
73
  {
40
74
  ruleId: 'node-no-sync-io',
75
+ category: 'performance',
76
+ dimension: 'file',
41
77
  severity: 'warning',
42
78
  languages: ['typescript', 'javascript'],
43
79
  pattern:
@@ -46,23 +82,63 @@ class NodeServerEnhancement extends EnhancementPack {
46
82
  },
47
83
  {
48
84
  ruleId: 'node-error-handler',
85
+ category: 'correctness',
86
+ dimension: 'file',
49
87
  severity: 'info',
50
88
  languages: ['typescript', 'javascript'],
51
89
  pattern: /app\.use\(\s*\(\s*err\s*,\s*req\s*,\s*res\s*,\s*next\s*\)/,
52
90
  message: 'Express 应用需要注册 4 参数错误处理中间件',
53
91
  },
92
+ {
93
+ ruleId: 'node-no-unhandled-promise',
94
+ category: 'correctness',
95
+ dimension: 'file',
96
+ severity: 'warning',
97
+ languages: ['typescript', 'javascript'],
98
+ pattern: /\.then\s*\([^)]*\)\s*(?!\.catch)/,
99
+ message: 'Promise 链应包含 .catch() 处理或使用 async/await + try/catch — 未处理的 rejection 会导致进程崩溃',
100
+ },
101
+ {
102
+ ruleId: 'nestjs-circular-dependency',
103
+ category: 'correctness',
104
+ dimension: 'file',
105
+ severity: 'warning',
106
+ languages: ['typescript', 'javascript'],
107
+ pattern: /forwardRef\s*\(\s*\(\)\s*=>/,
108
+ message: 'forwardRef 说明存在循环依赖 — 考虑重构模块结构或使用事件驱动解耦',
109
+ },
110
+ {
111
+ ruleId: 'nestjs-no-any-response',
112
+ category: 'style',
113
+ dimension: 'file',
114
+ severity: 'info',
115
+ languages: ['typescript', 'javascript'],
116
+ pattern: /@(?:Get|Post|Put|Delete|Patch)\s*\([^)]*\)\s*\n\s*(?:async\s+)?\w+\([^)]*\)\s*(?::\s*any)?/,
117
+ message: 'NestJS controller 方法建议声明返回类型 DTO — 便于 Swagger 文档生成与类型安全',
118
+ },
119
+ {
120
+ ruleId: 'node-exposed-secrets',
121
+ category: 'safety',
122
+ dimension: 'file',
123
+ severity: 'error',
124
+ languages: ['typescript', 'javascript'],
125
+ pattern: /(?:password|secret|api[_-]?key|token)\s*[:=]\s*['"][^'"]+['"]/i,
126
+ message: '硬编码机密信息 — 使用环境变量或 Secret Manager',
127
+ },
54
128
  ];
55
129
  }
56
130
 
57
131
  detectPatterns(astSummary) {
58
132
  const patterns = [];
133
+
134
+ // ── Express/Koa middleware ((req, res, next) signature) ──
59
135
  for (const m of astSummary.methods || []) {
60
- // Middleware: (req, res, next) => 签名
61
136
  if (!m.className && m.paramCount === 3) {
62
137
  patterns.push({ type: 'middleware', methodName: m.name, line: m.line, confidence: 0.6 });
63
138
  }
64
139
  }
65
- // NestJS decorators
140
+
141
+ // ── NestJS Controllers ──
66
142
  for (const cls of astSummary.classes || []) {
67
143
  if (cls.decorators?.some((d) => /@Controller/.test(d))) {
68
144
  patterns.push({
@@ -80,7 +156,105 @@ class NodeServerEnhancement extends EnhancementPack {
80
156
  confidence: 0.95,
81
157
  });
82
158
  }
159
+ if (cls.decorators?.some((d) => /@Module/.test(d))) {
160
+ patterns.push({
161
+ type: 'nestjs-module',
162
+ className: cls.name,
163
+ line: cls.line,
164
+ confidence: 0.95,
165
+ });
166
+ }
83
167
  }
168
+
169
+ // ── NestJS Guards / Pipes / Interceptors / Filters ──
170
+ for (const cls of astSummary.classes || []) {
171
+ const implemented = cls.interfaces || [];
172
+ if (implemented.includes('CanActivate')) {
173
+ patterns.push({
174
+ type: 'nestjs-guard',
175
+ className: cls.name,
176
+ line: cls.line,
177
+ confidence: 0.95,
178
+ });
179
+ }
180
+ if (implemented.includes('PipeTransform')) {
181
+ patterns.push({
182
+ type: 'nestjs-pipe',
183
+ className: cls.name,
184
+ line: cls.line,
185
+ confidence: 0.95,
186
+ });
187
+ }
188
+ if (implemented.includes('NestInterceptor')) {
189
+ patterns.push({
190
+ type: 'nestjs-interceptor',
191
+ className: cls.name,
192
+ line: cls.line,
193
+ confidence: 0.95,
194
+ });
195
+ }
196
+ if (implemented.includes('ExceptionFilter')) {
197
+ patterns.push({
198
+ type: 'nestjs-exception-filter',
199
+ className: cls.name,
200
+ line: cls.line,
201
+ confidence: 0.95,
202
+ });
203
+ }
204
+ }
205
+
206
+ // ── Fastify plugin pattern (fp(async function)) ──
207
+ for (const m of astSummary.methods || []) {
208
+ if (!m.className && m.isExported && m.isAsync) {
209
+ const nameLower = m.name?.toLowerCase() || '';
210
+ if (nameLower.includes('plugin') || nameLower.includes('register')) {
211
+ patterns.push({
212
+ type: 'fastify-plugin',
213
+ methodName: m.name,
214
+ line: m.line,
215
+ confidence: 0.7,
216
+ });
217
+ }
218
+ }
219
+ }
220
+
221
+ // ── Validation/DTO classes ──
222
+ for (const cls of astSummary.classes || []) {
223
+ const nameLower = cls.name?.toLowerCase() || '';
224
+ if (
225
+ nameLower.endsWith('dto') ||
226
+ nameLower.endsWith('schema') ||
227
+ nameLower.endsWith('validator')
228
+ ) {
229
+ patterns.push({
230
+ type: 'node-dto',
231
+ className: cls.name,
232
+ line: cls.line,
233
+ confidence: 0.8,
234
+ });
235
+ }
236
+ }
237
+
238
+ // ── Node framework imports ──
239
+ const serverImports = (astSummary.imports || []).filter(
240
+ (imp) =>
241
+ imp.includes('express') ||
242
+ imp.includes('fastify') ||
243
+ imp.includes('@nestjs') ||
244
+ imp.includes('koa') ||
245
+ imp.includes('hono') ||
246
+ imp.includes('zod') ||
247
+ imp.includes('class-validator') ||
248
+ imp.includes('joi')
249
+ );
250
+ if (serverImports.length > 0) {
251
+ patterns.push({
252
+ type: 'node-server-framework-usage',
253
+ importCount: serverImports.length,
254
+ confidence: 0.85,
255
+ });
256
+ }
257
+
84
258
  return patterns;
85
259
  }
86
260
  }
@@ -1,6 +1,13 @@
1
1
  /**
2
2
  * React Enhancement Pack
3
3
  * 条件: { languages: ['typescript', 'javascript'], frameworks: ['react', 'nextjs'] }
4
+ *
5
+ * 覆盖 React 19 生态:
6
+ * - Server / Client Components (RSC)
7
+ * - Custom Hooks + Hook 组合模式
8
+ * - 组件结构约定
9
+ * - 状态管理模式 (Context / Zustand / Jotai)
10
+ * - Suspense / ErrorBoundary
4
11
  */
5
12
 
6
13
  import { EnhancementPack } from './EnhancementPack.js';
@@ -10,7 +17,7 @@ class ReactEnhancement extends EnhancementPack {
10
17
  return 'react';
11
18
  }
12
19
  get displayName() {
13
- return 'React / Next.js Enhancement';
20
+ return 'React 19 Enhancement';
14
21
  }
15
22
  get conditions() {
16
23
  return { languages: ['typescript', 'javascript'], frameworks: ['react', 'nextjs'] };
@@ -22,7 +29,7 @@ class ReactEnhancement extends EnhancementPack {
22
29
  id: 'hook-pattern-scan',
23
30
  label: '自定義 Hook 分析',
24
31
  guide:
25
- '自定义 Hook 提取(useXxx 函数 + 内部状态/副作用分析)、Hook 组合模式、Hook 依赖关系',
32
+ '自定义 Hook 提取(useXxx 函数 + 内部状态/副作用分析)、Hook 组合模式、Hook 依赖关系、useCallback/useMemo 使用合理性',
26
33
  knowledgeTypes: ['code-pattern'],
27
34
  skillWorthy: true,
28
35
  dualOutput: true,
@@ -34,7 +41,7 @@ class ReactEnhancement extends EnhancementPack {
34
41
  {
35
42
  id: 'component-structure-scan',
36
43
  label: '组件结构约定',
37
- guide: '组件目录结构约定(文件组织、barrel export、props/state 命名规范)',
44
+ guide: '组件目录结构约定(文件组织、barrel export、props/state 命名规范、forwardRef 使用、组件拆分粒度)',
38
45
  knowledgeTypes: ['code-standard', 'architecture'],
39
46
  skillWorthy: true,
40
47
  dualOutput: true,
@@ -43,6 +50,34 @@ class ReactEnhancement extends EnhancementPack {
43
50
  description: 'React component structure conventions (auto-generated by enhancement)',
44
51
  },
45
52
  },
53
+ {
54
+ id: 'rsc-boundary-scan',
55
+ label: 'Server/Client 边界分析',
56
+ guide:
57
+ 'React Server Components 分析 — "use client" / "use server" 指令分布、Server → Client 数据传递边界、Serializable props 约束、async Server Component 模式',
58
+ knowledgeTypes: ['architecture', 'code-pattern'],
59
+ skillWorthy: true,
60
+ dualOutput: true,
61
+ skillMeta: {
62
+ name: 'project-react-rsc',
63
+ description:
64
+ 'React Server Component boundaries, directives and data flow (auto-generated by enhancement)',
65
+ },
66
+ },
67
+ {
68
+ id: 'state-management-scan',
69
+ label: '状态管理分析',
70
+ guide:
71
+ '状态管理模式分析 — Context Provider 层级、Zustand/Jotai/Redux store 结构、useReducer 有限状态机、状态提升 vs 组合',
72
+ knowledgeTypes: ['architecture', 'code-pattern'],
73
+ skillWorthy: true,
74
+ dualOutput: true,
75
+ skillMeta: {
76
+ name: 'project-react-state',
77
+ description:
78
+ 'React state management topology — Context/Zustand/Redux patterns (auto-generated by enhancement)',
79
+ },
80
+ },
46
81
  ];
47
82
  }
48
83
 
@@ -50,6 +85,8 @@ class ReactEnhancement extends EnhancementPack {
50
85
  return [
51
86
  {
52
87
  ruleId: 'react-no-direct-dom',
88
+ category: 'correctness',
89
+ dimension: 'file',
53
90
  severity: 'warning',
54
91
  languages: ['typescript', 'javascript'],
55
92
  pattern: /document\.(getElementById|querySelector|getElementsBy)/,
@@ -57,28 +94,152 @@ class ReactEnhancement extends EnhancementPack {
57
94
  },
58
95
  {
59
96
  ruleId: 'react-no-index-key',
97
+ category: 'correctness',
98
+ dimension: 'file',
60
99
  severity: 'warning',
61
100
  languages: ['typescript', 'javascript'],
62
101
  pattern:
63
102
  /\.map\s*\([^)]*,\s*(?:index|i|idx)\s*\)\s*=>\s*[\s\S]*?key\s*=\s*\{?\s*(?:index|i|idx)/,
64
103
  message: '避免使用 index 作为 key,使用稳定的唯一标识符',
65
104
  },
105
+ {
106
+ ruleId: 'react-hooks-conditional',
107
+ category: 'correctness',
108
+ dimension: 'file',
109
+ severity: 'error',
110
+ languages: ['typescript', 'javascript'],
111
+ pattern: /if\s*\([^)]*\)\s*\{[^}]*\buse[A-Z]\w*\s*\(/,
112
+ message: 'Hook 不能在条件语句中调用 — 违反 Rules of Hooks(Hook 必须在组件顶层调用)',
113
+ },
114
+ {
115
+ ruleId: 'react-useeffect-missing-cleanup',
116
+ category: 'correctness',
117
+ dimension: 'file',
118
+ severity: 'info',
119
+ languages: ['typescript', 'javascript'],
120
+ pattern: /useEffect\s*\(\s*\(\)\s*=>\s*\{[^}]*(?:addEventListener|setInterval|setTimeout|subscribe)[^}]*\}\s*,/,
121
+ message: 'useEffect 中注册了事件/订阅/定时器但可能缺少清理函数,会导致内存泄漏',
122
+ },
123
+ {
124
+ ruleId: 'react-no-setState-in-render',
125
+ category: 'correctness',
126
+ dimension: 'file',
127
+ severity: 'error',
128
+ languages: ['typescript', 'javascript'],
129
+ pattern: /(?:^|\n)\s*(?:const|let)\s+\[.*?,\s*set\w+\]\s*=\s*useState[\s\S]*?\n\s*set\w+\(/m,
130
+ message: '避免在渲染阶段直接调用 setState — 会导致无限重渲染',
131
+ },
132
+ {
133
+ ruleId: 'react-exhaustive-deps',
134
+ category: 'correctness',
135
+ dimension: 'file',
136
+ severity: 'warning',
137
+ languages: ['typescript', 'javascript'],
138
+ pattern: /\/\/\s*eslint-disable.*exhaustive-deps/,
139
+ message: '不要禁用 exhaustive-deps 规则,修复依赖数组以避免 stale closure',
140
+ },
141
+ {
142
+ ruleId: 'react-use-client-server-mixing',
143
+ category: 'correctness',
144
+ dimension: 'file',
145
+ severity: 'warning',
146
+ languages: ['typescript', 'javascript'],
147
+ pattern: /['"]use client['"]\s*;?\s*\n[\s\S]*?['"]use server['"]/,
148
+ message: '同一文件不能同时包含 "use client" 和 "use server" 指令',
149
+ },
66
150
  ];
67
151
  }
68
152
 
69
153
  detectPatterns(astSummary) {
70
154
  const patterns = [];
155
+
156
+ // ── Custom Hooks ──
71
157
  for (const m of astSummary.methods || []) {
72
158
  if (m.name && /^use[A-Z]/.test(m.name) && !m.className) {
73
159
  patterns.push({ type: 'custom-hook', methodName: m.name, line: m.line, confidence: 0.9 });
74
160
  }
75
161
  }
76
- // HOC: function withXxx(Component)
162
+
163
+ // ── HOC: function withXxx(Component) ──
77
164
  for (const m of astSummary.methods || []) {
78
165
  if (m.name && /^with[A-Z]/.test(m.name) && !m.className) {
79
166
  patterns.push({ type: 'hoc', methodName: m.name, line: m.line, confidence: 0.8 });
80
167
  }
81
168
  }
169
+
170
+ // ── Context Providers ──
171
+ for (const cls of astSummary.classes || []) {
172
+ const nameLower = cls.name?.toLowerCase() || '';
173
+ if (nameLower.includes('provider') || nameLower.includes('context')) {
174
+ patterns.push({
175
+ type: 'react-context-provider',
176
+ className: cls.name,
177
+ line: cls.line,
178
+ confidence: 0.8,
179
+ });
180
+ }
181
+ }
182
+
183
+ // ── forwardRef components ──
184
+ for (const m of astSummary.methods || []) {
185
+ if (m.name && !m.className) {
186
+ // 导出的组件函数(大写开头)
187
+ if (/^[A-Z]/.test(m.name)) {
188
+ patterns.push({
189
+ type: 'react-component',
190
+ methodName: m.name,
191
+ line: m.line,
192
+ confidence: 0.7,
193
+ });
194
+ }
195
+ }
196
+ }
197
+
198
+ // ── Error Boundary classes ──
199
+ for (const cls of astSummary.classes || []) {
200
+ if (cls.superclass && /Component/.test(cls.superclass)) {
201
+ const methods = cls.methods || [];
202
+ if (methods.includes('componentDidCatch') || methods.includes('getDerivedStateFromError')) {
203
+ patterns.push({
204
+ type: 'react-error-boundary',
205
+ className: cls.name,
206
+ line: cls.line,
207
+ confidence: 0.95,
208
+ });
209
+ }
210
+ }
211
+ }
212
+
213
+ // ── Zustand/Redux stores ──
214
+ for (const m of astSummary.methods || []) {
215
+ if (m.name && /^use\w*Store$/.test(m.name) && !m.className) {
216
+ patterns.push({
217
+ type: 'react-store',
218
+ methodName: m.name,
219
+ line: m.line,
220
+ confidence: 0.85,
221
+ });
222
+ }
223
+ }
224
+
225
+ // ── React imports ──
226
+ const reactImports = (astSummary.imports || []).filter(
227
+ (imp) =>
228
+ imp.includes('react') ||
229
+ imp.includes('zustand') ||
230
+ imp.includes('jotai') ||
231
+ imp.includes('@reduxjs') ||
232
+ imp.includes('react-query') ||
233
+ imp.includes('@tanstack')
234
+ );
235
+ if (reactImports.length > 0) {
236
+ patterns.push({
237
+ type: 'react-ecosystem-usage',
238
+ importCount: reactImports.length,
239
+ confidence: 0.85,
240
+ });
241
+ }
242
+
82
243
  return patterns;
83
244
  }
84
245
  }