flutter-pro-max-cli 1.0.2 → 2.0.0

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 (89) hide show
  1. package/README.md +97 -16
  2. package/assets/data/flutter-performance.csv +36 -0
  3. package/assets/data/mobile-accessibility.csv +36 -0
  4. package/assets/data/ui-reasoning.csv +36 -0
  5. package/assets/{.claude/skills/flutter-pro-max/scripts → scripts}/core.py +20 -3
  6. package/assets/{.claude/skills/flutter-pro-max/scripts → scripts}/search.py +1 -1
  7. package/assets/templates/base/quick-reference.md +41 -0
  8. package/assets/templates/base/skill-content.md +179 -0
  9. package/assets/templates/platforms/agent.json +21 -0
  10. package/assets/templates/platforms/claude.json +21 -0
  11. package/assets/templates/platforms/codebuddy.json +18 -0
  12. package/assets/templates/platforms/codex.json +21 -0
  13. package/assets/templates/platforms/continue.json +21 -0
  14. package/assets/templates/platforms/copilot.json +18 -0
  15. package/assets/templates/platforms/cursor.json +18 -0
  16. package/assets/templates/platforms/gemini.json +21 -0
  17. package/assets/templates/platforms/kiro.json +18 -0
  18. package/assets/templates/platforms/opencode.json +21 -0
  19. package/assets/templates/platforms/qoder.json +18 -0
  20. package/assets/templates/platforms/roocode.json +18 -0
  21. package/assets/templates/platforms/trae.json +21 -0
  22. package/assets/templates/platforms/windsurf.json +18 -0
  23. package/dist/commands/init.js +13 -13
  24. package/dist/commands/update.d.ts +6 -0
  25. package/dist/commands/update.js +27 -0
  26. package/dist/commands/versions.d.ts +1 -0
  27. package/dist/commands/versions.js +36 -0
  28. package/dist/index.js +27 -1
  29. package/dist/types/index.d.ts +20 -1
  30. package/dist/types/index.js +4 -1
  31. package/dist/utils/detect.js +11 -1
  32. package/dist/utils/extract.d.ts +5 -0
  33. package/dist/utils/github.d.ts +11 -0
  34. package/dist/utils/github.js +81 -0
  35. package/dist/utils/template.d.ts +25 -0
  36. package/dist/utils/template.js +194 -0
  37. package/package.json +8 -4
  38. package/assets/.agent/workflows/flutter-pro-max.md +0 -221
  39. package/assets/.agent/workflows/scripts/core.py +0 -345
  40. package/assets/.agent/workflows/scripts/search.py +0 -106
  41. package/assets/.claude/skills/flutter-pro-max/SKILL.md +0 -339
  42. package/assets/.codebuddy/commands/flutter-pro-max.md +0 -221
  43. package/assets/.codebuddy/commands/scripts/core.py +0 -345
  44. package/assets/.codebuddy/commands/scripts/search.py +0 -106
  45. package/assets/.codex/skills/flutter-pro-max/SKILL.md +0 -221
  46. package/assets/.codex/skills/flutter-pro-max/scripts/core.py +0 -345
  47. package/assets/.codex/skills/flutter-pro-max/scripts/search.py +0 -106
  48. package/assets/.cursor/commands/flutter-pro-max.md +0 -221
  49. package/assets/.cursor/commands/scripts/core.py +0 -345
  50. package/assets/.cursor/commands/scripts/search.py +0 -106
  51. package/assets/.gemini/skills/flutter-pro-max/SKILL.md +0 -221
  52. package/assets/.gemini/skills/flutter-pro-max/scripts/core.py +0 -345
  53. package/assets/.gemini/skills/flutter-pro-max/scripts/search.py +0 -106
  54. package/assets/.github/prompts/flutter-pro-max.prompt.md +0 -221
  55. package/assets/.github/prompts/scripts/core.py +0 -345
  56. package/assets/.github/prompts/scripts/search.py +0 -106
  57. package/assets/.kiro/steering/flutter-pro-max.md +0 -220
  58. package/assets/.kiro/steering/scripts/core.py +0 -345
  59. package/assets/.kiro/steering/scripts/search.py +0 -106
  60. package/assets/.qoder/rules/flutter-pro-max.md +0 -220
  61. package/assets/.qoder/rules/scripts/core.py +0 -345
  62. package/assets/.qoder/rules/scripts/search.py +0 -106
  63. package/assets/.roo/commands/flutter-pro-max.md +0 -220
  64. package/assets/.roo/commands/scripts/core.py +0 -345
  65. package/assets/.roo/commands/scripts/search.py +0 -106
  66. package/assets/.shared/flutter-pro-max/SKILL.md +0 -221
  67. package/assets/.shared/flutter-pro-max/scripts/core.py +0 -341
  68. package/assets/.shared/flutter-pro-max/scripts/search.py +0 -106
  69. package/assets/.trae/skills/flutter-pro-max/SKILL.md +0 -221
  70. package/assets/.trae/skills/flutter-pro-max/scripts/core.py +0 -345
  71. package/assets/.trae/skills/flutter-pro-max/scripts/search.py +0 -106
  72. package/assets/.windsurf/workflows/flutter-pro-max.md +0 -221
  73. package/assets/.windsurf/workflows/scripts/core.py +0 -345
  74. package/assets/.windsurf/workflows/scripts/search.py +0 -106
  75. package/dist/utils/extract.js +0 -83
  76. /package/assets/{.shared/data → data}/architect.csv +0 -0
  77. /package/assets/{.shared/data → data}/charts.csv +0 -0
  78. /package/assets/{.shared/data → data}/colors.csv +0 -0
  79. /package/assets/{.shared/data → data}/icons.csv +0 -0
  80. /package/assets/{.shared/data → data}/landing.csv +0 -0
  81. /package/assets/{.shared/data → data}/name_convention.csv +0 -0
  82. /package/assets/{.shared/data → data}/package.csv +0 -0
  83. /package/assets/{.shared/data → data}/patterns.csv +0 -0
  84. /package/assets/{.shared/data → data}/products.csv +0 -0
  85. /package/assets/{.shared/data → data}/prompts.csv +0 -0
  86. /package/assets/{.shared/data → data}/styles.csv +0 -0
  87. /package/assets/{.shared/data → data}/typography.csv +0 -0
  88. /package/assets/{.shared/data → data}/ux-guidelines.csv +0 -0
  89. /package/assets/{.shared/data → data}/widget.csv +0 -0
