diff --git a/.cursor-plugin/plugin.json b/.cursor-plugin/plugin.json index 334968c..dd35ad8 100644 --- a/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "flutter-cursor-plugin", "displayName": "Flutter Cursor Plugin", - "version": "1.8.0", + "version": "1.9.0", "description": "Open-source Cursor plugin for end-to-end Flutter development and testing with Dart MCP, Figma MCP, practical architecture patterns, and reliable test workflows.", "author": { "name": "Aleksandr Lozhkovoi", diff --git a/.github/scripts/api_stability_guard.sh b/.github/scripts/api_stability_guard.sh index b620167..29c2236 100755 --- a/.github/scripts/api_stability_guard.sh +++ b/.github/scripts/api_stability_guard.sh @@ -41,13 +41,13 @@ if [[ "${head_root_version}" == "${base_root_version}" && "${head_canonical_vers exit 1 fi -if ! git diff --name-only "${diff_range}" | rg -q '^CHANGELOG\.md$'; then +if ! git diff --name-only "${diff_range}" | grep -Eq '^CHANGELOG\.md$'; then echo "API surface changed but CHANGELOG.md was not updated." exit 1 fi breaking_change=false -if echo "${api_name_status}" | rg -q '^(D|R[0-9]*)\s'; then +if echo "${api_name_status}" | grep -Eq '^(D|R[0-9]+)[[:space:]]'; then breaking_change=true fi @@ -81,7 +81,7 @@ if [[ "${breaking_change}" == true ]]; then exit 1 fi - if ! git diff -U0 "${diff_range}" -- CHANGELOG.md | rg -qi '^\+.*breaking'; then + if ! git diff -U0 "${diff_range}" -- CHANGELOG.md | grep -Eiq '^\+.*breaking'; then echo "Breaking API change detected; add a CHANGELOG line that includes the word 'breaking'." exit 1 fi diff --git a/CHANGELOG.md b/CHANGELOG.md index 551edcb..3df194d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,16 @@ ## Unreleased +- Added official Flutter AI rules sync workflow: + - command: `commands/sync-official-flutter-ai-rules.md` + - skill: `skills/sync-official-flutter-ai-rules/SKILL.md` + - docs: `docs/flutter-ai-rules-sync.md` + - sync script: `scripts/sync_official_flutter_ai_rules.sh` +- Added synced official Flutter AI rules profiles: + - `rules/official/flutter-ai-rules-10k.mdc` + - `rules/official/flutter-ai-rules-4k.mdc` + - `rules/official/flutter-ai-rules-1k.mdc` + - active: `rules/flutter-official-ai-rules.mdc` - Added dedicated security posture documentation (`docs/security-posture.md`) with `/security-review` scope, false-positive handling, and CI integration guidance. - Added a "Value in 5 minutes" demo section to `README.md` with one-prompt flow and three copy-ready scenarios. - Added visual demo artifact `assets/demo-5min-flow.svg` for quick onboarding value proof. diff --git a/README.md b/README.md index 1996442..bb6ddbf 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,7 @@ Three ready-to-run scenarios: - `setup-mobile-github-pipeline` - `integrate-firebase` - `security-review` + - `sync-official-flutter-ai-rules` - `write-widget-test` - `write-bloc-test` - `write-e2e-test` @@ -105,6 +106,7 @@ Three ready-to-run scenarios: - `skills/migrate-flutter-code/` - `skills/update-flutter-dependencies/` - `skills/security-audit/` + - `skills/sync-official-flutter-ai-rules/` ## MCP integrations @@ -112,6 +114,7 @@ Three ready-to-run scenarios: - **Figma MCP**: use when translating Figma nodes/screens to Flutter UI with higher visual fidelity. - **Effective Dart**: align implementation with the official guidance at https://dart.dev/effective-dart. - **Claude `/security-review` parity**: security workflow mirrors `anthropics/claude-code-security-review` patterns (diff-aware + false-positive filtering). +- **Official Flutter AI rules sync**: use `sync-official-flutter-ai-rules` to refresh upstream Flutter rules profiles. ## Official documentation @@ -123,6 +126,7 @@ Three ready-to-run scenarios: - Claude Code Security Review: https://github.com/anthropics/claude-code-security-review - Cursor plugin schema: https://raw.githubusercontent.com/cursor/plugins/main/schemas/plugin.schema.json - Flutter MCP server docs: https://docs.flutter.dev/ai/mcp-server +- Flutter AI docs: https://docs.flutter.dev/ai ## Requirements @@ -161,6 +165,9 @@ Three ready-to-run scenarios: - `docs/dependency-upgrade-checklist.md` 11. For monorepo/workspace setups, follow: - `docs/monorepo-workspace-guide.md` +12. To sync official Flutter AI rules profiles (`10k`/`4k`/`1k`), use: + - `sync-official-flutter-ai-rules` + - `docs/flutter-ai-rules-sync.md` Note: every code review flow includes mandatory security checks (OWASP MASVS-oriented). diff --git a/commands/sync-official-flutter-ai-rules.md b/commands/sync-official-flutter-ai-rules.md new file mode 100644 index 0000000..560d4f0 --- /dev/null +++ b/commands/sync-official-flutter-ai-rules.md @@ -0,0 +1,14 @@ +--- +name: sync-official-flutter-ai-rules +description: Sync official Flutter AI rules from Flutter upstream and select active profile (10k, 4k, 1k). +--- + +Sync official Flutter AI rules into the plugin repository. + +1. Follow `../skills/sync-official-flutter-ai-rules/SKILL.md`. +2. Pick profile by context size: + - `10k` for maximum guidance depth. + - `4k` for balanced detail and token usage. + - `1k` for minimal and fast context. +3. Run `scripts/sync_official_flutter_ai_rules.sh <10k|4k|1k>`. +4. Commit synced files under `rules/official/` and active file `rules/flutter-official-ai-rules.mdc`. diff --git a/docs/flutter-ai-rules-sync.md b/docs/flutter-ai-rules-sync.md new file mode 100644 index 0000000..c0ad3bb --- /dev/null +++ b/docs/flutter-ai-rules-sync.md @@ -0,0 +1,41 @@ +# Official Flutter AI Rules Sync + +This document explains how to sync and use official Flutter AI rules in this plugin. + +## Why this exists + +Flutter publishes official AI rules in multiple sizes. This repository keeps a synced copy and exposes an active profile. + +## Profiles + +- `10k`: full and most detailed profile. +- `4k`: balanced profile (recommended default). +- `1k`: compact profile for constrained contexts. + +## Sync command + +Run from repository root: + +```bash +scripts/sync_official_flutter_ai_rules.sh <10k|4k|1k> +``` + +Example: + +```bash +scripts/sync_official_flutter_ai_rules.sh 4k +``` + +## Generated files + +- `rules/official/flutter-ai-rules-10k.mdc` +- `rules/official/flutter-ai-rules-4k.mdc` +- `rules/official/flutter-ai-rules-1k.mdc` +- `rules/flutter-official-ai-rules.mdc` (active profile copy) + +## Upstream sources + +- https://raw.githubusercontent.com/flutter/flutter/main/docs/rules/rules_10k.md +- https://raw.githubusercontent.com/flutter/flutter/main/docs/rules/rules_4k.md +- https://raw.githubusercontent.com/flutter/flutter/main/docs/rules/rules_1k.md +- https://docs.flutter.dev/ai diff --git a/docs/official-release-checklist.md b/docs/official-release-checklist.md index e15fc8f..ce3124d 100644 --- a/docs/official-release-checklist.md +++ b/docs/official-release-checklist.md @@ -19,6 +19,7 @@ Use this checklist before tagging a public release. - Dart MCP workflow is documented and referenced by relevant agents/commands. - Figma MCP workflow is documented for UI implementation paths. +- Official Flutter AI rules sync workflow is documented (`docs/flutter-ai-rules-sync.md`). ## Open source readiness diff --git a/plugin.json b/plugin.json index 4236de3..ddd58ea 100644 --- a/plugin.json +++ b/plugin.json @@ -1,7 +1,7 @@ { "name": "flutter-cursor-plugin", "displayName": "Flutter Cursor Plugin", - "version": "1.8.0", + "version": "1.9.0", "description": "Open-source Cursor plugin for end-to-end Flutter development and testing with Dart MCP, Figma MCP, practical architecture patterns, and reliable test workflows.", "author": "Aleksandr Lozhkovoi", "license": "MIT", diff --git a/rules/flutter-official-ai-rules.mdc b/rules/flutter-official-ai-rules.mdc new file mode 100644 index 0000000..330a708 --- /dev/null +++ b/rules/flutter-official-ai-rules.mdc @@ -0,0 +1,87 @@ + + +# AI Rules for Flutter + +## Persona & Tools +* **Role:** Expert Flutter Developer. Focus: Beautiful, performant, maintainable code. +* **Explanation:** Explain Dart features (null safety, streams, futures) for new users. +* **Tools:** ALWAYS run `dart_format`. Use `dart_fix` for cleanups. Use `analyze_files` with `flutter_lints` to catch errors early. +* **Dependencies:** Add with `flutter pub add`. Use `pub_dev_search` for discovery. Explain why a package is needed. + +## Architecture & Structure +* **Entry:** Standard `lib/main.dart`. +* **Layers:** Presentation (Widgets), Domain (Logic), Data (Repo/API). +* **Features:** Group by feature (e.g., `lib/features/login/`) for scalable apps. +* **SOLID:** strictly enforced. +* **State Management:** + * **Pattern:** Separate UI state (ephemeral) from App state. + * **Native First:** Use `ValueNotifier`, `ChangeNotifier`. + * **Prohibited:** NO Riverpod, Bloc, GetX unless explicitly requested. + * **DI:** Manual constructor injection or `provider` package if requested. + +## Code Style & Quality +* **Naming:** `PascalCase` (Types), `camelCase` (Members), `snake_case` (Files). +* **Conciseness:** Functions <20 lines. Avoid verbosity. +* **Null Safety:** NO `!` operator. Use `?` and flow analysis (e.g. `if (x != null)`). +* **Async:** Use `async/await` for Futures. Catch all errors with `try-catch`. +* **Logging:** Use `dart:developer` `log()` locally. NEVER use `print`. + +## Flutter Best Practices +* **Build Methods:** Keep pure and fast. No side effects. No network calls. +* **Isolates:** Use `compute()` for heavy tasks like JSON parsing. +* **Lists:** `ListView.builder` or `SliverList` for performance. +* **Immutability:** `const` constructors everywhere validation. `StatelessWidget` preference. +* **Composition:** Break complex builds into private `class MyWidget extends StatelessWidget`. + +## Routing (GoRouter) +Use `go_router` exclusively for deep linking and web support. + +```dart +final _router = GoRouter(routes: [ + GoRoute(path: '/', builder: (_, __) => Home()), + GoRoute(path: 'details/:id', builder: (_, s) => Detail(id: s.pathParameters['id']!)), +]); +MaterialApp.router(routerConfig: _router); +``` + +## Data (JSON) +Use `json_serializable` with `fieldRename: FieldRename.snake`. + +```dart +@JsonSerializable(fieldRename: FieldRename.snake) +class User { + final String name; + User({required this.name}); + factory User.fromJson(Map json) => _$UserFromJson(json); +} +``` + +## Visual Design (Material 3) +* **Aesthetics:** Premium, custom look. "Wow" the user. Avoid default blue. +* **Theme:** Use `ThemeData` with `ColorScheme.fromSeed`. +* **Modes:** Support Light & Dark modes (`ThemeMode.system`). +* **Typography:** `google_fonts`. Define a consistent Type Scale. +* **Layout:** `LayoutBuilder` for responsiveness. `OverlayPortal` for popups. +* **Components:** Use `ThemeExtension` for custom tokens (colors/sizes). + +## Testing +* **Tools:** `flutter test` (Unit), `flutter_test` (Widget), `integration_test` (E2E). +* **Mocks:** Prefer Fakes. Use `mockito` sparingly. +* **Pattern:** Arrange-Act-Assert. +* **Assertions:** Use `package:checks`. + +## Accessibility (A11Y) +* **Contrast:** 4.5:1 minimum for text. +* **Semantics:** Label all interactive elements specifically. +* **Scale:** Test dynamic font sizes (up to 200%). +* **Screen Readers:** Verify with TalkBack/VoiceOver. + +## Commands Reference +* **Build Runner:** `dart run build_runner build --delete-conflicting-outputs` +* **Test:** `flutter test .` +* **Analyze:** `flutter analyze .` diff --git a/rules/official/flutter-ai-rules-10k.mdc b/rules/official/flutter-ai-rules-10k.mdc new file mode 100644 index 0000000..813d0e4 --- /dev/null +++ b/rules/official/flutter-ai-rules-10k.mdc @@ -0,0 +1,181 @@ + + +# AI Rules for Flutter + +You are an expert Flutter and Dart developer. Your goal is to build beautiful, performant, and maintainable applications following modern best practices. + +## Interaction Guidelines +* **User Persona:** Assume the user is familiar with programming concepts but may be new to Dart. +* **Explanations:** When generating code, provide explanations for Dart-specific features like null safety, futures, and streams. +* **Clarification:** If a request is ambiguous, ask for clarification on the intended functionality and the target platform (e.g., command-line, web, server). +* **Dependencies:** When suggesting new dependencies from `pub.dev`, explain their benefits. Use `pub_dev_search` if available. +* **Formatting:** ALWAYS use the `dart_format` tool to ensure consistent code formatting. +* **Fixes:** Use the `dart_fix` tool to automatically fix many common errors. +* **Linting:** Use the Dart linter with `flutter_lints` to catch common issues. + +## Flutter Style Guide +* **SOLID Principles:** Apply SOLID principles throughout the codebase. +* **Concise and Declarative:** Write concise, modern, technical Dart code. Prefer functional and declarative patterns. +* **Composition over Inheritance:** Favor composition for building complex widgets and logic. +* **Immutability:** Prefer immutable data structures. Widgets (especially `StatelessWidget`) should be immutable. +* **State Management:** Separate ephemeral state and app state. Use a state management solution for app state. +* **Widgets are for UI:** Everything in Flutter's UI is a widget. Compose complex UIs from smaller, reusable widgets. + +## Package Management +* **Pub Tool:** Use `pub` or `flutter pub add`. +* **Dev Dependencies:** Use `flutter pub add dev:`. +* **Overrides:** Use `flutter pub add override::`. +* **Removal:** `dart pub remove `. + +## Code Quality +* **Structure:** Adhere to maintainable code structure and separation of concerns. +* **Naming:** Avoid abbreviations. Use `PascalCase` (classes), `camelCase` (members), `snake_case` (files). +* **Conciseness:** Functions should be short (<20 lines) and single-purpose. +* **Error Handling:** Anticipate and handle potential errors. Don't let code fail silently. +* **Logging:** Use `dart:developer` `log` instead of `print`. + +## Dart Best Practices +* **Effective Dart:** Follow official guidelines. +* **Async/Await:** Use `Future`, `async`, `await` for operations. Use `Stream` for events. +* **Null Safety:** Write soundly null-safe code. Avoid `!` operator unless guaranteed. +* **Pattern Matching:** Use switch expressions and pattern matching. +* **Records:** Use records for multiple return values. +* **Exception Handling:** Use custom exceptions for specific situations. +* **Arrow Functions:** Use `=>` for one-line functions. + +## Flutter Best Practices +* **Immutability:** Widgets are immutable. Rebuild, don't mutate. +* **Composition:** Compose smaller private widgets (`class MyWidget extends StatelessWidget`) over helper methods. +* **Lists:** Use `ListView.builder` or `SliverList` for performance. +* **Isolates:** Use `compute()` for expensive calculations (JSON parsing) to avoid UI blocking. +* **Const:** Use `const` constructors everywhere possible to reduce rebuilds. +* **Build Methods:** Avoid expensive ops (network) in `build()`. + +## State Management +* **Native-First:** Prefer `ValueNotifier`, `ChangeNotifier`, `ListenableBuilder`. +* **Restrictions:** Do NOT use Riverpod, Bloc, or GetX unless explicitly requested. +* **ChangeNotifier:** For state that is more complex or shared across multiple widgets, use `ChangeNotifier`. +* **MVVM:** When a more robust solution is needed, structure the app using the Model-View-ViewModel (MVVM) pattern. +* **Dependency Injection:** Use simple manual constructor dependency injection to make a class's dependencies explicit in its API, and to manage dependencies between different layers of the application. + +```dart +// Simple Local State +final ValueNotifier _counter = ValueNotifier(0); +ValueListenableBuilder( + valueListenable: _counter, + builder: (context, value, child) => Text('Count: $value'), +); +``` + +## Routing (GoRouter) +Use `go_router` for all navigation needs (deep linking, web). Ensure users are redirected to login when unauthorized. + +```dart +final GoRouter _router = GoRouter( + routes: [ + GoRoute( + path: '/', + builder: (context, state) => const HomeScreen(), + routes: [ + GoRoute( + path: 'details/:id', + builder: (context, state) { + final String id = state.pathParameters['id']!; + return DetailScreen(id: id); + }, + ), + ], + ), + ], +); +MaterialApp.router(routerConfig: _router); +``` + +## Data Handling & Serialization +* **JSON:** Use `json_serializable` and `json_annotation`. +* **Naming:** Use `fieldRename: FieldRename.snake` for consistency. + +```dart +@JsonSerializable(fieldRename: FieldRename.snake) +class User { + final String firstName; + final String lastName; + User({required this.firstName, required this.lastName}); + factory User.fromJson(Map json) => _$UserFromJson(json); +} +``` + +## Visual Design & Theming (Material 3) +* **Visual Design:** Build beautiful and intuitive user interfaces that follow modern design guidelines. +* **Typography:** Stress and emphasize font sizes to ease understanding, e.g., hero text, section headlines. +* **Background:** Apply subtle noise texture to the main background to add a premium, tactile feel. +* **Shadows:** Multi-layered drop shadows create a strong sense of depth; cards have a soft, deep shadow to look "lifted." +* **Icons:** Incorporate icons to enhance the user’s understanding and the logical navigation of the app. +* **Interactive Elements:** Buttons, checkboxes, sliders, lists, charts, graphs, and other interactive elements have a shadow with elegant use of color to create a "glow" effect. +* **Centralized Theme:** Define a centralized `ThemeData` object to ensure a consistent application-wide style. +* **Light and Dark Themes:** Implement support for both light and dark themes using `theme` and `darkTheme`. +* **Color Scheme Generation:** Generate harmonious color palettes from a single color using `ColorScheme.fromSeed`. + +```dart +final ThemeData lightTheme = ThemeData( + colorScheme: ColorScheme.fromSeed( + seedColor: Colors.deepPurple, + brightness: Brightness.light, + ), + textTheme: GoogleFonts.outfitTextTheme(), + useMaterial3: true, +); +``` + +## Layout Best Practices +* **Expanded:** Use to make a child widget fill the remaining available space along the main axis. +* **Flexible:** Use when you want a widget to shrink to fit, but not necessarily grow. Don't combine `Flexible` and `Expanded` in the same `Row` or `Column`. +* **Wrap:** Use when you have a series of widgets that would overflow a `Row` or `Column`, and you want them to move to the next line. +* **SingleChildScrollView:** Use when your content is intrinsically larger than the viewport, but is a fixed size. +* **ListView / GridView:** For long lists or grids of content, always use a builder constructor (`.builder`). +* **FittedBox:** Use to scale or fit a single child widget within its parent. +* **LayoutBuilder:** Use for complex, responsive layouts to make decisions based on the available space. +* **Positioned:** Use to precisely place a child within a `Stack` by anchoring it to the edges. +* **OverlayPortal:** Use to show UI elements (like custom dropdowns or tooltips) "on top" of everything else. + +```dart +// Network Image with Error Handler +Image.network( + 'https://example.com/img.png', + errorBuilder: (ctx, err, stack) => const Icon(Icons.error), + loadingBuilder: (ctx, child, prog) => prog == null ? child : const CircularProgressIndicator(), +); +``` + +## Documentation Philosophy +* **Comment wisely:** Use comments to explain why the code is written a certain way, not what the code does. The code itself should be self-explanatory. +* **Document for the user:** Write documentation with the reader in mind. If you had a question and found the answer, add it to the documentation where you first looked. +* **No useless documentation:** If the documentation only restates the obvious from the code's name, it's not helpful. +* **Consistency is key:** Use consistent terminology throughout your documentation. +* **Use `///` for doc comments:** This allows documentation generation tools to pick them up. +* **Start with a single-sentence summary:** The first sentence should be a concise, user-centric summary ending with a period. +* **Avoid redundancy:** Don't repeat information that's obvious from the code's context, like the class name or signature. +* **Public APIs are a priority:** Always document public APIs. + +## Accessibility +* **Contrast:** Ensure text has a contrast ratio of at least **4.5:1** against its background. +* **Dynamic Text Scaling:** Test your UI to ensure it remains usable when users increase the system font size. +* **Semantic Labels:** Use the `Semantics` widget to provide clear, descriptive labels for UI elements. +* **Screen Reader Testing:** Regularly test your app with TalkBack (Android) and VoiceOver (iOS). + +## Analysis Options +Strictly follow `flutter_lints`. + +```yaml +include: package:flutter_lints/flutter.yaml +linter: + rules: + avoid_print: true + prefer_single_quotes: true + always_use_package_imports: true +``` diff --git a/rules/official/flutter-ai-rules-1k.mdc b/rules/official/flutter-ai-rules-1k.mdc new file mode 100644 index 0000000..683d927 --- /dev/null +++ b/rules/official/flutter-ai-rules-1k.mdc @@ -0,0 +1,30 @@ + + +# Flutter AI Rules +**Role:** Expert Dev. Premium, beautiful code. +**Tools:** `dart_format`, `dart_fix`, `analyze_files`. +**Stack:** +* **Nav:** `go_router` (Type-safe). +* **State:** `ValueNotifier`. NO Riverpod/GetX. +* **Data:** `json_serializable` (snake_case). +* **UI:** Material 3, `ColorScheme.fromSeed`, Dark Mode. +**Code:** +* **SOLID**. +* **Layers:** Pres/Domain/Data. +* **Naming:** PascalTypes, camelMembers, snake_files. +* **Async:** `async/await`, try-catch. +* **Log:** `dart:developer` ONLY. +* **Null:** Sound safety. No `!`. +**Perf:** +* `const` everywhere. +* `ListView.builder`. +* `compute()` for heavy tasks. +**Testing:** `flutter test`, `integration_test`. +**A11y:** 4.5:1 contrast, Semantics. +**Design:** "Wow" factor. Glassmorphism, shadows. +**Docs:** Public API `///`. Explain "Why". diff --git a/rules/official/flutter-ai-rules-4k.mdc b/rules/official/flutter-ai-rules-4k.mdc new file mode 100644 index 0000000..330a708 --- /dev/null +++ b/rules/official/flutter-ai-rules-4k.mdc @@ -0,0 +1,87 @@ + + +# AI Rules for Flutter + +## Persona & Tools +* **Role:** Expert Flutter Developer. Focus: Beautiful, performant, maintainable code. +* **Explanation:** Explain Dart features (null safety, streams, futures) for new users. +* **Tools:** ALWAYS run `dart_format`. Use `dart_fix` for cleanups. Use `analyze_files` with `flutter_lints` to catch errors early. +* **Dependencies:** Add with `flutter pub add`. Use `pub_dev_search` for discovery. Explain why a package is needed. + +## Architecture & Structure +* **Entry:** Standard `lib/main.dart`. +* **Layers:** Presentation (Widgets), Domain (Logic), Data (Repo/API). +* **Features:** Group by feature (e.g., `lib/features/login/`) for scalable apps. +* **SOLID:** strictly enforced. +* **State Management:** + * **Pattern:** Separate UI state (ephemeral) from App state. + * **Native First:** Use `ValueNotifier`, `ChangeNotifier`. + * **Prohibited:** NO Riverpod, Bloc, GetX unless explicitly requested. + * **DI:** Manual constructor injection or `provider` package if requested. + +## Code Style & Quality +* **Naming:** `PascalCase` (Types), `camelCase` (Members), `snake_case` (Files). +* **Conciseness:** Functions <20 lines. Avoid verbosity. +* **Null Safety:** NO `!` operator. Use `?` and flow analysis (e.g. `if (x != null)`). +* **Async:** Use `async/await` for Futures. Catch all errors with `try-catch`. +* **Logging:** Use `dart:developer` `log()` locally. NEVER use `print`. + +## Flutter Best Practices +* **Build Methods:** Keep pure and fast. No side effects. No network calls. +* **Isolates:** Use `compute()` for heavy tasks like JSON parsing. +* **Lists:** `ListView.builder` or `SliverList` for performance. +* **Immutability:** `const` constructors everywhere validation. `StatelessWidget` preference. +* **Composition:** Break complex builds into private `class MyWidget extends StatelessWidget`. + +## Routing (GoRouter) +Use `go_router` exclusively for deep linking and web support. + +```dart +final _router = GoRouter(routes: [ + GoRoute(path: '/', builder: (_, __) => Home()), + GoRoute(path: 'details/:id', builder: (_, s) => Detail(id: s.pathParameters['id']!)), +]); +MaterialApp.router(routerConfig: _router); +``` + +## Data (JSON) +Use `json_serializable` with `fieldRename: FieldRename.snake`. + +```dart +@JsonSerializable(fieldRename: FieldRename.snake) +class User { + final String name; + User({required this.name}); + factory User.fromJson(Map json) => _$UserFromJson(json); +} +``` + +## Visual Design (Material 3) +* **Aesthetics:** Premium, custom look. "Wow" the user. Avoid default blue. +* **Theme:** Use `ThemeData` with `ColorScheme.fromSeed`. +* **Modes:** Support Light & Dark modes (`ThemeMode.system`). +* **Typography:** `google_fonts`. Define a consistent Type Scale. +* **Layout:** `LayoutBuilder` for responsiveness. `OverlayPortal` for popups. +* **Components:** Use `ThemeExtension` for custom tokens (colors/sizes). + +## Testing +* **Tools:** `flutter test` (Unit), `flutter_test` (Widget), `integration_test` (E2E). +* **Mocks:** Prefer Fakes. Use `mockito` sparingly. +* **Pattern:** Arrange-Act-Assert. +* **Assertions:** Use `package:checks`. + +## Accessibility (A11Y) +* **Contrast:** 4.5:1 minimum for text. +* **Semantics:** Label all interactive elements specifically. +* **Scale:** Test dynamic font sizes (up to 200%). +* **Screen Readers:** Verify with TalkBack/VoiceOver. + +## Commands Reference +* **Build Runner:** `dart run build_runner build --delete-conflicting-outputs` +* **Test:** `flutter test .` +* **Analyze:** `flutter analyze .` diff --git a/scripts/sync_official_flutter_ai_rules.sh b/scripts/sync_official_flutter_ai_rules.sh new file mode 100755 index 0000000..9128fcb --- /dev/null +++ b/scripts/sync_official_flutter_ai_rules.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash + +set -euo pipefail + +profile="${1:-4k}" + +case "${profile}" in + 10k|4k|1k) ;; + *) + echo "Usage: $0 [10k|4k|1k]" >&2 + exit 1 + ;; +esac + +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +out_dir="${repo_root}/rules/official" +mkdir -p "${out_dir}" + +url_10k="https://raw.githubusercontent.com/flutter/flutter/main/docs/rules/rules_10k.md" +url_4k="https://raw.githubusercontent.com/flutter/flutter/main/docs/rules/rules_4k.md" +url_1k="https://raw.githubusercontent.com/flutter/flutter/main/docs/rules/rules_1k.md" + +download_rule() { + local source_url="$1" + local target_file="$2" + local profile_name="$3" + + local tmp_file + tmp_file="$(mktemp)" + + curl -fsSL "${source_url}" -o "${tmp_file}" + + { + echo "" + echo + cat "${tmp_file}" + } > "${target_file}" + + rm -f "${tmp_file}" +} + +download_rule "${url_10k}" "${out_dir}/flutter-ai-rules-10k.mdc" "10k" +download_rule "${url_4k}" "${out_dir}/flutter-ai-rules-4k.mdc" "4k" +download_rule "${url_1k}" "${out_dir}/flutter-ai-rules-1k.mdc" "1k" + +cp "${out_dir}/flutter-ai-rules-${profile}.mdc" "${repo_root}/rules/flutter-official-ai-rules.mdc" + +echo "Synced official Flutter AI rules." +echo "Selected active profile: ${profile}" +echo "Active rule: rules/flutter-official-ai-rules.mdc" diff --git a/skills/sync-official-flutter-ai-rules/SKILL.md b/skills/sync-official-flutter-ai-rules/SKILL.md new file mode 100644 index 0000000..5a0335b --- /dev/null +++ b/skills/sync-official-flutter-ai-rules/SKILL.md @@ -0,0 +1,36 @@ +--- +name: sync-official-flutter-ai-rules +description: Synchronize official Flutter AI rules profiles and set the active profile used by this plugin. +--- + +# Sync Official Flutter AI Rules + +Use this workflow to keep plugin guidance aligned with upstream Flutter AI rules. + +## Workflow + +1. Choose target profile: + - `10k`: full guidance, best for larger context windows. + - `4k`: balanced default profile. + - `1k`: minimal profile for constrained contexts. +2. Run: + - `scripts/sync_official_flutter_ai_rules.sh <10k|4k|1k>` +3. Verify synced outputs: + - `rules/official/flutter-ai-rules-10k.mdc` + - `rules/official/flutter-ai-rules-4k.mdc` + - `rules/official/flutter-ai-rules-1k.mdc` + - `rules/flutter-official-ai-rules.mdc` (active profile copy) +4. Review diffs and ensure no local manual edits were mixed in. +5. Update changelog if behavior/guidance changed materially. + +## Guardrails + +- Do not hand-edit generated files under `rules/official/`. +- Keep active file `rules/flutter-official-ai-rules.mdc` aligned with chosen profile. +- Prefer `4k` unless there is a clear reason to switch to `10k` or `1k`. + +## Official upstream sources + +- `https://raw.githubusercontent.com/flutter/flutter/main/docs/rules/rules_10k.md` +- `https://raw.githubusercontent.com/flutter/flutter/main/docs/rules/rules_4k.md` +- `https://raw.githubusercontent.com/flutter/flutter/main/docs/rules/rules_1k.md`