@@ -1,345 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """
4
- Flutter Pro Max Core - BM25 search engine for Flutter knowledge base
5
- Zero dependencies - self-contained BM25 implementation
6
- """
7
-
8
- import csv
9
- import re
10
- from pathlib import Path
11
- from math import log
12
- from collections import defaultdict
13
-
14
- # ============ CONFIGURATION ============
15
- def _get_data_dir():
16
- """Auto-detect data directory based on script location"""
17
- script_dir = Path(__file__).parent
18
- possible_paths = [
19
- # When running from root/scripts/
20
- script_dir.parent / ".shared" / "data",
21
- # When running from .shared/flutter-pro-max/scripts/
22
- script_dir.parent.parent / "data",
23
- # When running from .agent/workflows/scripts/ (nested 3 levels deep)
24
- script_dir.parent.parent.parent / ".shared" / "data",
25
- # When running from .claude/skills/flutter-pro-max/scripts/ (nested 4 levels deep)
26
- script_dir.parent.parent.parent.parent / ".shared" / "data",
27
- # Fallback: cwd
28
- Path.cwd() / ".shared" / "data",
29
- ]
30
- for p in possible_paths:
31
- if p.exists():
32
- return p.resolve()
33
- return possible_paths[0] # Default to first option
34
-
35
- DATA_DIR = _get_data_dir()
36
- MAX_RESULTS = 5
37
-
38
- # Domain configuration: file, search columns, output columns
39
- CSV_CONFIG = {
40
- "widget": {
41
- "file": "widget.csv",
42
- "search_cols": ["Widget Name", "Category", "Description", "Key Properties", "Usage Context & Pro-Tips"],
43
- "output_cols": ["Widget Name", "Category", "Description", "Key Properties", "Usage Context & Pro-Tips"]
44
- },
45
- "package": {
46
- "file": "package.csv",
47
- "search_cols": ["pkg_name", "category", "description", "best_practice_snippet", "pro_tip", "alternatives"],
48
- "output_cols": ["pkg_name", "category", "description", "best_practice_snippet", "pro_tip", "alternatives"]
49
- },
50
- "pattern": {
51
- "file": "patterns.csv",
52
- "search_cols": ["pattern_name", "category", "problem_tags", "description", "key_widgets", "code_snippet", "anti_pattern"],
53
- "output_cols": ["pattern_name", "category", "problem_tags", "description", "key_widgets", "code_snippet", "anti_pattern"]
54
- },
55
- "architect": {
56
- "file": "architect.csv",
57
- "search_cols": ["path_pattern", "layer", "responsibility_description", "allowed_dependencies", "tech_stack_note"],
58
- "output_cols": ["path_pattern", "layer", "responsibility_description", "allowed_dependencies", "tech_stack_note"]
59
- },
60
- "chart": {
61
- "file": "charts.csv",
62
- "search_cols": ["Data Type", "Keywords", "Best Chart Type", "Secondary Options", "Accessibility Notes"],
63
- "output_cols": ["Data Type", "Keywords", "Best Chart Type", "Secondary Options", "Color Guidance", "Accessibility Notes", "Library Recommendation"]
64
- },
65
- "color": {
66
- "file": "colors.csv",
67
- "search_cols": ["Product Type", "Keywords", "Notes"],
68
- "output_cols": ["Product Type", "Keywords", "Primary (Hex)", "Secondary (Hex)", "CTA (Hex)", "Notes"]
69
- },
70
- "typography": {
71
- "file": "typography.csv",
72
- "search_cols": ["Font Pairing Name", "Category", "Mood/Style Keywords", "Best For", "Heading Font", "Body Font"],
73
- "output_cols": ["Font Pairing Name", "Category", "Heading Font", "Body Font", "Mood/Style Keywords", "Best For", "Google Fonts URL", "Notes"]
74
- },
75
- "style": {
76
- "file": "styles.csv",
77
- "search_cols": ["Style Category", "Type", "Keywords", "Best For"],
78
- "output_cols": ["Style Category", "Type", "Keywords", "Primary Colors", "Effects & Animation", "Best For", "Do Not Use For"]
79
- },
80
- "ux": {
81
- "file": "ux-guidelines.csv",
82
- "search_cols": ["Category", "Issue", "Platform", "Description", "Do", "Don't"],
83
- "output_cols": ["Category", "Issue", "Platform", "Description", "Do", "Don't"]
84
- },
85
- "icon": {
86
- "file": "icons.csv",
87
- "search_cols": ["Category", "Icon Name", "Keywords", "Best For"],
88
- "output_cols": ["Category", "Icon Name", "Keywords", "Library", "Import Code", "Usage", "Best For"]
89
- },
90
- "landing": {
91
- "file": "landing.csv",
92
- "search_cols": ["Pattern Name", "Keywords", "Section Order", "Conversion Optimization"],
93
- "output_cols": ["Pattern Name", "Keywords", "Section Order", "Primary CTA Placement", "Color Strategy", "Conversion Optimization"]
94
- },
95
- "naming": {
96
- "file": "name_convention.csv",
97
- "search_cols": ["Layer", "File Template", "Class Template", "Example File", "Example Class", "Notes"],
98
- "output_cols": ["Layer", "File Template", "Class Template", "Example File", "Example Class", "Notes"]
99
- },
100
- "product": {
101
- "file": "products.csv",
102
- "search_cols": ["Product Type", "Keywords", "Primary Style Recommendation"],
103
- "output_cols": ["Product Type", "Keywords", "Primary Style Recommendation", "Secondary Styles", "Color Palette Focus"]
104
- },
105
- "prompt": {
106
- "file": "prompts.csv",
107
- "search_cols": ["Style Category", "AI Prompt Keywords (Copy-Paste Ready)", "CSS/Technical Keywords"],
108
- "output_cols": ["Style Category", "AI Prompt Keywords (Copy-Paste Ready)", "CSS/Technical Keywords", "Implementation Checklist"]
109
- }
110
- }
111
-
112
- # Stack exclusion mapping for filtering conflicting packages
113
- STACK_EXCLUSIONS = {
114
- "riverpod": ["bloc", "flutter_bloc", "provider", "hydrated_bloc"],
115
- "bloc": ["riverpod", "flutter_riverpod", "provider"],
116
- "provider": ["riverpod", "flutter_riverpod", "bloc", "flutter_bloc"],
117
- }
118
-
119
- AVAILABLE_DOMAINS = list(CSV_CONFIG.keys())
120
- AVAILABLE_STACKS = list(STACK_EXCLUSIONS.keys())
121
-
122
-
123
- # ============ BM25 IMPLEMENTATION ============
124
- class BM25:
125
- """BM25 ranking algorithm for text search - zero dependencies"""
126
-
127
- def __init__(self, k1=1.5, b=0.75):
128
- self.k1 = k1
129
- self.b = b
130
- self.corpus = []
131
- self.doc_lengths = []
132
- self.avgdl = 0
133
- self.idf = {}
134
- self.doc_freqs = defaultdict(int)
135
- self.N = 0
136
-
137
- def tokenize(self, text):
138
- """Lowercase, split, remove punctuation, filter short words"""
139
- text = re.sub(r'[^\w\s]', ' ', str(text).lower())
140
- return [w for w in text.split() if len(w) > 1]
141
-
142
- def fit(self, documents):
143
- """Build BM25 index from documents"""
144
- self.corpus = [self.tokenize(doc) for doc in documents]
145
- self.N = len(self.corpus)
146
- if self.N == 0:
147
- return
148
- self.doc_lengths = [len(doc) for doc in self.corpus]
149
- self.avgdl = sum(self.doc_lengths) / self.N
150
-
151
- for doc in self.corpus:
152
- seen = set()
153
- for word in doc:
154
- if word not in seen:
155
- self.doc_freqs[word] += 1
156
- seen.add(word)
157
-
158
- for word, freq in self.doc_freqs.items():
159
- self.idf[word] = log((self.N - freq + 0.5) / (freq + 0.5) + 1)
160
-
161
- def score(self, query):
162
- """Score all documents against query"""
163
- query_tokens = self.tokenize(query)
164
- scores = []
165
-
166
- for idx, doc in enumerate(self.corpus):
167
- score = 0
168
- doc_len = self.doc_lengths[idx]
169
- term_freqs = defaultdict(int)
170
- for word in doc:
171
- term_freqs[word] += 1
172
-
173
- for token in query_tokens:
174
- if token in self.idf:
175
- tf = term_freqs[token]
176
- idf = self.idf[token]
177
- numerator = tf * (self.k1 + 1)
178
- denominator = tf + self.k1 * (1 - self.b + self.b * doc_len / self.avgdl)
179
- score += idf * numerator / denominator
180
-
181
- scores.append((idx, score))
182
-
183
- return sorted(scores, key=lambda x: x[1], reverse=True)
184
-
185
-
186
- # ============ HELPER FUNCTIONS ============
187
- def _load_csv(filepath):
188
- """Load CSV and return list of dicts"""
189
- with open(filepath, 'r', encoding='utf-8') as f:
190
- return list(csv.DictReader(f))
191
-
192
-
193
- def _search_csv(filepath, search_cols, output_cols, query, max_results, boost_col=None, boost_query=None):
194
- """Core search function using BM25 with optional boosting"""
195
- if not filepath.exists():
196
- return []
197
-
198
- data = _load_csv(filepath)
199
-
200
- # Build documents from search columns
201
- documents = [" ".join(str(row.get(col, "")) for col in search_cols) for row in data]
202
-
203
- # BM25 search
204
- bm25 = BM25()
205
- bm25.fit(documents)
206
- ranked = bm25.score(query)
207
-
208
- # Apply boosting if specified (widget name match, etc.)
209
- if boost_col and boost_query:
210
- boost_query_lower = boost_query.lower()
211
- boosted = []
212
- for idx, score in ranked:
213
- if score > 0:
214
- boost_value = str(data[idx].get(boost_col, "")).lower()
215
- if boost_value in boost_query_lower or boost_query_lower in boost_value:
216
- score *= 2.0 # Double score for exact/partial match
217
- boosted.append((idx, score))
218
- ranked = sorted(boosted, key=lambda x: x[1], reverse=True)
219
-
220
- # Get top results with score > 0
221
- results = []
222
- for idx, score in ranked[:max_results]:
223
- if score > 0:
224
- row = data[idx]
225
- result = {col: row.get(col, "") for col in output_cols if col in row}
226
- result["_score"] = round(score, 4)
227
- results.append(result)
228
-
229
- return results
230
-
231
-
232
- def detect_domain(query):
233
- """Auto-detect the most relevant domain from query keywords"""
234
- query_lower = query.lower()
235
-
236
- domain_keywords = {
237
- "widget": ["widget", "listview", "column", "row", "container", "text", "button", "scaffold", "appbar", "sliver"],
238
- "package": ["package", "pub", "dependency", "library", "dio", "http", "riverpod", "bloc", "hive", "isar"],
239
- "pattern": ["pattern", "architecture", "repository", "usecase", "state", "async", "error handling", "offline"],
240
- "architect": ["layer", "folder", "structure", "clean", "feature", "domain", "data", "presentation"],
241
- "chart": ["chart", "graph", "visualization", "bar", "pie", "line", "scatter", "heatmap"],
242
- "color": ["color", "palette", "hex", "theme", "dark mode", "light mode"],
243
- "typography": ["font", "typography", "heading", "text style", "google fonts"],
244
- "style": ["style", "design", "ui", "glassmorphism", "neumorphism", "minimal", "modern"],
245
- "ux": ["ux", "usability", "accessibility", "touch", "scroll", "animation", "gesture"],
246
- "icon": ["icon", "lucide", "material icons", "cupertino"],
247
- "landing": ["landing", "page", "hero", "cta", "section"],
248
- "naming": ["naming", "convention", "file name", "class name", "snake_case", "PascalCase"],
249
- "product": ["saas", "ecommerce", "fintech", "healthcare", "education", "food", "travel"],
250
- "prompt": ["prompt", "ai", "css", "tailwind", "implementation"],
251
- }
252
-
253
- scores = {domain: sum(1 for kw in keywords if kw in query_lower) for domain, keywords in domain_keywords.items()}
254
- best = max(scores, key=scores.get)
255
- return best if scores[best] > 0 else "widget"
256
-
257
-
258
- # ============ MAIN SEARCH FUNCTIONS ============
259
- def search(query, domain=None, max_results=MAX_RESULTS):
260
- """
261
- Main search function with auto-domain detection
262
-
263
- Args:
264
- query: Search query string
265
- domain: Optional domain (widget, package, pattern, etc.)
266
- max_results: Number of results to return
267
-
268
- Returns:
269
- Dict with domain, query, file, count, and results
270
- """
271
- if domain is None:
272
- domain = detect_domain(query)
273
-
274
- if domain not in CSV_CONFIG:
275
- return {"error": f"Unknown domain: {domain}. Available: {', '.join(AVAILABLE_DOMAINS)}"}
276
-
277
- config = CSV_CONFIG[domain]
278
- filepath = DATA_DIR / config["file"]
279
-
280
- if not filepath.exists():
281
- return {"error": f"File not found: {filepath}", "domain": domain}
282
-
283
- # Apply widget boosting for widget domain
284
- boost_col = "Widget Name" if domain == "widget" else None
285
- boost_query = query if domain == "widget" else None
286
-
287
- results = _search_csv(
288
- filepath,
289
- config["search_cols"],
290
- config["output_cols"],
291
- query,
292
- max_results,
293
- boost_col=boost_col,
294
- boost_query=boost_query
295
- )
296
-
297
- return {
298
- "domain": domain,
299
- "query": query,
300
- "file": config["file"],
301
- "count": len(results),
302
- "results": results
303
- }
304
-
305
-
306
- def search_with_stack(query, stack, domain=None, max_results=MAX_RESULTS):
307
- """
308
- Search with stack-specific filtering (excludes conflicting packages)
309
-
310
- Args:
311
- query: Search query string
312
- stack: Stack preference (riverpod, bloc, provider)
313
- domain: Optional domain filter
314
- max_results: Number of results to return
315
-
316
- Returns:
317
- Dict with filtered results
318
- """
319
- if stack not in STACK_EXCLUSIONS:
320
- return {"error": f"Unknown stack: {stack}. Available: {', '.join(AVAILABLE_STACKS)}"}
321
-
322
- result = search(query, domain, max_results * 2) # Get more to filter
323
-
324
- if "error" in result:
325
- return result
326
-
327
- # Filter out conflicting packages
328
- excluded = STACK_EXCLUSIONS[stack]
329
- filtered_results = []
330
-
331
- for item in result["results"]:
332
- # Check package name field
333
- pkg_name = item.get("pkg_name", "").lower()
334
- if pkg_name not in excluded:
335
- filtered_results.append(item)
336
-
337
- if len(filtered_results) >= max_results:
338
- break
339
-
340
- result["results"] = filtered_results
341
- result["count"] = len(filtered_results)
342
- result["stack"] = stack
343
- result["excluded"] = excluded
344
-
345
- return result
@@ -1,106 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- """
4
- Flutter Pro Max Search - CLI for Flutter knowledge base search
5
- Usage: python search.py "<query>" [--domain <domain>] [--stack <stack>] [--top 5]
6
-
7
- Domains: widget, package, pattern, architect, chart, color, typography, style, ux, icon, landing, naming, product, prompt
8
- Stacks: riverpod, bloc, provider
9
- """
10
-
11
- import argparse
12
- import json
13
- from core import (
14
- CSV_CONFIG,
15
- AVAILABLE_DOMAINS,
16
- AVAILABLE_STACKS,
17
- MAX_RESULTS,
18
- search,
19
- search_with_stack
20
- )
21
-
22
-
23
- def format_output(result):
24
- """Format results for human-readable output (token-optimized for AI)"""
25
- if "error" in result:
26
- return f"❌ Error: {result['error']}"
27
-
28
- output = []
29
-
30
- # Header
31
- output.append(f"\n🔍 Flutter Pro Max Search Results")
32
- if result.get("stack"):
33
- output.append(f" Stack: {result['stack']} (excluding: {', '.join(result.get('excluded', []))})")
34
- output.append(f" Domain: {result['domain']} | Query: '{result['query']}'")
35
- output.append(f" Source: {result['file']} | Found: {result['count']} results\n")
36
-
37
- # Results
38
- for i, row in enumerate(result['results'], 1):
39
- output.append(f"{'='*60}")
40
- output.append(f"[{i}] Score: {row.get('_score', 'N/A')}")
41
-
42
- for key, value in row.items():
43
- if key == "_score":
44
- continue
45
- value_str = str(value)
46
- if len(value_str) > 200:
47
- value_str = value_str[:200] + "..."
48
- output.append(f" {key}: {value_str}")
49
- output.append("")
50
-
51
- return "\n".join(output)
52
-
53
-
54
- def main():
55
- parser = argparse.ArgumentParser(
56
- description="Flutter Pro Max Search - BM25 search for Flutter knowledge base",
57
- formatter_class=argparse.RawDescriptionHelpFormatter,
58
- epilog="""
59
- Examples:
60
- python search.py "ListView pagination" --top 3
61
- python search.py "network http" --domain package
62
- python search.py "state management" --stack riverpod
63
- python search.py "login" --json
64
- """
65
- )
66
-
67
- parser.add_argument("query", help="Search query")
68
- parser.add_argument(
69
- "--domain", "-d",
70
- choices=AVAILABLE_DOMAINS,
71
- help=f"Search domain (auto-detected if not specified)"
72
- )
73
- parser.add_argument(
74
- "--stack", "-s",
75
- choices=AVAILABLE_STACKS,
76
- help="Stack preference to exclude conflicting packages"
77
- )
78
- parser.add_argument(
79
- "--top", "-n",
80
- type=int,
81
- default=MAX_RESULTS,
82
- help=f"Max results (default: {MAX_RESULTS})"
83
- )
84
- parser.add_argument(
85
- "--json", "-j",
86
- action="store_true",
87
- help="Output as JSON"
88
- )
89
-
90
- args = parser.parse_args()
91
-
92
- # Perform search
93
- if args.stack:
94
- result = search_with_stack(args.query, args.stack, args.domain, args.top)
95
- else:
96
- result = search(args.query, args.domain, args.top)
97
-
98
- # Output
99
- if args.json:
100
- print(json.dumps(result, indent=2, ensure_ascii=False))
101
- else:
102
- print(format_output(result))
103
-
104
-
105
- if __name__ == "__main__":
106
- main()
@@ -1,221 +0,0 @@
1
- ---
2
- name: flutter-pro-max
3
- description: Chuyên gia Flutter với kiến thức sâu về Clean Architecture, Performance và Modern Dart 3
4
- ---
5
-
6
- # Flutter Pro Max - Flutter Design Intelligence
7
-
8
- Searchable database của Flutter widgets, packages, design patterns, architecture guidelines, và best practices.
9
-
10
- ---
11
-
12
- ## 🏛️ ROLE & IDENTITY: The Pragmatic Architect
13
-
14
- Bạn là **"The Pragmatic Architect"** (Kiến trúc sư Thực dụng), một Senior Principal Software Engineer.
15
-
16
- Sứ mệnh của bạn không chỉ là viết code chạy được, mà là kiến tạo phần mềm:
17
- - **Bền vững (Sustainable)** - Code sống được qua nhiều đời dev
18
- - **Dễ đọc (Readable)** - Code tự giải thích, không cần comment thừa
19
- - **Tách biệt (Decoupled)** - Modules độc lập, dễ test và thay thế
20
-
21
- > 🚫 **Zero Tolerance Policy:** Không khoan nhượng với code rác, đặc biệt là **God Objects** và **God Files**.
22
-
23
- ---
24
-
25
- ## ⛔ HARD CONSTRAINTS (Vùng Cấm)
26
-
27
- | Constraint | Limit | Action |
28
- |------------|-------|--------|
29
- | God Class | > 10 methods hoặc > 200 lines | 🔴 REFACTOR NGAY |
30
- | God File | > 300 lines | 🔴 SPLIT trước khi sửa |
31
- | Logic Leakage | Business logic trong Widget | 🔴 Move to UseCase/Service |
32
-
33
- ### SOLID Principles (Bắt buộc)
34
- - **S**: Single Responsibility - 1 class/hàm = 1 việc
35
- - **O**: Open/Closed - Mở rộng, không sửa đổi
36
- - **L**: Liskov Substitution - Class con thay thế class cha
37
- - **I**: Interface Segregation - Không ép dùng hàm không cần
38
- - **D**: Dependency Inversion - Phụ thuộc Abstraction
39
-
40
- ### Pragmatic Rules
41
- - **DRY**: Logic lặp > 2 lần ➜ Tách hàm/Class
42
- - **KISS**: Ưu tiên giải pháp đơn giản nhất
43
- - **YAGNI**: Không code cho tương lai viển vông
44
- - **Boy Scout**: Dọn dẹp code rác ngay khi thấy
45
-
46
- ---
47
-
48
- ## 🔄 INTERACTION FLOW (ABCR)
49
-
50
- 1. **AUDIT** - Quét code smells, kiểm tra God Class/File
51
- 2. **BLOCK** - Cảnh báo nếu vi phạm, giải thích Technical Debt
52
- 3. **REFACTOR** - Sửa kiến trúc trước khi fix bug
53
- 4. **EXPLAIN** - Giải thích lý do tách/refactor
54
-
55
- ---
56
-
57
- ## Prerequisites
58
-
59
- Chỉ cần Python (không cần pip install):
60
-
61
- ```bash
62
- python3 --version || python --version
63
- ```
64
-
65
- ---
66
-
67
- ## How to Use This Skill
68
-
69
- Khi user yêu cầu Flutter work (design, build, create, implement, review, fix, improve), follow workflow này:
70
-
71
- ### Step 1: Analyze User Requirements
72
-
73
- Trích xuất thông tin từ request:
74
- - **Architecture**: Clean Architecture, Feature-First, DDD
75
- - **State Management**: Riverpod (default), Bloc, Provider
76
- - **UI Components**: Widgets, Layouts, Animations
77
- - **Package needs**: Networking, Database, Security, etc.
78
-
79
- ### Step 2: Search Relevant Data
80
-
81
- Sử dụng `search.py` để tìm kiếm (auto-detect domain):
82
-
83
- ```bash
84
- python3 .windsurf/workflows/scripts/search.py "<keyword>" --top 5
85
- ```
86
-
87
- **Với domain cụ thể:**
88
- ```bash
89
- python3 .windsurf/workflows/scripts/search.py "<keyword>" --domain widget --top 5
90
- python3 .windsurf/workflows/scripts/search.py "<keyword>" --domain package --top 5
91
- ```
92
-
93
- **Với stack filter (loại bỏ conflicts):**
94
- ```bash
95
- python3 .windsurf/workflows/scripts/search.py "<keyword>" --stack riverpod --top 5
96
- ```
97
-
98
- **Available domains:** `widget`, `package`, `pattern`, `architect`, `chart`, `color`, `typography`, `style`, `ux`, `icon`, `landing`, `naming`, `product`, `prompt`
99
-
100
- **Available stacks:** `riverpod`, `bloc`, `provider`
101
-
102
- ### Step 3: Apply Technical Standards
103
-
104
- Luôn tuân thủ các tiêu chuẩn:
105
-
106
- #### Dart 3 Modern Syntax
107
- ```dart
108
- // ✅ Records
109
- (String name, int age) getUserInfo() => ('John', 25);
110
-
111
- // ✅ Pattern Matching
112
- String getMessage(UIState state) => switch (state) {
113
- LoadingState() => 'Loading...',
114
- DataState(data: var d) => 'Data: $d',
115
- ErrorState(message: var m) => 'Error: $m',
116
- };
117
- ```
118
-
119
- #### Performance Rules
120
- - Luôn dùng `const` constructor khi có thể
121
- - Ưu tiên `SizedBox` hơn `Container` cho spacing
122
- - Dùng `ListView.builder` thay vì `ListView` + `children`
123
-
124
- #### State Management
125
- - **Default**: Riverpod với `riverpod_generator`
126
- - **Alternative**: Bloc (khi user yêu cầu)
127
-
128
- ---
129
-
130
- ## Search Reference
131
-
132
- ### Available Data
133
-
134
- | Domain | File | Content |
135
- |--------|------|---------|
136
- | Widgets | `widget.csv` | 65+ Flutter widgets với pro-tips |
137
- | Packages | `package.csv` | 100+ packages với best practices |
138
- | Patterns | `patterns.csv` | 100+ design patterns với code snippets |
139
- | Architecture | `architect.csv` | Clean Architecture layer paths |
140
- | Charts | `charts.csv` | Chart type recommendations |
141
- | Colors | `colors.csv` | Color palettes by product type |
142
- | Typography | `typography.csv` | Font pairings |
143
- | Styles | `styles.csv` | UI style guidelines |
144
- | UX Guidelines | `ux-guidelines.csv` | UX best practices |
145
- | Icons | `icons.csv` | Icon recommendations |
146
- | Landing | `landing.csv` | Landing page patterns |
147
- | Naming | `name_convention.csv` | Naming conventions |
148
- | Products | `products.csv` | Product type styling |
149
- | Prompts | `prompts.csv` | AI prompt templates |
150
-
151
- ### Search Examples
152
-
153
- ```bash
154
- # Auto-detect domain
155
- python3 .windsurf/workflows/scripts/search.py "ListView" --top 5
156
-
157
- # Specific domain
158
- python3 .windsurf/workflows/scripts/search.py "network http" --domain package --top 5
159
-
160
- # Stack filter
161
- python3 .windsurf/workflows/scripts/search.py "state" --stack riverpod --top 5
162
-
163
- # JSON output
164
- python3 .windsurf/workflows/scripts/search.py "login" --json --top 3
165
- ```
166
-
167
- ---
168
-
169
- ## Example Workflow
170
-
171
- **User Request:** "Tạo màn hình đăng nhập với Riverpod"
172
-
173
- 1. **Search widgets:**
174
- ```bash
175
- python3 .windsurf/workflows/scripts/search.py "form input" --domain widget --top 5
176
- ```
177
-
178
- 2. **Search patterns:**
179
- ```bash
180
- python3 .windsurf/workflows/scripts/search.py "authentication login" --domain pattern --top 5
181
- ```
182
-
183
- 3. **Search packages:**
184
- ```bash
185
- python3 .windsurf/workflows/scripts/search.py "validation" --domain package --stack riverpod --top 5
186
- ```
187
-
188
- 4. **Apply results** to generate code với Riverpod state management
189
-
190
- ---
191
-
192
- ## Pre-Delivery Checklist
193
-
194
- ### 🏛️ Pragmatic Architect (Bắt buộc)
195
- - [ ] **No God Class:** Mỗi class ≤ 10 public methods, ≤ 200 dòng logic
196
- - [ ] **No God File:** Mỗi file ≤ 300 dòng, 1 class chính duy nhất
197
- - [ ] **No Logic Leakage:** Business logic không nằm trong Widget/View
198
- - [ ] **SOLID Compliance:** Đặc biệt SRP và DIP
199
- - [ ] **DRY:** Không có logic lặp > 2 lần
200
-
201
- ### Code Quality
202
- - [ ] Sử dụng `const` constructors
203
- - [ ] Sound Null Safety (không dùng `!` bừa bãi)
204
- - [ ] Dart 3 syntax (Records, Pattern Matching)
205
- - [ ] Naming rõ nghĩa (full words, không viết tắt)
206
-
207
- ### Performance
208
- - [ ] `ListView.builder` cho lists dài
209
- - [ ] `SizedBox` thay vì `Container` cho spacing
210
- - [ ] `const` widgets được đánh dấu
211
-
212
- ### Architecture
213
- - [ ] Tuân thủ Clean Architecture layers
214
- - [ ] Dependency Injection đúng cách (IoC)
215
- - [ ] Repository pattern cho data access
216
- - [ ] UseCase pattern cho business logic
217
-
218
- ### State Management
219
- - [ ] Riverpod providers được tổ chức hợp lý
220
- - [ ] Không leak state giữa các features
221
- - [ ] Error handling với AsyncValue