From 1d46007a5b25e82b9038d3c388ef0c779776850b Mon Sep 17 00:00:00 2001 From: Camille Simon Date: Fri, 12 Jun 2026 14:58:45 -0700 Subject: [PATCH 1/5] Add first set of skills --- .../camera_android_camerax/skills/android-cli | 1 + .../skills/dart-add-unit-test | 1 + .../third_party/skills/android-cli/SKILL.md | 231 ++++++++++++++++++ .../skills/android-cli/references/interact.md | 36 +++ .../skills/android-cli/references/journeys.md | 50 ++++ .../skills/dart-add-unit-test/SKILL.md | 122 +++++++++ 6 files changed, 441 insertions(+) create mode 120000 packages/camera/camera_android_camerax/skills/android-cli create mode 120000 packages/camera/camera_android_camerax/skills/dart-add-unit-test create mode 100644 packages/third_party/skills/android-cli/SKILL.md create mode 100644 packages/third_party/skills/android-cli/references/interact.md create mode 100644 packages/third_party/skills/android-cli/references/journeys.md create mode 100644 packages/third_party/skills/dart-add-unit-test/SKILL.md diff --git a/packages/camera/camera_android_camerax/skills/android-cli b/packages/camera/camera_android_camerax/skills/android-cli new file mode 120000 index 000000000000..5ca76d6577eb --- /dev/null +++ b/packages/camera/camera_android_camerax/skills/android-cli @@ -0,0 +1 @@ +../../../../third_party/skills/android-cli \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/skills/dart-add-unit-test b/packages/camera/camera_android_camerax/skills/dart-add-unit-test new file mode 120000 index 000000000000..b6a4b4c26126 --- /dev/null +++ b/packages/camera/camera_android_camerax/skills/dart-add-unit-test @@ -0,0 +1 @@ +../../../../third_party/skills/dart-add-unit-test \ No newline at end of file diff --git a/packages/third_party/skills/android-cli/SKILL.md b/packages/third_party/skills/android-cli/SKILL.md new file mode 100644 index 000000000000..1938645a3463 --- /dev/null +++ b/packages/third_party/skills/android-cli/SKILL.md @@ -0,0 +1,231 @@ +--- +name: android-cli +description: Provides instructions for installing and using the `android` CLI. The `android` command-line tool is a critical tool for Android development and helps you create new Android projects, run Android apps on devices, manage and interact with Android virtual devices (including screenshots and UI inspection), manage Android SDK components, look up official Android documentation, and discover and install official Android skills. +license: Complete terms in LICENSE.txt +metadata: + author: Google LLC + keywords: + - sdk + - emulator + - skills + - docs + - knowledge base + - project creation + - screenshots +--- +# Android CLI Specialist + +This skill provides instructions for using the `android` CLI tool. The tool includes various commands for creating projects, running applications, interacting with devices, and managing the CLI environment. + +## Installation + +If the android tool is not in the path, install it. To install run the following command: +Linux: curl -fsSL https://dl.google.com/android/cli/latest/linux_x86_64/install.sh | bash +Mac Arm: curl -fsSL https://dl.google.com/android/cli/latest/darwin_arm64/install.sh | bash +Mac Intel: curl -fsSL https://dl.google.com/android/cli/latest/darwin_x86_64/install.sh | bash +Windows: curl -fsSL https://dl.google.com/android/cli/latest/windows_x86_64/install.cmd -o "%TEMP%\i.cmd" && "%TEMP%\i.cmd" + +## SDK management +To manage the installation of Android SDKs and tools, use the `sdk` command. For example: + +- `android sdk install [@]...`: Install specific packages. Multiple packages can be specified, separated by spaces. `` defaults to latest. For example: `android sdk install platforms/android-30@2 platforms/android-34` +- `android sdk update []`: Update a specific package or all packages to the latest version. +- `android sdk remove `: Remove a package from the local SDK. +- `android sdk list --all`: List installed and available SDK packages. + +## Project creation +Create projects from templates using the `create` command. + +For example: `android create empty-activity --name="My App" --output=./my-app` + +## Interacting with devices +For more information on interacting with running devices, see [here](references/interact.md) + +## Running journey tests +For more information on running journeys, see [here](references/journeys.md) + +## Doc searching +The `docs` command searches authoritative, high-quality Android developer documentation in the Android Knowledge Base. +By providing a few keywords, this tool will return high quality articles that contain examples or guidance on how to use Android APIs or libraries. +Use this tool to obtain additional information on how to achieve Android-specific tasks or to know more about Android APIs, surfaces, libraries, or devices. + +Always use this tool to get the most up-to-date information about Android concepts. Typical good use cases are: + - Finding migration guides for APIs. + - Finding examples for APIs. + - Finding up-to-date information about Android APIs. + - Finding best practices for Android concepts. + +## Running APKs +Use the `run` command to run Android apps. + +## Managing emulators + +Manage Android Virtual Devices (AVDs) using the `android emulator` command + +## Capturing screenshots + +Capture an image of the current screen of a connected Android device and output it to a file using the `android screenshot` command. + +## Managing skills + +Manage antigravity agent skills for Android using the `android skills` command. + +## Inspecting UI Layouts + +Use the `android layout` command to inspect the UI layout of an Android application. It returns the layout tree of an Android application in JSON format. When debugging UI errors, this is often a much faster approach than taking a screenshot. + +## Updating the CLI + +Update the Android CLI using the `android update` command. + +# `android help` output + +Usage: android [-hV] [--sdk=PARAM] [COMMAND] + -h, --help Show this help message and exit. + --sdk=PARAM Path to the Android SDK + -V, --version Print version information and exit. +Commands: + create Create a new Android project + describe Analyzes an Android project to generate descriptive metadata. + docs Android documentation commands + emulator Emulator commands + help Shows the help of all commands + info Print environment information (SDK Location, etc.) + init Initializes the environment (eg. skills) for Android CLI. + layout Returns the layout tree of an application + run Deploy an Android Application + screen Commands to view the device + sdk Download and list SDK packages + skills Manage skills + studio Android Studio commands + update Update the Android CLI + +create + Usage: android create [-h] [--verbose] [--list] [--minSdk=api] + --name=applicationName [-o=dest-path] [template-name] + Create a new Android project + [template-name] The template name + -h, --help Show this help message and exit. + --minSdk=api The 'minSdk' supported by the application (default + is defined in the template) + --name=applicationName + The name of the application (e.g. 'My Application') + -o, --output=dest-path The destination project directory path (default is + '.') + --verbose Enables verbose output + --list List all available templates + +describe + Usage: android describe [-hV] [--project_dir=PARAM] + Analyzes an Android project to generate descriptive metadata. + This command identifies and outputs the paths to JSON files that detail the + project's structure, including build targets and their corresponding output + artifact locations (e.g., APKs). This information enables other tools and + commands to locate build artifacts efficiently. + -h, --help Show this help message and exit. + --project_dir=PARAM The project directory to describe + -V, --version Print version information and exit. + +docs + Usage: android docs [-h] [COMMAND] + Android documentation commands + -h, --help Show this help message and exit. + Commands: + search Search Android documentation + fetch Fetch Android documentation + +emulator + Usage: android emulator [-h] [COMMAND] + Emulator commands + -h, --help Show this help message and exit. + Commands: + create Creates a virtual device + start Launches the specified virtual device. This command will return when + the emulator is fully started and ready to use. + stop Stops the specified virtual device + list Lists available virtual devices + remove Delete a virtual device + +help + Usage: android help [COMMAND] + Shows the help of all commands + [COMMAND] The command to show help for + +info + Usage: android info + Print environment information (SDK Location, etc.) + The specific field to print the value of. If omitted print all. + +init + Usage: android init + Initializes the environment (eg. skills) for Android CLI. + +layout + Usage: android layout [-dhp] [--device=PARAM] [-o=PARAM] + Returns the layout tree of an application + -d, --diff Returns a flat list of the layout elements that have + changed since the last invocation of ui-dump + --device=PARAM The device serial number + -h, --help Show this help message and exit. + -o, --output=PARAM Writes the layout tree to the specified file or + directory. If omitted, prints the tree to standard + output + -p, --pretty Pretty-prints the returned JSON + +run + Usage: android run [-h] [--debug] [--activity=PARAM] [--device=PARAM] + [--type=PARAM] [--apks=PARAM[,PARAM...]]... + Deploy an Android Application + --activity=PARAM The activity name + --apks=PARAM[,PARAM...] + The paths to the APKs + --debug Run in debug mode + --device=PARAM The device serial number + -h, --help Show this help message and exit. + --type=PARAM The component type (ACTIVITY, SERVICE, etc.) + +screen + Usage: android screen [-h] [COMMAND] + Commands to view the device + -h, --help Show this help message and exit. + Commands: + capture Outputs the device screen to a PNG + resolve Target UI elements visually + +sdk + Usage: android sdk [COMMAND] + Download and list SDK packages + Commands: + install Install SDK packages + update Update one or all packages to the latest version + remove Remove a package from the SDK + list List installed and available SDK packages + +skills + Usage: android skills [COMMAND] + Manage skills + Commands: + add Install a skill + remove Remove a skill + list List available skills + find Find skills by keyword + +studio + Usage: android studio [-h] [COMMAND] + Android Studio commands + -h, --help Show this help message and exit. + Commands: + find-declaration Find declaration of a symbol + find-usages Find usages of a symbol + open-file Open a file in Android Studio + check Check the status of running Studio instances + analyze-file Analyze a file in Android Studio + render-compose-preview Render a Compose preview in Android Studio + version-lookup Looks up the latest available versions on the + internet of maven artifacts, Android versions, and + more. + +update + Usage: android update [--url=PARAM] + Update the Android CLI + --url=PARAM The URL to download the update from diff --git a/packages/third_party/skills/android-cli/references/interact.md b/packages/third_party/skills/android-cli/references/interact.md new file mode 100644 index 000000000000..3e37f4ac8d60 --- /dev/null +++ b/packages/third_party/skills/android-cli/references/interact.md @@ -0,0 +1,36 @@ +Title: Live Content + +Description: Fetched live + +Source: https://raw.githubusercontent.com/android/skills/main/devtools/android-cli/references/interact.md + +--- + +# Tools +Run `android layout --help` and `android screen --help`. + +## UI Dump +`android layout` returns a flat JSON list of the UI elements on screen. +`android layout --diff` returns a flat JSON list of the UI elements that have changed since the last call to `layout` or `layout --diff` + +Each JSON object represents a UI element in the Android app. The following properties may be present: +- `text` - any literal text the element contains +- `resourceId` - the Android resource id used to refer to the element +- `contentDesc` - a description of a UI element for use by accessibility tools +- `interactions` - the set of user interactions the element supports. May contain one or more of: `checkable`, `clickable`, `focusable`, `scrollable`, `long-clickable`, `password` +- `state` - the set of states the element is in. May contain one or more of `checked`, `focused`, `selected` +- `bounds` - the screen coordinates of the bounding rectangle of the element, in the format `[min X,min Y][max X, max Y]` +- `center` - the screen coordinates of the center of the element, in the format `[x,y]` +- `off-screen` - if true, the element is in the UI hierarchy but not visible; it may require scrolling to view. + +Use `layout` as a primary means of examining an Android app. Use `layout --diff` to focus on changes and to keep your context small. +Example: When entering digits into a calculator, use `layout --diff` to output only the digit readout element. + +`layout` may fail due to the app displaying a WebView or animation; in these cases, use `android screen --annotate` to inspect the app. +This failure will likely resolve after navigating away from the current screen. + +## Screenshot +`android screen capture -o ` saves a PNG of the current device screen to `` + +Use `screen capture` as a secondary me + diff --git a/packages/third_party/skills/android-cli/references/journeys.md b/packages/third_party/skills/android-cli/references/journeys.md new file mode 100644 index 000000000000..7ffc26fa6919 --- /dev/null +++ b/packages/third_party/skills/android-cli/references/journeys.md @@ -0,0 +1,50 @@ +Title: Live Content + +Description: Fetched live + +Source: https://raw.githubusercontent.com/android/skills/main/devtools/android-cli/references/journeys.md + +--- + +A journey is an XML-specified test of an Android app's behavior. It consists of a list of `` elements. For example: +```xml + + + A sample journey to illustrate the format + + + + Tap the "Home" icon + + + Verify that the app is on its Home screen + + + +``` + +Evaluate a journey by proceeding through the `` list in sequential order. Evaluate each `` block individually. +A journey succeeds if all elements in the `` list succeed. + +A journey is a test case for an app. The journey XML is the source of truth; if the app disagrees with the journey, the app has failed. +Additionally, if the app exits, crashes, or freezes, journey evaluation stops and the journey fails. + +**IMPORTANT** - Execute each step EXACTLY as written, and independently of other steps! If an action says to `"tap the first search result"`, +you MUST find the search results and tap the first one. Do this even if you believe you know the intent behind the action. + +## Taking Actions +Some `` elements specify UI interactions to perform on the running Android app. Perform the interaction and verify that the app does +not crash or behave in an unexpected manner. This is the *only* verification you should perform for an ``. + +If the interaction cannot be performed as specified, the journey fails. +Example: +```Click the red button``` +If you determine a red button is not present in the UI, the journey fails. + +If the text of an `` specifies a list of actions, break it into sub-actions and evaluate them individually: +Example: +```Search for soda and add the first result to the cart``` +This should be evaluated as: +``` +Search for soda Review stack trace for failures -> Fix implementation or assertions -> Re-run until passing. + +## Examples + +### Standard Unit Test Suite +Demonstrates grouping, setup, synchronous, and asynchronous testing. + +```dart +import 'package:test/test.dart'; +import 'package:my_package/calculator.dart'; + +void main() { + group('Calculator', () { + late Calculator calc; + + setUp(() { + calc = Calculator(); + }); + + test('adds two numbers correctly', () { + expect(calc.add(2, 3), equals(5)); + }); + + test('handles asynchronous operations', () async { + final result = await calc.fetchRemoteValue(); + expect(result, isNotNull); + expect(result, greaterThan(0)); + }); + }); +} +``` + +### Mocking with Mockito +Demonstrates configuring a mock object for dependency injection testing. + +```dart +import 'package:test/test.dart'; +import 'package:mockito/mockito.dart'; +import 'package:mockito/annotations.dart'; +import 'package:my_package/api_client.dart'; +import 'package:my_package/data_service.dart'; + +// Generate the mock using build_runner: dart run build_runner build +@GenerateNiceMocks([MockSpec()]) +import 'data_service_test.mocks.dart'; + +void main() { + group('DataService', () { + late MockApiClient mockApiClient; + late DataService dataService; + + setUp(() { + mockApiClient = MockApiClient(); + dataService = DataService(apiClient: mockApiClient); + }); + + test('returns parsed data on successful API call', () async { + // Configure the mock + when(mockApiClient.get('/data')).thenAnswer((_) async => '{"id": 1}'); + + // Execute the system under test + final result = await dataService.fetchData(); + + // Verify outcomes and interactions + expect(result.id, equals(1)); + verify(mockApiClient.get('/data')).called(1); + }); + }); +} +``` From efb3a48df6dbe7fd8feaa9ae8a755ecb3a3c251f Mon Sep 17 00:00:00 2001 From: Camille Simon Date: Fri, 12 Jun 2026 15:00:33 -0700 Subject: [PATCH 2/5] Add second set of skills --- .../skills/dart-collect-coverage | 1 + .../skills/dart-generate-test-mocks | 1 + .../skills/dart-run-static-analysis | 1 + .../skills/flutter-add-integration-test | 1 + .../camera_android_camerax/skills/grill-me | 1 + .../skills/receiving-code-review | 1 + .../skills/dart-collect-coverage/SKILL.md | 54 +++++++++++ .../skills/dart-generate-test-mocks/SKILL.md | 44 +++++++++ .../skills/dart-run-static-analysis/SKILL.md | 30 ++++++ .../flutter-add-integration-test/SKILL.md | 48 ++++++++++ packages/third_party/skills/grill-me/SKILL.md | 5 + .../skills/receiving-code-review/SKILL.md | 94 +++++++++++++++++++ 12 files changed, 281 insertions(+) create mode 120000 packages/camera/camera_android_camerax/skills/dart-collect-coverage create mode 120000 packages/camera/camera_android_camerax/skills/dart-generate-test-mocks create mode 120000 packages/camera/camera_android_camerax/skills/dart-run-static-analysis create mode 120000 packages/camera/camera_android_camerax/skills/flutter-add-integration-test create mode 120000 packages/camera/camera_android_camerax/skills/grill-me create mode 120000 packages/camera/camera_android_camerax/skills/receiving-code-review create mode 100644 packages/third_party/skills/dart-collect-coverage/SKILL.md create mode 100644 packages/third_party/skills/dart-generate-test-mocks/SKILL.md create mode 100644 packages/third_party/skills/dart-run-static-analysis/SKILL.md create mode 100644 packages/third_party/skills/flutter-add-integration-test/SKILL.md create mode 100644 packages/third_party/skills/grill-me/SKILL.md create mode 100644 packages/third_party/skills/receiving-code-review/SKILL.md diff --git a/packages/camera/camera_android_camerax/skills/dart-collect-coverage b/packages/camera/camera_android_camerax/skills/dart-collect-coverage new file mode 120000 index 000000000000..b6da5ac60be0 --- /dev/null +++ b/packages/camera/camera_android_camerax/skills/dart-collect-coverage @@ -0,0 +1 @@ +../../../../third_party/skills/dart-collect-coverage \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/skills/dart-generate-test-mocks b/packages/camera/camera_android_camerax/skills/dart-generate-test-mocks new file mode 120000 index 000000000000..bbc26dd31f36 --- /dev/null +++ b/packages/camera/camera_android_camerax/skills/dart-generate-test-mocks @@ -0,0 +1 @@ +../../../../third_party/skills/dart-generate-test-mocks \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/skills/dart-run-static-analysis b/packages/camera/camera_android_camerax/skills/dart-run-static-analysis new file mode 120000 index 000000000000..b91723a9bad2 --- /dev/null +++ b/packages/camera/camera_android_camerax/skills/dart-run-static-analysis @@ -0,0 +1 @@ +../../../../third_party/skills/dart-run-static-analysis \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/skills/flutter-add-integration-test b/packages/camera/camera_android_camerax/skills/flutter-add-integration-test new file mode 120000 index 000000000000..caed9350e626 --- /dev/null +++ b/packages/camera/camera_android_camerax/skills/flutter-add-integration-test @@ -0,0 +1 @@ +../../../../third_party/skills/flutter-add-integration-test \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/skills/grill-me b/packages/camera/camera_android_camerax/skills/grill-me new file mode 120000 index 000000000000..6ce842d52593 --- /dev/null +++ b/packages/camera/camera_android_camerax/skills/grill-me @@ -0,0 +1 @@ +../../../../third_party/skills/grill-me \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/skills/receiving-code-review b/packages/camera/camera_android_camerax/skills/receiving-code-review new file mode 120000 index 000000000000..b9170ccf97bc --- /dev/null +++ b/packages/camera/camera_android_camerax/skills/receiving-code-review @@ -0,0 +1 @@ +../../../../third_party/skills/receiving-code-review \ No newline at end of file diff --git a/packages/third_party/skills/dart-collect-coverage/SKILL.md b/packages/third_party/skills/dart-collect-coverage/SKILL.md new file mode 100644 index 000000000000..bc39ca9e9a2c --- /dev/null +++ b/packages/third_party/skills/dart-collect-coverage/SKILL.md @@ -0,0 +1,54 @@ +description: Collect coverage using the coverage packge and create an LCOV report +metadata: + model: models/gemini-3.1-pro-preview + last_modified: Fri, 24 Apr 2026 15:14:32 GMT +--- +# Implementing Dart and Flutter Test Coverage + +## Contents +- [Testing Fundamentals](#testing-fundamentals) +- [Coverage Directives](#coverage-directives) +- [Workflow: Configuring and Generating Coverage Reports](#workflow-configuring-and-generating-coverage-reports) +- [Workflow: Advanced Manual Coverage Collection](#workflow-advanced-manual-coverage-collection) +- [Examples](#examples) + +## Testing Fundamentals + +Structure your test suites using the standard Dart testing paradigms. Use `package:test` for Dart projects and `flutter_test` for Flutter projects. + +- **Unit Tests:** Verify individual functions, methods, or classes. +- **Component/Widget Tests:** Verify component behavior, layout, and interaction using mock objects (`package:mockito`). +- **Integration Tests:** Verify entire app flows on simulated or real devices. + +## Coverage Directives + +Exclude specific lines, blocks, or entire files from coverage metrics using inline comments. Pass the `--check-ignore` flag during formatting to enforce these directives. + +- Ignore a single line: `// coverage:ignore-line` +- Ignore a block of code: `// coverage:ignore-start` and `// coverage:ignore-end` +- Ignore an entire file: `// coverage:ignore-file` + +## Workflow: Configuring and Generating Coverage Reports + +Follow this sequential workflow to add the coverage package, execute tests, and generate an LCOV report. + +**Task Progress Checklist:** +- [ ] 1. Add `coverage` as a `dev_dependency`. +- [ ] 2. Execute the automated coverage script. +- [ ] 3. Validate the LCOV output. + +### 1. Add Dependencies +Add the `coverage` package as a `dev_dependency` to your project. Do not add it to standard dependencies. + +If working in a standard Dart project: +```bash +dart pub add dev:coverage +``` + +If working in a Flutter project: +```bash +flutter pub add dev:coverage +``` + +### 2. Collect Coverag + diff --git a/packages/third_party/skills/dart-generate-test-mocks/SKILL.md b/packages/third_party/skills/dart-generate-test-mocks/SKILL.md new file mode 100644 index 000000000000..61893db98dc9 --- /dev/null +++ b/packages/third_party/skills/dart-generate-test-mocks/SKILL.md @@ -0,0 +1,44 @@ +description: Define and generate mock objects for external dependencies using `package:mockito` and `build_runner`. Use when unit testing classes that depend on complex external services like APIs or databases. +metadata: + model: models/gemini-3.1-pro-preview + last_modified: Fri, 24 Apr 2026 15:13:58 GMT +--- +# Testing and Mocking Dart Applications + +## Contents +- [Structuring Code for Testability](#structuring-code-for-testability) +- [Managing Dependencies](#managing-dependencies) +- [Generating Mocks](#generating-mocks) +- [Implementing Unit Tests](#implementing-unit-tests) +- [Workflow: Creating and Running Mocked Tests](#workflow-creating-and-running-mocked-tests) +- [Examples](#examples) + +## Structuring Code for Testability +Design Dart classes to support dependency injection. Isolate complex external dependencies (like API clients or databases) so they can be replaced with mock objects during testing. + +- Inject external services (e.g., `http.Client`) through class constructors. +- Represent URLs strictly as `Uri` objects using `Uri.parse(string)`. +- Utilize Dart's object-oriented features (classes, mixins) to define clear interfaces for external interactions. + +## Managing Dependencies +Configure the `pubspec.yaml` file with the necessary testing and code generation packages. + +- Add runtime dependencies (e.g., `package:http`) using `dart pub add http`. +- Add testing dependencies using `dart pub add dev:test dev:mockito dev:build_runner`. +- Import HTTP libraries with a prefix to avoid namespace collisions: `import 'package:http/http.dart' as http;`. + +## Generating Mocks +Use `package:mockito` and `build_runner` to automatically generate mock classes for fixed scenarios and behavior verification. + +- Always use the `@GenerateNiceMocks` annotation (preferable to `@GenerateMocks` to avoid missing stub exceptions). +- Place the annotation in the test file, passing a list of `MockSpec()` objects. +- Import the generated file using the `.mocks.dart` extension. +- Execute `build_runner` to generate the mock files: `dart run build_runner build`. + +## Implementing Unit Tests +Isolate the system under test using the generated mock objects. Use `package:test` to structure the test suite. + +- **Stubbing:** Configure mock behavior before interacting with the system under test. + - Use `when(mock.method()).thenReturn(value)` for synchronous methods. + - **CRITICAL:** Always use `thenAnswer((_) async => value)` for methods + diff --git a/packages/third_party/skills/dart-run-static-analysis/SKILL.md b/packages/third_party/skills/dart-run-static-analysis/SKILL.md new file mode 100644 index 000000000000..d7748ad08e14 --- /dev/null +++ b/packages/third_party/skills/dart-run-static-analysis/SKILL.md @@ -0,0 +1,30 @@ +description: Execute `dart analyze` to identify warnings and errors, and use `dart fix --apply` to automatically resolve mechanical lint issues. Use during development to ensure code quality and before committing changes. +metadata: + model: models/gemini-3.1-pro-preview + last_modified: Fri, 24 Apr 2026 15:09:34 GMT +--- +# Analyzing and Fixing Dart Code + +## Contents +- [Analysis Configuration](#analysis-configuration) +- [Diagnostic Suppression](#diagnostic-suppression) +- [Workflow: Executing Static Analysis](#workflow-executing-static-analysis) +- [Workflow: Applying Automated Fixes](#workflow-applying-automated-fixes) +- [Examples](#examples) + +## Analysis Configuration + +Configure the Dart analyzer using the `analysis_options.yaml` file located at the package root. + +- **Base Configuration:** Always include a standard rule set (e.g., `package:lints/recommended.yaml` or `package:flutter_lints/flutter.yaml`) using the `include:` directive. +- **Strict Type Checks:** Enable strict type checks under the `analyzer: language:` node to prevent implicit downcasts and dynamic inferences. Set `strict-casts: true`, `strict-inference: true`, and `strict-raw-types: true`. +- **Linter Rules:** Explicitly enable or disable specific rules under the `linter: rules:` node. Use a key-value map (`rule_name: true/false`) when overriding included rules, or a list (`- rule_name`) when defining a fresh set. Do not mix list and map syntax in the same `rules` block. +- **Formatter Configuration:** Configure `dart format` behavior under the `formatter:` node. Set `page_width` (default 80) and `trailing_commas` (`automate` or `preserve`). +- **Analyzer Plugins:** Enable custom diagnostics by adding plugins under the `analyzer: plugins:` node. Ensure the plugin package is added as a `dev_dependency` in `pubspec.yaml`. + +## Diagnostic Suppression + +When a diagnostic (lint or warning) yields a false positive or applies to generated code, suppress it explicitly. + +- **File-level Exclusion:** Use the `analyzer: exclude:` node in `analysis_options.yaml` to exclude enti + diff --git a/packages/third_party/skills/flutter-add-integration-test/SKILL.md b/packages/third_party/skills/flutter-add-integration-test/SKILL.md new file mode 100644 index 000000000000..4e0b24fbac9e --- /dev/null +++ b/packages/third_party/skills/flutter-add-integration-test/SKILL.md @@ -0,0 +1,48 @@ +description: Configures Flutter Driver for app interaction and converts MCP actions into permanent integration tests. Use when adding integration testing to a project, exploring UI components via MCP, or automating user flows with the integration_test package. +metadata: + model: models/gemini-3.1-pro-preview + last_modified: Tue, 21 Apr 2026 18:29:20 GMT +--- +# Implementing Flutter Integration Tests + +## Contents +- [Project Setup and Dependencies](#project-setup-and-dependencies) +- [Interactive Exploration via MCP](#interactive-exploration-via-mcp) +- [Test Authoring Guidelines](#test-authoring-guidelines) +- [Execution and Profiling](#execution-and-profiling) +- [Workflow: End-to-End Integration Testing](#workflow-end-to-end-integration-testing) +- [Examples](#examples) + +## Project Setup and Dependencies + +Configure the project to support integration testing and Flutter Driver extensions. + +1. Add required development dependencies to `pubspec.yaml`: + ```bash + flutter pub add 'dev:integration_test:{"sdk":"flutter"}' + flutter pub add 'dev:flutter_test:{"sdk":"flutter"}' + ``` +2. Enable the Flutter Driver extension in your application entry point (typically `lib/main.dart` or a dedicated `lib/main_test.dart`): + - Import `package:flutter_driver/driver_extension.dart`. + - Call `enableFlutterDriverExtension();` before `runApp()`. +3. Add `Key` parameters (e.g., `ValueKey('login_button')`) to critical widgets in the application code to ensure reliable targeting during tests. + +## Interactive Exploration via MCP + +Use the Dart/Flutter MCP server tools to interactively explore and manipulate the application state before writing static tests. + +- **Launch**: Execute `launch_app` with `target: "lib/main_test.dart"` to start the application and acquire the DTD URI. +- **Inspect**: Execute `get_widget_tree` to discover available `Key`s, `Text` nodes, and widget `Type`s. +- **Interact**: Execute `tap`, `enter_text`, and `scroll` to simulate user flows. +- **Wait**: Always execute `waitFor` or verify state with `get_health` when navigating or triggering animations. +- **Troubleshoot Unmounted Widgets**: If a widget is not found in the tree, it may be lazily loaded in a `SliverList` or `ListView`. Execute `scroll` or `scrollIntoView` to force the widget to mount before interacting with it. + +## Test Authoring Guidelines + +Structure integration tests using the `flutter_test` API paradigm. + +- Create a dedicated `integration_test/` directory at the project root. +- Name all test files using the `_test.dart` convention. +- Initialize the binding by calling `IntegrationTestWidgetsFlutterBinding.ensureInitialized();` at the start of `main()`. +- Load the application UI using `await tester.pumpWidget(MyApp()); + diff --git a/packages/third_party/skills/grill-me/SKILL.md b/packages/third_party/skills/grill-me/SKILL.md new file mode 100644 index 000000000000..a7170e8e4524 --- /dev/null +++ b/packages/third_party/skills/grill-me/SKILL.md @@ -0,0 +1,5 @@ +description: Interview the user relentlessly about a plan or design until reaching shared understanding, resolving each branch of the decision tree. Use when user wants to stress-test a plan, get grilled on their design, or mentions "grill me". +--- + +Interview me relentlessly about every aspect of this plan until we reach a shared + diff --git a/packages/third_party/skills/receiving-code-review/SKILL.md b/packages/third_party/skills/receiving-code-review/SKILL.md new file mode 100644 index 000000000000..12a3a7cc82ef --- /dev/null +++ b/packages/third_party/skills/receiving-code-review/SKILL.md @@ -0,0 +1,94 @@ +description: Use when receiving code review feedback, before implementing suggestions, especially if feedback seems unclear or technically questionable - requires technical rigor and verification, not performative agreement or blind implementation +--- + +# Code Review Reception + +## Overview + +Code review requires technical evaluation, not emotional performance. + +**Core principle:** Verify before implementing. Ask before assuming. Technical correctness over social comfort. + +## The Response Pattern + +``` +WHEN receiving code review feedback: + +1. READ: Complete feedback without reacting +2. UNDERSTAND: Restate requirement in own words (or ask) +3. VERIFY: Check against codebase reality +4. EVALUATE: Technically sound for THIS codebase? +5. RESPOND: Technical acknowledgment or reasoned pushback +6. IMPLEMENT: One item at a time, test each +``` + +## Forbidden Responses + +**NEVER:** +- "You're absolutely right!" (explicit CLAUDE.md violation) +- "Great point!" / "Excellent feedback!" (performative) +- "Let me implement that now" (before verification) + +**INSTEAD:** +- Restate the technical requirement +- Ask clarifying questions +- Push back with technical reasoning if wrong +- Just start working (actions > words) + +## Handling Unclear Feedback + +``` +IF any item is unclear: + STOP - do not implement anything yet + ASK for clarification on unclear items + +WHY: Items may be related. Partial understanding = wrong implementation. +``` + +**Example:** +``` +your human partner: "Fix 1-6" +You understand 1,2,3,6. Unclear on 4,5. + +❌ WRONG: Implement 1,2,3,6 now, ask about 4,5 later +✅ RIGHT: "I understand items 1,2,3,6. Need clarification on 4 and 5 before proceeding." +``` + +## Source-Specific Handling + +### From your human partner +- **Trusted** - implement after understanding +- **Still ask** if scope unclear +- **No performative agreement** +- **Skip to action** or technical acknowledgment + +### From External Reviewers +``` +BEFORE implementing: + 1. Check: Technically correct for THIS codebase? + 2. Check: Breaks existing functionality? + 3. Check: Reason for current implementation? + 4. Check: Works on all platforms/versions? + 5. Check: Does reviewer understand full context? + +IF suggestion seems wrong: + Push back with technical reasoning + +IF can't easily verify: + Say so: "I can't verify this without [X]. Should I [investigate/ask/proceed]?" + +IF conflicts with your human partner's prior decisions: + Stop and discuss with your human partner first +``` + +**your human partner's rule:** "External feedback - be skeptical, but check carefully" + +## YAGNI Check for "Professional" Features + +``` +IF reviewer suggests "implementing properly": + grep codebase for actual usage + + IF unused: "This endpoint isn't called. Remove it (YAGNI)?" + IF used: Then + From fe30f721fb451fab960478ec1b3d18a92382680b Mon Sep 17 00:00:00 2001 From: Camille Simon Date: Mon, 15 Jun 2026 09:10:18 -0700 Subject: [PATCH 3/5] move skills to correct place --- {packages/third_party => third_party}/skills/android-cli/SKILL.md | 0 .../skills/android-cli/references/interact.md | 0 .../skills/android-cli/references/journeys.md | 0 .../skills/dart-add-unit-test/SKILL.md | 0 .../skills/dart-collect-coverage/SKILL.md | 0 .../skills/dart-generate-test-mocks/SKILL.md | 0 .../skills/dart-run-static-analysis/SKILL.md | 0 .../skills/flutter-add-integration-test/SKILL.md | 0 {packages/third_party => third_party}/skills/grill-me/SKILL.md | 0 .../skills/receiving-code-review/SKILL.md | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename {packages/third_party => third_party}/skills/android-cli/SKILL.md (100%) rename {packages/third_party => third_party}/skills/android-cli/references/interact.md (100%) rename {packages/third_party => third_party}/skills/android-cli/references/journeys.md (100%) rename {packages/third_party => third_party}/skills/dart-add-unit-test/SKILL.md (100%) rename {packages/third_party => third_party}/skills/dart-collect-coverage/SKILL.md (100%) rename {packages/third_party => third_party}/skills/dart-generate-test-mocks/SKILL.md (100%) rename {packages/third_party => third_party}/skills/dart-run-static-analysis/SKILL.md (100%) rename {packages/third_party => third_party}/skills/flutter-add-integration-test/SKILL.md (100%) rename {packages/third_party => third_party}/skills/grill-me/SKILL.md (100%) rename {packages/third_party => third_party}/skills/receiving-code-review/SKILL.md (100%) diff --git a/packages/third_party/skills/android-cli/SKILL.md b/third_party/skills/android-cli/SKILL.md similarity index 100% rename from packages/third_party/skills/android-cli/SKILL.md rename to third_party/skills/android-cli/SKILL.md diff --git a/packages/third_party/skills/android-cli/references/interact.md b/third_party/skills/android-cli/references/interact.md similarity index 100% rename from packages/third_party/skills/android-cli/references/interact.md rename to third_party/skills/android-cli/references/interact.md diff --git a/packages/third_party/skills/android-cli/references/journeys.md b/third_party/skills/android-cli/references/journeys.md similarity index 100% rename from packages/third_party/skills/android-cli/references/journeys.md rename to third_party/skills/android-cli/references/journeys.md diff --git a/packages/third_party/skills/dart-add-unit-test/SKILL.md b/third_party/skills/dart-add-unit-test/SKILL.md similarity index 100% rename from packages/third_party/skills/dart-add-unit-test/SKILL.md rename to third_party/skills/dart-add-unit-test/SKILL.md diff --git a/packages/third_party/skills/dart-collect-coverage/SKILL.md b/third_party/skills/dart-collect-coverage/SKILL.md similarity index 100% rename from packages/third_party/skills/dart-collect-coverage/SKILL.md rename to third_party/skills/dart-collect-coverage/SKILL.md diff --git a/packages/third_party/skills/dart-generate-test-mocks/SKILL.md b/third_party/skills/dart-generate-test-mocks/SKILL.md similarity index 100% rename from packages/third_party/skills/dart-generate-test-mocks/SKILL.md rename to third_party/skills/dart-generate-test-mocks/SKILL.md diff --git a/packages/third_party/skills/dart-run-static-analysis/SKILL.md b/third_party/skills/dart-run-static-analysis/SKILL.md similarity index 100% rename from packages/third_party/skills/dart-run-static-analysis/SKILL.md rename to third_party/skills/dart-run-static-analysis/SKILL.md diff --git a/packages/third_party/skills/flutter-add-integration-test/SKILL.md b/third_party/skills/flutter-add-integration-test/SKILL.md similarity index 100% rename from packages/third_party/skills/flutter-add-integration-test/SKILL.md rename to third_party/skills/flutter-add-integration-test/SKILL.md diff --git a/packages/third_party/skills/grill-me/SKILL.md b/third_party/skills/grill-me/SKILL.md similarity index 100% rename from packages/third_party/skills/grill-me/SKILL.md rename to third_party/skills/grill-me/SKILL.md diff --git a/packages/third_party/skills/receiving-code-review/SKILL.md b/third_party/skills/receiving-code-review/SKILL.md similarity index 100% rename from packages/third_party/skills/receiving-code-review/SKILL.md rename to third_party/skills/receiving-code-review/SKILL.md From a96d08d48a4fdfcc185c3bb23bcc1216d79f060a Mon Sep 17 00:00:00 2001 From: Camille Simon Date: Mon, 15 Jun 2026 10:08:16 -0700 Subject: [PATCH 4/5] npx install skills --- .../flutter-add-integration-test/SKILL.md | 163 ++++++++++++++ .../{ => .agents/skills}/android-cli/SKILL.md | 0 .../skills/android-cli/references/interact.md | 83 +++++++ .../skills/android-cli/references/journeys.md | 97 ++++++++ .../skills}/dart-add-unit-test/SKILL.md | 0 .../skills/dart-collect-coverage/SKILL.md | 141 ++++++++++++ .../skills/dart-generate-test-mocks/SKILL.md | 155 +++++++++++++ .../skills/dart-run-static-analysis/SKILL.md | 104 +++++++++ .../flutter-add-integration-test/SKILL.md | 163 ++++++++++++++ .../skills/.agents/skills/grill-me/SKILL.md | 10 + .../skills/receiving-code-review/SKILL.md | 213 ++++++++++++++++++ .../skills/android-cli/references/interact.md | 36 --- .../skills/android-cli/references/journeys.md | 50 ---- .../skills/dart-collect-coverage/SKILL.md | 54 ----- .../skills/dart-generate-test-mocks/SKILL.md | 44 ---- .../skills/dart-run-static-analysis/SKILL.md | 30 --- .../flutter-add-integration-test/SKILL.md | 48 ---- third_party/skills/grill-me/SKILL.md | 5 - .../skills/receiving-code-review/SKILL.md | 94 -------- third_party/skills/skills-lock.json | 47 ++++ 20 files changed, 1176 insertions(+), 361 deletions(-) create mode 100644 third_party/skills/.agents/skills/.agents/skills/flutter-add-integration-test/SKILL.md rename third_party/skills/{ => .agents/skills}/android-cli/SKILL.md (100%) create mode 100644 third_party/skills/.agents/skills/android-cli/references/interact.md create mode 100644 third_party/skills/.agents/skills/android-cli/references/journeys.md rename third_party/skills/{ => .agents/skills}/dart-add-unit-test/SKILL.md (100%) create mode 100644 third_party/skills/.agents/skills/dart-collect-coverage/SKILL.md create mode 100644 third_party/skills/.agents/skills/dart-generate-test-mocks/SKILL.md create mode 100644 third_party/skills/.agents/skills/dart-run-static-analysis/SKILL.md create mode 100644 third_party/skills/.agents/skills/flutter-add-integration-test/SKILL.md create mode 100644 third_party/skills/.agents/skills/grill-me/SKILL.md create mode 100644 third_party/skills/.agents/skills/receiving-code-review/SKILL.md delete mode 100644 third_party/skills/android-cli/references/interact.md delete mode 100644 third_party/skills/android-cli/references/journeys.md delete mode 100644 third_party/skills/dart-collect-coverage/SKILL.md delete mode 100644 third_party/skills/dart-generate-test-mocks/SKILL.md delete mode 100644 third_party/skills/dart-run-static-analysis/SKILL.md delete mode 100644 third_party/skills/flutter-add-integration-test/SKILL.md delete mode 100644 third_party/skills/grill-me/SKILL.md delete mode 100644 third_party/skills/receiving-code-review/SKILL.md create mode 100644 third_party/skills/skills-lock.json diff --git a/third_party/skills/.agents/skills/.agents/skills/flutter-add-integration-test/SKILL.md b/third_party/skills/.agents/skills/.agents/skills/flutter-add-integration-test/SKILL.md new file mode 100644 index 000000000000..60902f1aa315 --- /dev/null +++ b/third_party/skills/.agents/skills/.agents/skills/flutter-add-integration-test/SKILL.md @@ -0,0 +1,163 @@ +--- +name: flutter-add-integration-test +description: Configures Flutter Driver for app interaction and converts MCP actions into permanent integration tests. Use when adding integration testing to a project, exploring UI components via MCP, or automating user flows with the integration_test package. +metadata: + model: models/gemini-3.1-pro-preview + last_modified: Tue, 21 Apr 2026 18:29:20 GMT +--- +# Implementing Flutter Integration Tests + +## Contents +- [Project Setup and Dependencies](#project-setup-and-dependencies) +- [Interactive Exploration via MCP](#interactive-exploration-via-mcp) +- [Test Authoring Guidelines](#test-authoring-guidelines) +- [Execution and Profiling](#execution-and-profiling) +- [Workflow: End-to-End Integration Testing](#workflow-end-to-end-integration-testing) +- [Examples](#examples) + +## Project Setup and Dependencies + +Configure the project to support integration testing and Flutter Driver extensions. + +1. Add required development dependencies to `pubspec.yaml`: + ```bash + flutter pub add 'dev:integration_test:{"sdk":"flutter"}' + flutter pub add 'dev:flutter_test:{"sdk":"flutter"}' + ``` +2. Enable the Flutter Driver extension in your application entry point (typically `lib/main.dart` or a dedicated `lib/main_test.dart`): + - Import `package:flutter_driver/driver_extension.dart`. + - Call `enableFlutterDriverExtension();` before `runApp()`. +3. Add `Key` parameters (e.g., `ValueKey('login_button')`) to critical widgets in the application code to ensure reliable targeting during tests. + +## Interactive Exploration via MCP + +Use the Dart/Flutter MCP server tools to interactively explore and manipulate the application state before writing static tests. + +- **Launch**: Execute `launch_app` with `target: "lib/main_test.dart"` to start the application and acquire the DTD URI. +- **Inspect**: Execute `get_widget_tree` to discover available `Key`s, `Text` nodes, and widget `Type`s. +- **Interact**: Execute `tap`, `enter_text`, and `scroll` to simulate user flows. +- **Wait**: Always execute `waitFor` or verify state with `get_health` when navigating or triggering animations. +- **Troubleshoot Unmounted Widgets**: If a widget is not found in the tree, it may be lazily loaded in a `SliverList` or `ListView`. Execute `scroll` or `scrollIntoView` to force the widget to mount before interacting with it. + +## Test Authoring Guidelines + +Structure integration tests using the `flutter_test` API paradigm. + +- Create a dedicated `integration_test/` directory at the project root. +- Name all test files using the `_test.dart` convention. +- Initialize the binding by calling `IntegrationTestWidgetsFlutterBinding.ensureInitialized();` at the start of `main()`. +- Load the application UI using `await tester.pumpWidget(MyApp());`. +- Trigger frames and wait for animations to complete using `await tester.pumpAndSettle();` after interactions like `tester.tap()`. +- Assert widget visibility using `expect(find.byKey(ValueKey('foo')), findsOneWidget);` or `findsNothing`. +- Scroll to specific off-screen widgets using `await tester.scrollUntilVisible(itemFinder, 500.0, scrollable: listFinder);`. + +**Conditional Logic for Legacy `flutter_driver`:** +- If maintaining or migrating legacy `flutter_driver` tests, use `driver.waitFor()`, `driver.waitForAbsent()`, `driver.tap()`, and `driver.scroll()` instead of the `WidgetTester` APIs. + +## Execution and Profiling + +Execute tests using the `flutter drive` command. Require a host driver script located in `test_driver/integration_test.dart` that calls `integrationDriver()`. + +**Conditional Execution Targets:** +- **If testing on Chrome:** Launch `chromedriver --port=4444` in a separate terminal, then run: + `flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart -d chrome` +- **If testing headless web:** Run with `-d web-server`. +- **If testing on Android (Local):** Run `flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart`. +- **If testing on Firebase Test Lab (Android):** + 1. Build debug APK: `flutter build apk --debug` + 2. Build test APK: `./gradlew app:assembleAndroidTest` + 3. Upload both APKs to the Firebase Test Lab console. + +## Workflow: End-to-End Integration Testing + +Copy and follow this checklist to implement and verify integration tests. + +- [ ] **Task Progress: Setup** + - [ ] Add `integration_test` and `flutter_test` to `pubspec.yaml`. + - [ ] Inject `enableFlutterDriverExtension()` into the app entry point. + - [ ] Assign `ValueKey`s to target widgets. +- [ ] **Task Progress: Exploration** + - [ ] Run `launch_app` via MCP. + - [ ] Map the widget tree using `get_widget_tree`. + - [ ] Validate interaction paths using MCP tools (`tap`, `enter_text`). +- [ ] **Task Progress: Authoring** + - [ ] Create `integration_test/app_test.dart`. + - [ ] Write test cases using `WidgetTester` APIs. + - [ ] Create `test_driver/integration_test.dart` with `integrationDriver()`. +- [ ] **Task Progress: Execution & Feedback Loop** + - [ ] Run `flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart`. + - [ ] **Feedback Loop**: Review test output -> If `PumpAndSettleTimedOutException` occurs, check for infinite animations -> If widget not found, add `scrollUntilVisible` -> Re-run test until passing. + +## Examples + +### Standard Integration Test (`integration_test/app_test.dart`) + +```dart +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:my_app/main.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + group('End-to-end test', () { + testWidgets('tap on the floating action button, verify counter', (tester) async { + // Load app widget. + await tester.pumpWidget(const MyApp()); + + // Verify the counter starts at 0. + expect(find.text('0'), findsOneWidget); + + // Find the floating action button to tap on. + final fab = find.byKey(const ValueKey('increment')); + + // Emulate a tap on the floating action button. + await tester.tap(fab); + + // Trigger a frame and wait for animations. + await tester.pumpAndSettle(); + + // Verify the counter increments by 1. + expect(find.text('1'), findsOneWidget); + }); + }); +} +``` + +### Host Driver Script (`test_driver/integration_test.dart`) + +```dart +import 'package:integration_test/integration_test_driver.dart'; + +Future main() => integrationDriver(); +``` + +### Performance Profiling Driver Script (`test_driver/perf_driver.dart`) + +Use this driver script if you wrap your test actions in `binding.traceAction()` to capture performance metrics. + +```dart +import 'package:flutter_driver/flutter_driver.dart' as driver; +import 'package:integration_test/integration_test_driver.dart'; + +Future main() { + return integrationDriver( + responseDataCallback: (data) async { + if (data != null) { + final timeline = driver.Timeline.fromJson( + data['scrolling_timeline'] as Map, + ); + + final summary = driver.TimelineSummary.summarize(timeline); + + await summary.writeTimelineToFile( + 'scrolling_timeline', + pretty: true, + includeSummary: true, + ); + } + }, + ); +} +``` diff --git a/third_party/skills/android-cli/SKILL.md b/third_party/skills/.agents/skills/android-cli/SKILL.md similarity index 100% rename from third_party/skills/android-cli/SKILL.md rename to third_party/skills/.agents/skills/android-cli/SKILL.md diff --git a/third_party/skills/.agents/skills/android-cli/references/interact.md b/third_party/skills/.agents/skills/android-cli/references/interact.md new file mode 100644 index 000000000000..099e66ba2ee0 --- /dev/null +++ b/third_party/skills/.agents/skills/android-cli/references/interact.md @@ -0,0 +1,83 @@ +# Tools +Run `android layout --help` and `android screen --help`. + +## UI Dump +`android layout` returns a flat JSON list of the UI elements on screen. +`android layout --diff` returns a flat JSON list of the UI elements that have changed since the last call to `layout` or `layout --diff` + +Each JSON object represents a UI element in the Android app. The following properties may be present: +- `text` - any literal text the element contains +- `resourceId` - the Android resource id used to refer to the element +- `contentDesc` - a description of a UI element for use by accessibility tools +- `interactions` - the set of user interactions the element supports. May contain one or more of: `checkable`, `clickable`, `focusable`, `scrollable`, `long-clickable`, `password` +- `state` - the set of states the element is in. May contain one or more of `checked`, `focused`, `selected` +- `bounds` - the screen coordinates of the bounding rectangle of the element, in the format `[min X,min Y][max X, max Y]` +- `center` - the screen coordinates of the center of the element, in the format `[x,y]` +- `off-screen` - if true, the element is in the UI hierarchy but not visible; it may require scrolling to view. + +Use `layout` as a primary means of examining an Android app. Use `layout --diff` to focus on changes and to keep your context small. +Example: When entering digits into a calculator, use `layout --diff` to output only the digit readout element. + +`layout` may fail due to the app displaying a WebView or animation; in these cases, use `android screen --annotate` to inspect the app. +This failure will likely resolve after navigating away from the current screen. + +## Screenshot +`android screen capture -o ` saves a PNG of the current device screen to `` + +Use `screen capture` as a secondary means of examining an Android app +Examples: +- Understanding the content of an on-screen image +- Looking at a `WebView` (web content does not always appear in the ui dump) +- Trying to find a UI element by its visual appearance + +**IMPORTANT**: Always *VISUALLY* examine the PNG image returned from `android screen` BEFORE doing anything else. + +## Annotated Screenshot +`android screen capture --annotate -o ` +`android screen resolve --screen --string ` + +The `--annotate` command adds numerical labels and bounding boxes around UI elements. Use this command to locate UI elements that cannot +be located in the `layout` output. + +**IMPORTANT**: When using `android screen --annotate`, always *VISUALLY* examine the resulting PNG file. + +To refer to these labels in input commands, use `screen resolve` to convert labels into coordinates: + +`android screen resolve --screen --string "#3"` returns ` ` + +To save turns, you can combine shell commands: + +`adb shell input $(android screen resolve --screen screen.png --string "tap #34")` + +This command taps on region #34 from `screen.png` + +## Input +Use `adb shell input` for interacting with Android devices. +Refer to the `"interactions"` property of an element for what interactions can be performed on a particular element. + +Interact with UI elements with their `center` coordinate or their `bounds` coordinates: +```json +{ + "key": -248568265, + "class": "android.widget.Button", + "bounds": "[138,9][167,38]", + "center": "[152,23]" +} +``` +To tap on this button, you would execute `adb shell input tap 152 23`. This taps the center. + +```json +{ + "key": 12487234, + "class": "com.example.ui.ScrollableList", + "bounds": "[100,200][400,600]", + "center": "[250,400]" +} +``` +To scroll down on this list, you would execute `adb shell input swipe 250 400 600 500`. This swipes from the center to the bottom over 500ms. + +# Android Interaction Rules +1. Always ensure text input fields have `"focused"` in their `"state"` list before entering text +2. If an element has `"scrollable"` in its `"interactions"` list, try scrolling it when looking for missing UI elements +2. Always scroll slowly when executing scroll inputs. The 5th argument to `adb shell input swipe` controls scroll duration. +3. Content may take time to load; if a `layout` is missing information after you take an action, wait a few seconds, then perform `layout --diff` to see if anything changes. \ No newline at end of file diff --git a/third_party/skills/.agents/skills/android-cli/references/journeys.md b/third_party/skills/.agents/skills/android-cli/references/journeys.md new file mode 100644 index 000000000000..74545ddff54f --- /dev/null +++ b/third_party/skills/.agents/skills/android-cli/references/journeys.md @@ -0,0 +1,97 @@ +A journey is an XML-specified test of an Android app's behavior. It consists of a list of `` elements. For example: +```xml + + + A sample journey to illustrate the format + + + + Tap the "Home" icon + + + Verify that the app is on its Home screen + + + +``` + +Evaluate a journey by proceeding through the `` list in sequential order. Evaluate each `` block individually. +A journey succeeds if all elements in the `` list succeed. + +A journey is a test case for an app. The journey XML is the source of truth; if the app disagrees with the journey, the app has failed. +Additionally, if the app exits, crashes, or freezes, journey evaluation stops and the journey fails. + +**IMPORTANT** - Execute each step EXACTLY as written, and independently of other steps! If an action says to `"tap the first search result"`, +you MUST find the search results and tap the first one. Do this even if you believe you know the intent behind the action. + +## Taking Actions +Some `` elements specify UI interactions to perform on the running Android app. Perform the interaction and verify that the app does +not crash or behave in an unexpected manner. This is the *only* verification you should perform for an ``. + +If the interaction cannot be performed as specified, the journey fails. +Example: +```Click the red button``` +If you determine a red button is not present in the UI, the journey fails. + +If the text of an `` specifies a list of actions, break it into sub-actions and evaluate them individually: +Example: +```Search for soda and add the first result to the cart``` +This should be evaluated as: +``` +Search for soda +Add the first result to the cart +``` + +If an `` contains something that is not a specification for a UI interaction, alert the user that the journey is malformed and exit +early, specifying the error in question. + +## Verifying Expectations +`` elements that begin with "check" or "verify" specify expectations for the current state of the Android app. Determine the current +state of the app and check if the expectations are met. + +Determine the current state of the app by inspecting the current screen of the device without interacting with it. +Example: +```Check if "Switch 2" is visible on the screen``` +This requires only inspecting the current screen, not scrolling or interacting. If "Switch 2" is not currently visible, the action fails. + +If the expectations are not met, mark the `` as a failure and the journey evaluation ends. A single `` may contain +multiple expectations. +Example: +```Verify that the app is on the Home screen, the Home icon is blue, and the temperature is displayed``` +This `` fails if ANY of the following are false: +- The app is on the Home screen +- There is a Home icon, and it is blue +- A temperature is displayed + +## Handling failure +When running a journey, evaluate it as a test. Failure is acceptable, and often expected. Proper reporting of failures is the priority. + +Keep debugging and troubleshooting to a minimum; assume that tools are showing you the correct output every time. The goal is to determine +if the *current* Android app can correctly handle the *current* steps outlined in the journey. Suggestions for bug fixes, clarification, or +other improvements should be kept to journey evaluation summary at the end. + +## Summarizing +For each `` you evaluated, output JSON describing the results. + +``` +{ + "journey:", The name of the journey + "results:" [ + { + // A string containing the full text of the + "action": "Click the blue button, + // "PASSED" if the instruction was evaluated, "FAILED" if the instruction could not be evaluated, or "SKIPPED" if journey evaluation ended early because an instruction failed + "status": "PASSED", + // A list of the ADB commands executed while evaluating the instruction, + "commands": [ "adb input swipe 490 200 500 500 500", "adb input tap 45 920" ], + // Failure reasons, feedback, or other useful information + "comment": "The journey step doesn't specify that the button requires scrolling to see", + }, + { + "action": "The home screen is shown", + "status": "FAILED", + "comment": "The settings page was shown", + }, + ] +} +``` \ No newline at end of file diff --git a/third_party/skills/dart-add-unit-test/SKILL.md b/third_party/skills/.agents/skills/dart-add-unit-test/SKILL.md similarity index 100% rename from third_party/skills/dart-add-unit-test/SKILL.md rename to third_party/skills/.agents/skills/dart-add-unit-test/SKILL.md diff --git a/third_party/skills/.agents/skills/dart-collect-coverage/SKILL.md b/third_party/skills/.agents/skills/dart-collect-coverage/SKILL.md new file mode 100644 index 000000000000..60dad77533dc --- /dev/null +++ b/third_party/skills/.agents/skills/dart-collect-coverage/SKILL.md @@ -0,0 +1,141 @@ +--- +name: dart-collect-coverage +description: Collect coverage using the coverage packge and create an LCOV report +metadata: + model: models/gemini-3.1-pro-preview + last_modified: Fri, 24 Apr 2026 15:14:32 GMT +--- +# Implementing Dart and Flutter Test Coverage + +## Contents +- [Testing Fundamentals](#testing-fundamentals) +- [Coverage Directives](#coverage-directives) +- [Workflow: Configuring and Generating Coverage Reports](#workflow-configuring-and-generating-coverage-reports) +- [Workflow: Advanced Manual Coverage Collection](#workflow-advanced-manual-coverage-collection) +- [Examples](#examples) + +## Testing Fundamentals + +Structure your test suites using the standard Dart testing paradigms. Use `package:test` for Dart projects and `flutter_test` for Flutter projects. + +- **Unit Tests:** Verify individual functions, methods, or classes. +- **Component/Widget Tests:** Verify component behavior, layout, and interaction using mock objects (`package:mockito`). +- **Integration Tests:** Verify entire app flows on simulated or real devices. + +## Coverage Directives + +Exclude specific lines, blocks, or entire files from coverage metrics using inline comments. Pass the `--check-ignore` flag during formatting to enforce these directives. + +- Ignore a single line: `// coverage:ignore-line` +- Ignore a block of code: `// coverage:ignore-start` and `// coverage:ignore-end` +- Ignore an entire file: `// coverage:ignore-file` + +## Workflow: Configuring and Generating Coverage Reports + +Follow this sequential workflow to add the coverage package, execute tests, and generate an LCOV report. + +**Task Progress Checklist:** +- [ ] 1. Add `coverage` as a `dev_dependency`. +- [ ] 2. Execute the automated coverage script. +- [ ] 3. Validate the LCOV output. + +### 1. Add Dependencies +Add the `coverage` package as a `dev_dependency` to your project. Do not add it to standard dependencies. + +If working in a standard Dart project: +```bash +dart pub add dev:coverage +``` + +If working in a Flutter project: +```bash +flutter pub add dev:coverage +``` + +### 2. Collect Coverage and Generate LCOV +Use the bundled `test_with_coverage` script. This script automatically runs all tests, collects the JSON coverage data from the Dart VM, and formats it into an LCOV report. + +```bash +dart run coverage:test_with_coverage +``` +*Note: If working within a Dart workspace (monorepo), specify the test directories explicitly (e.g., `dart run coverage:test_with_coverage -- pkgs/foo/test pkgs/bar/test`).* + +### 3. Feedback Loop: Validate Output +**Run validator -> review errors -> fix:** +1. Verify that the `coverage/` directory was created in the project root. +2. Ensure `coverage/coverage.json` (raw data) and `coverage/lcov.info` (formatted report) exist. +3. If coverage is missing for specific files, ensure they are imported and executed by your test files, or add `// coverage:ignore-file` if they are intentionally excluded. + +## Workflow: Advanced Manual Coverage Collection + +If you require granular control over the VM service, isolate pausing, or need branch/function-level coverage, use the manual collection workflow. + +**Task Progress Checklist:** +- [ ] 1. Run tests with VM service enabled. +- [ ] 2. Collect raw JSON coverage. +- [ ] 3. Format JSON to LCOV. + +### 1. Run Tests with VM Service +Execute tests while pausing isolates on exit and exposing the VM service on a specific port (e.g., 8181). + +```bash +dart run --pause-isolates-on-exit --disable-service-auth-codes --enable-vm-service=8181 test & +``` + +### 2. Collect Raw Coverage +Extract the coverage data from the running VM service and output it to a JSON file. + +```bash +dart run coverage:collect_coverage --wait-paused --uri=http://127.0.0.1:8181/ -o coverage/coverage.json --resume-isolates +``` +*Optional: Append `--function-coverage` and `--branch-coverage` to gather deeper metrics (requires Dart VM 2.17.0+).* + +### 3. Format to LCOV +Convert the raw JSON data into the standard LCOV format. + +```bash +dart run coverage:format_coverage --packages=.dart_tool/package_config.json --lcov -i coverage/coverage.json -o coverage/lcov.info --check-ignore +``` + +## Examples + +### Example: `pubspec.yaml` Configuration +Ensure your `pubspec.yaml` reflects the `coverage` package strictly under `dev_dependencies`. + +```yaml +name: my_dart_app +environment: + sdk: ^3.0.0 + +dependencies: + path: ^1.8.0 + +dev_dependencies: + test: ^1.24.0 + coverage: ^1.15.0 +``` + +### Example: Applying Ignore Directives +Use ignore directives to prevent generated code or untestable edge cases from lowering coverage scores. + +```dart +// coverage:ignore-file +import 'package:meta/meta.dart'; + +class SystemConfig { + final String env; + + SystemConfig(this.env); + + // coverage:ignore-start + void legacyInit() { + print('Deprecated initialization'); + } + // coverage:ignore-end + + bool isProduction() { + if (env == 'prod') return true; + return false; // coverage:ignore-line + } +} +``` diff --git a/third_party/skills/.agents/skills/dart-generate-test-mocks/SKILL.md b/third_party/skills/.agents/skills/dart-generate-test-mocks/SKILL.md new file mode 100644 index 000000000000..fcd6d8b5e365 --- /dev/null +++ b/third_party/skills/.agents/skills/dart-generate-test-mocks/SKILL.md @@ -0,0 +1,155 @@ +--- +name: dart-generate-test-mocks +description: Define and generate mock objects for external dependencies using `package:mockito` and `build_runner`. Use when unit testing classes that depend on complex external services like APIs or databases. +metadata: + model: models/gemini-3.1-pro-preview + last_modified: Fri, 24 Apr 2026 15:13:58 GMT +--- +# Testing and Mocking Dart Applications + +## Contents +- [Structuring Code for Testability](#structuring-code-for-testability) +- [Managing Dependencies](#managing-dependencies) +- [Generating Mocks](#generating-mocks) +- [Implementing Unit Tests](#implementing-unit-tests) +- [Workflow: Creating and Running Mocked Tests](#workflow-creating-and-running-mocked-tests) +- [Examples](#examples) + +## Structuring Code for Testability +Design Dart classes to support dependency injection. Isolate complex external dependencies (like API clients or databases) so they can be replaced with mock objects during testing. + +- Inject external services (e.g., `http.Client`) through class constructors. +- Represent URLs strictly as `Uri` objects using `Uri.parse(string)`. +- Utilize Dart's object-oriented features (classes, mixins) to define clear interfaces for external interactions. + +## Managing Dependencies +Configure the `pubspec.yaml` file with the necessary testing and code generation packages. + +- Add runtime dependencies (e.g., `package:http`) using `dart pub add http`. +- Add testing dependencies using `dart pub add dev:test dev:mockito dev:build_runner`. +- Import HTTP libraries with a prefix to avoid namespace collisions: `import 'package:http/http.dart' as http;`. + +## Generating Mocks +Use `package:mockito` and `build_runner` to automatically generate mock classes for fixed scenarios and behavior verification. + +- Always use the `@GenerateNiceMocks` annotation (preferable to `@GenerateMocks` to avoid missing stub exceptions). +- Place the annotation in the test file, passing a list of `MockSpec()` objects. +- Import the generated file using the `.mocks.dart` extension. +- Execute `build_runner` to generate the mock files: `dart run build_runner build`. + +## Implementing Unit Tests +Isolate the system under test using the generated mock objects. Use `package:test` to structure the test suite. + +- **Stubbing:** Configure mock behavior before interacting with the system under test. + - Use `when(mock.method()).thenReturn(value)` for synchronous methods. + - **CRITICAL:** Always use `thenAnswer((_) async => value)` for methods returning a `Future` or `Stream`. Never use `thenReturn` for asynchronous returns. +- **Verification:** Assert that the system under test interacted with the mock object correctly. + - Use `verify(mock.method()).called(1)` to check exact invocation counts. + - Use argument matchers like `any`, `anyNamed`, or `captureAny` for flexible verification. + +## Workflow: Creating and Running Mocked Tests + +Use the following checklist to implement and verify mocked unit tests. + +### Task Progress +- [ ] 1. Identify the external dependency to mock (e.g., `http.Client`). +- [ ] 2. Inject the dependency into the target class constructor. +- [ ] 3. Create a test file (e.g., `target_test.dart`) and add `@GenerateNiceMocks([MockSpec()])`. +- [ ] 4. Add the `part` or `import` directive for the generated `.mocks.dart` file. +- [ ] 5. Run `dart run build_runner build` to generate the mock classes. +- [ ] 6. Write the test cases using `group()` and `test()`. +- [ ] 7. Stub required behaviors using `when()`. +- [ ] 8. Execute the target method. +- [ ] 9. Verify interactions using `verify()` and assert outcomes using `expect()`. +- [ ] 10. Run the test suite using `dart test`. + +### Feedback Loop: Test Failures +If tests fail or `build_runner` encounters errors: +1. **Run validator:** Execute `dart test` or `dart run build_runner build`. +2. **Review errors:** Check for missing stubs, mismatched argument matchers, or syntax errors in the generated files. +3. **Fix:** + - If a mock method throws an unexpected null error, ensure you used `@GenerateNiceMocks`. + - If an async stub throws an `ArgumentError`, change `thenReturn` to `thenAnswer`. + - If `build_runner` fails, ensure the `.mocks.dart` import matches the file name exactly. +4. Repeat until all tests pass. + +## Examples + +### High-Fidelity Mocking and Testing Example + +**1. System Under Test (`lib/api_service.dart`)** +```dart +import 'dart:convert'; +import 'package:http/http.dart' as http; + +class ApiService { + final http.Client client; + + ApiService(this.client); + + Future fetchData(String urlString) async { + final uri = Uri.parse(urlString); + final response = await client.get(uri); + + if (response.statusCode == 200) { + return jsonDecode(response.body)['data']; + } else { + throw Exception('Failed to load data'); + } + } +} +``` + +**2. Test Implementation (`test/api_service_test.dart`)** +```dart +import 'package:test/test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; +import 'package:http/http.dart' as http; +import 'package:my_app/api_service.dart'; + +// Generate the mock class for http.Client +@GenerateNiceMocks([MockSpec()]) +import 'api_service_test.mocks.dart'; + +void main() { + group('ApiService', () { + late ApiService apiService; + late MockClient mockHttpClient; + + setUp(() { + mockHttpClient = MockClient(); + apiService = ApiService(mockHttpClient); + }); + + test('returns data if the http call completes successfully', () async { + // Arrange: Stub the async HTTP GET request using thenAnswer + when(mockHttpClient.get(any)).thenAnswer( + (_) async => http.Response('{"data": "Success"}', 200), + ); + + // Act + final result = await apiService.fetchData('https://api.example.com/data'); + + // Assert + expect(result, 'Success'); + + // Verify the mock was called with the correct Uri + verify(mockHttpClient.get(Uri.parse('https://api.example.com/data'))).called(1); + }); + + test('throws an exception if the http call completes with an error', () { + // Arrange + when(mockHttpClient.get(any)).thenAnswer( + (_) async => http.Response('Not Found', 404), + ); + + // Act & Assert + expect( + apiService.fetchData('https://api.example.com/data'), + throwsException, + ); + }); + }); +} +``` diff --git a/third_party/skills/.agents/skills/dart-run-static-analysis/SKILL.md b/third_party/skills/.agents/skills/dart-run-static-analysis/SKILL.md new file mode 100644 index 000000000000..27ca6546684a --- /dev/null +++ b/third_party/skills/.agents/skills/dart-run-static-analysis/SKILL.md @@ -0,0 +1,104 @@ +--- +name: dart-run-static-analysis +description: Execute `dart analyze` to identify warnings and errors, and use `dart fix --apply` to automatically resolve mechanical lint issues. Use during development to ensure code quality and before committing changes. +metadata: + model: models/gemini-3.1-pro-preview + last_modified: Fri, 24 Apr 2026 15:09:34 GMT +--- +# Analyzing and Fixing Dart Code + +## Contents +- [Analysis Configuration](#analysis-configuration) +- [Diagnostic Suppression](#diagnostic-suppression) +- [Workflow: Executing Static Analysis](#workflow-executing-static-analysis) +- [Workflow: Applying Automated Fixes](#workflow-applying-automated-fixes) +- [Examples](#examples) + +## Analysis Configuration + +Configure the Dart analyzer using the `analysis_options.yaml` file located at the package root. + +- **Base Configuration:** Always include a standard rule set (e.g., `package:lints/recommended.yaml` or `package:flutter_lints/flutter.yaml`) using the `include:` directive. +- **Strict Type Checks:** Enable strict type checks under the `analyzer: language:` node to prevent implicit downcasts and dynamic inferences. Set `strict-casts: true`, `strict-inference: true`, and `strict-raw-types: true`. +- **Linter Rules:** Explicitly enable or disable specific rules under the `linter: rules:` node. Use a key-value map (`rule_name: true/false`) when overriding included rules, or a list (`- rule_name`) when defining a fresh set. Do not mix list and map syntax in the same `rules` block. +- **Formatter Configuration:** Configure `dart format` behavior under the `formatter:` node. Set `page_width` (default 80) and `trailing_commas` (`automate` or `preserve`). +- **Analyzer Plugins:** Enable custom diagnostics by adding plugins under the `analyzer: plugins:` node. Ensure the plugin package is added as a `dev_dependency` in `pubspec.yaml`. + +## Diagnostic Suppression + +When a diagnostic (lint or warning) yields a false positive or applies to generated code, suppress it explicitly. + +- **File-level Exclusion:** Use the `analyzer: exclude:` node in `analysis_options.yaml` to exclude entire files or directories (e.g., `**/*.g.dart`) using glob patterns. +- **File-level Suppression:** Add `// ignore_for_file: ` at the top of a Dart file to suppress specific diagnostics for the entire file. Use `// ignore_for_file: type=lint` to suppress all linter rules. +- **Line-level Suppression:** Add `// ignore: ` on the line directly above the offending code, or appended to the end of the offending line. +- **Pubspec Suppression:** Add `# ignore: ` above the offending line in `pubspec.yaml` files (e.g., `# ignore: sort_pub_dependencies`). +- **Plugin Diagnostics:** Prefix the diagnostic code with the plugin name when suppressing plugin-specific issues (e.g., `// ignore: some_plugin/some_code`). + +## Workflow: Executing Static Analysis + +Use this workflow to identify type-related bugs, style violations, and potential runtime errors. + +**Task Progress:** +- [ ] 1. Verify `analysis_options.yaml` exists at the project root. +- [ ] 2. Run the analyzer using the `analyze_files` MCP tool (if available) or the CLI command `dart analyze `. +- [ ] 3. Review the diagnostic output. +- [ ] 4. If info-level issues must be treated as failures, append the `--fatal-infos` flag. +- [ ] 5. Resolve reported errors manually or proceed to the Automated Fixes workflow. + +## Workflow: Applying Automated Fixes + +Use this workflow to resolve outdated API usages, apply quick fixes, and migrate code (e.g., Dart 3 migrations). + +**Task Progress:** +- [ ] 1. Execute a dry run to preview proposed changes using the `dart_fix` MCP tool or CLI command `dart fix --dry-run`. +- [ ] 2. Review the proposed fixes to ensure they align with the intended architecture. +- [ ] 3. If additional fixes are required, verify that the corresponding linter rules are enabled in `analysis_options.yaml`. +- [ ] 4. Apply the fixes using the `dart_fix` MCP tool or CLI command `dart fix --apply`. +- [ ] 5. Format the modified code using the `dart_format` MCP tool or CLI command `dart format .`. +- [ ] 6. Run the static analysis workflow to verify all diagnostics are resolved. + +## Examples + +### Comprehensive `analysis_options.yaml` + +```yaml +include: package:flutter_lints/recommended.yaml + +analyzer: + exclude: + - "**/*.g.dart" + - "lib/generated/**" + language: + strict-casts: true + strict-inference: true + strict-raw-types: true + errors: + todo: ignore + invalid_assignment: warning + missing_return: error + +linter: + rules: + avoid_shadowing_type_parameters: false + await_only_futures: true + use_super_parameters: true + +formatter: + page_width: 100 + trailing_commas: preserve +``` + +### Inline Diagnostic Suppression + +```dart +// Suppress for the entire file +// ignore_for_file: unused_local_variable, dead_code + +void processData() { + // Suppress for a specific line + // ignore: invalid_assignment + int x = ''; + + const y = 10; // ignore: constant_identifier_names +} +``` diff --git a/third_party/skills/.agents/skills/flutter-add-integration-test/SKILL.md b/third_party/skills/.agents/skills/flutter-add-integration-test/SKILL.md new file mode 100644 index 000000000000..60902f1aa315 --- /dev/null +++ b/third_party/skills/.agents/skills/flutter-add-integration-test/SKILL.md @@ -0,0 +1,163 @@ +--- +name: flutter-add-integration-test +description: Configures Flutter Driver for app interaction and converts MCP actions into permanent integration tests. Use when adding integration testing to a project, exploring UI components via MCP, or automating user flows with the integration_test package. +metadata: + model: models/gemini-3.1-pro-preview + last_modified: Tue, 21 Apr 2026 18:29:20 GMT +--- +# Implementing Flutter Integration Tests + +## Contents +- [Project Setup and Dependencies](#project-setup-and-dependencies) +- [Interactive Exploration via MCP](#interactive-exploration-via-mcp) +- [Test Authoring Guidelines](#test-authoring-guidelines) +- [Execution and Profiling](#execution-and-profiling) +- [Workflow: End-to-End Integration Testing](#workflow-end-to-end-integration-testing) +- [Examples](#examples) + +## Project Setup and Dependencies + +Configure the project to support integration testing and Flutter Driver extensions. + +1. Add required development dependencies to `pubspec.yaml`: + ```bash + flutter pub add 'dev:integration_test:{"sdk":"flutter"}' + flutter pub add 'dev:flutter_test:{"sdk":"flutter"}' + ``` +2. Enable the Flutter Driver extension in your application entry point (typically `lib/main.dart` or a dedicated `lib/main_test.dart`): + - Import `package:flutter_driver/driver_extension.dart`. + - Call `enableFlutterDriverExtension();` before `runApp()`. +3. Add `Key` parameters (e.g., `ValueKey('login_button')`) to critical widgets in the application code to ensure reliable targeting during tests. + +## Interactive Exploration via MCP + +Use the Dart/Flutter MCP server tools to interactively explore and manipulate the application state before writing static tests. + +- **Launch**: Execute `launch_app` with `target: "lib/main_test.dart"` to start the application and acquire the DTD URI. +- **Inspect**: Execute `get_widget_tree` to discover available `Key`s, `Text` nodes, and widget `Type`s. +- **Interact**: Execute `tap`, `enter_text`, and `scroll` to simulate user flows. +- **Wait**: Always execute `waitFor` or verify state with `get_health` when navigating or triggering animations. +- **Troubleshoot Unmounted Widgets**: If a widget is not found in the tree, it may be lazily loaded in a `SliverList` or `ListView`. Execute `scroll` or `scrollIntoView` to force the widget to mount before interacting with it. + +## Test Authoring Guidelines + +Structure integration tests using the `flutter_test` API paradigm. + +- Create a dedicated `integration_test/` directory at the project root. +- Name all test files using the `_test.dart` convention. +- Initialize the binding by calling `IntegrationTestWidgetsFlutterBinding.ensureInitialized();` at the start of `main()`. +- Load the application UI using `await tester.pumpWidget(MyApp());`. +- Trigger frames and wait for animations to complete using `await tester.pumpAndSettle();` after interactions like `tester.tap()`. +- Assert widget visibility using `expect(find.byKey(ValueKey('foo')), findsOneWidget);` or `findsNothing`. +- Scroll to specific off-screen widgets using `await tester.scrollUntilVisible(itemFinder, 500.0, scrollable: listFinder);`. + +**Conditional Logic for Legacy `flutter_driver`:** +- If maintaining or migrating legacy `flutter_driver` tests, use `driver.waitFor()`, `driver.waitForAbsent()`, `driver.tap()`, and `driver.scroll()` instead of the `WidgetTester` APIs. + +## Execution and Profiling + +Execute tests using the `flutter drive` command. Require a host driver script located in `test_driver/integration_test.dart` that calls `integrationDriver()`. + +**Conditional Execution Targets:** +- **If testing on Chrome:** Launch `chromedriver --port=4444` in a separate terminal, then run: + `flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart -d chrome` +- **If testing headless web:** Run with `-d web-server`. +- **If testing on Android (Local):** Run `flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart`. +- **If testing on Firebase Test Lab (Android):** + 1. Build debug APK: `flutter build apk --debug` + 2. Build test APK: `./gradlew app:assembleAndroidTest` + 3. Upload both APKs to the Firebase Test Lab console. + +## Workflow: End-to-End Integration Testing + +Copy and follow this checklist to implement and verify integration tests. + +- [ ] **Task Progress: Setup** + - [ ] Add `integration_test` and `flutter_test` to `pubspec.yaml`. + - [ ] Inject `enableFlutterDriverExtension()` into the app entry point. + - [ ] Assign `ValueKey`s to target widgets. +- [ ] **Task Progress: Exploration** + - [ ] Run `launch_app` via MCP. + - [ ] Map the widget tree using `get_widget_tree`. + - [ ] Validate interaction paths using MCP tools (`tap`, `enter_text`). +- [ ] **Task Progress: Authoring** + - [ ] Create `integration_test/app_test.dart`. + - [ ] Write test cases using `WidgetTester` APIs. + - [ ] Create `test_driver/integration_test.dart` with `integrationDriver()`. +- [ ] **Task Progress: Execution & Feedback Loop** + - [ ] Run `flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart`. + - [ ] **Feedback Loop**: Review test output -> If `PumpAndSettleTimedOutException` occurs, check for infinite animations -> If widget not found, add `scrollUntilVisible` -> Re-run test until passing. + +## Examples + +### Standard Integration Test (`integration_test/app_test.dart`) + +```dart +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:my_app/main.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + group('End-to-end test', () { + testWidgets('tap on the floating action button, verify counter', (tester) async { + // Load app widget. + await tester.pumpWidget(const MyApp()); + + // Verify the counter starts at 0. + expect(find.text('0'), findsOneWidget); + + // Find the floating action button to tap on. + final fab = find.byKey(const ValueKey('increment')); + + // Emulate a tap on the floating action button. + await tester.tap(fab); + + // Trigger a frame and wait for animations. + await tester.pumpAndSettle(); + + // Verify the counter increments by 1. + expect(find.text('1'), findsOneWidget); + }); + }); +} +``` + +### Host Driver Script (`test_driver/integration_test.dart`) + +```dart +import 'package:integration_test/integration_test_driver.dart'; + +Future main() => integrationDriver(); +``` + +### Performance Profiling Driver Script (`test_driver/perf_driver.dart`) + +Use this driver script if you wrap your test actions in `binding.traceAction()` to capture performance metrics. + +```dart +import 'package:flutter_driver/flutter_driver.dart' as driver; +import 'package:integration_test/integration_test_driver.dart'; + +Future main() { + return integrationDriver( + responseDataCallback: (data) async { + if (data != null) { + final timeline = driver.Timeline.fromJson( + data['scrolling_timeline'] as Map, + ); + + final summary = driver.TimelineSummary.summarize(timeline); + + await summary.writeTimelineToFile( + 'scrolling_timeline', + pretty: true, + includeSummary: true, + ); + } + }, + ); +} +``` diff --git a/third_party/skills/.agents/skills/grill-me/SKILL.md b/third_party/skills/.agents/skills/grill-me/SKILL.md new file mode 100644 index 000000000000..bd04394c675e --- /dev/null +++ b/third_party/skills/.agents/skills/grill-me/SKILL.md @@ -0,0 +1,10 @@ +--- +name: grill-me +description: Interview the user relentlessly about a plan or design until reaching shared understanding, resolving each branch of the decision tree. Use when user wants to stress-test a plan, get grilled on their design, or mentions "grill me". +--- + +Interview me relentlessly about every aspect of this plan until we reach a shared understanding. Walk down each branch of the design tree, resolving dependencies between decisions one-by-one. For each question, provide your recommended answer. + +Ask the questions one at a time. + +If a question can be answered by exploring the codebase, explore the codebase instead. diff --git a/third_party/skills/.agents/skills/receiving-code-review/SKILL.md b/third_party/skills/.agents/skills/receiving-code-review/SKILL.md new file mode 100644 index 000000000000..4ea72cdf014d --- /dev/null +++ b/third_party/skills/.agents/skills/receiving-code-review/SKILL.md @@ -0,0 +1,213 @@ +--- +name: receiving-code-review +description: Use when receiving code review feedback, before implementing suggestions, especially if feedback seems unclear or technically questionable - requires technical rigor and verification, not performative agreement or blind implementation +--- + +# Code Review Reception + +## Overview + +Code review requires technical evaluation, not emotional performance. + +**Core principle:** Verify before implementing. Ask before assuming. Technical correctness over social comfort. + +## The Response Pattern + +``` +WHEN receiving code review feedback: + +1. READ: Complete feedback without reacting +2. UNDERSTAND: Restate requirement in own words (or ask) +3. VERIFY: Check against codebase reality +4. EVALUATE: Technically sound for THIS codebase? +5. RESPOND: Technical acknowledgment or reasoned pushback +6. IMPLEMENT: One item at a time, test each +``` + +## Forbidden Responses + +**NEVER:** +- "You're absolutely right!" (explicit CLAUDE.md violation) +- "Great point!" / "Excellent feedback!" (performative) +- "Let me implement that now" (before verification) + +**INSTEAD:** +- Restate the technical requirement +- Ask clarifying questions +- Push back with technical reasoning if wrong +- Just start working (actions > words) + +## Handling Unclear Feedback + +``` +IF any item is unclear: + STOP - do not implement anything yet + ASK for clarification on unclear items + +WHY: Items may be related. Partial understanding = wrong implementation. +``` + +**Example:** +``` +your human partner: "Fix 1-6" +You understand 1,2,3,6. Unclear on 4,5. + +❌ WRONG: Implement 1,2,3,6 now, ask about 4,5 later +✅ RIGHT: "I understand items 1,2,3,6. Need clarification on 4 and 5 before proceeding." +``` + +## Source-Specific Handling + +### From your human partner +- **Trusted** - implement after understanding +- **Still ask** if scope unclear +- **No performative agreement** +- **Skip to action** or technical acknowledgment + +### From External Reviewers +``` +BEFORE implementing: + 1. Check: Technically correct for THIS codebase? + 2. Check: Breaks existing functionality? + 3. Check: Reason for current implementation? + 4. Check: Works on all platforms/versions? + 5. Check: Does reviewer understand full context? + +IF suggestion seems wrong: + Push back with technical reasoning + +IF can't easily verify: + Say so: "I can't verify this without [X]. Should I [investigate/ask/proceed]?" + +IF conflicts with your human partner's prior decisions: + Stop and discuss with your human partner first +``` + +**your human partner's rule:** "External feedback - be skeptical, but check carefully" + +## YAGNI Check for "Professional" Features + +``` +IF reviewer suggests "implementing properly": + grep codebase for actual usage + + IF unused: "This endpoint isn't called. Remove it (YAGNI)?" + IF used: Then implement properly +``` + +**your human partner's rule:** "You and reviewer both report to me. If we don't need this feature, don't add it." + +## Implementation Order + +``` +FOR multi-item feedback: + 1. Clarify anything unclear FIRST + 2. Then implement in this order: + - Blocking issues (breaks, security) + - Simple fixes (typos, imports) + - Complex fixes (refactoring, logic) + 3. Test each fix individually + 4. Verify no regressions +``` + +## When To Push Back + +Push back when: +- Suggestion breaks existing functionality +- Reviewer lacks full context +- Violates YAGNI (unused feature) +- Technically incorrect for this stack +- Legacy/compatibility reasons exist +- Conflicts with your human partner's architectural decisions + +**How to push back:** +- Use technical reasoning, not defensiveness +- Ask specific questions +- Reference working tests/code +- Involve your human partner if architectural + +**Signal if uncomfortable pushing back out loud:** "Strange things are afoot at the Circle K" + +## Acknowledging Correct Feedback + +When feedback IS correct: +``` +✅ "Fixed. [Brief description of what changed]" +✅ "Good catch - [specific issue]. Fixed in [location]." +✅ [Just fix it and show in the code] + +❌ "You're absolutely right!" +❌ "Great point!" +❌ "Thanks for catching that!" +❌ "Thanks for [anything]" +❌ ANY gratitude expression +``` + +**Why no thanks:** Actions speak. Just fix it. The code itself shows you heard the feedback. + +**If you catch yourself about to write "Thanks":** DELETE IT. State the fix instead. + +## Gracefully Correcting Your Pushback + +If you pushed back and were wrong: +``` +✅ "You were right - I checked [X] and it does [Y]. Implementing now." +✅ "Verified this and you're correct. My initial understanding was wrong because [reason]. Fixing." + +❌ Long apology +❌ Defending why you pushed back +❌ Over-explaining +``` + +State the correction factually and move on. + +## Common Mistakes + +| Mistake | Fix | +|---------|-----| +| Performative agreement | State requirement or just act | +| Blind implementation | Verify against codebase first | +| Batch without testing | One at a time, test each | +| Assuming reviewer is right | Check if breaks things | +| Avoiding pushback | Technical correctness > comfort | +| Partial implementation | Clarify all items first | +| Can't verify, proceed anyway | State limitation, ask for direction | + +## Real Examples + +**Performative Agreement (Bad):** +``` +Reviewer: "Remove legacy code" +❌ "You're absolutely right! Let me remove that..." +``` + +**Technical Verification (Good):** +``` +Reviewer: "Remove legacy code" +✅ "Checking... build target is 10.15+, this API needs 13+. Need legacy for backward compat. Current impl has wrong bundle ID - fix it or drop pre-13 support?" +``` + +**YAGNI (Good):** +``` +Reviewer: "Implement proper metrics tracking with database, date filters, CSV export" +✅ "Grepped codebase - nothing calls this endpoint. Remove it (YAGNI)? Or is there usage I'm missing?" +``` + +**Unclear Item (Good):** +``` +your human partner: "Fix items 1-6" +You understand 1,2,3,6. Unclear on 4,5. +✅ "Understand 1,2,3,6. Need clarification on 4 and 5 before implementing." +``` + +## GitHub Thread Replies + +When replying to inline review comments on GitHub, reply in the comment thread (`gh api repos/{owner}/{repo}/pulls/{pr}/comments/{id}/replies`), not as a top-level PR comment. + +## The Bottom Line + +**External feedback = suggestions to evaluate, not orders to follow.** + +Verify. Question. Then implement. + +No performative agreement. Technical rigor always. diff --git a/third_party/skills/android-cli/references/interact.md b/third_party/skills/android-cli/references/interact.md deleted file mode 100644 index 3e37f4ac8d60..000000000000 --- a/third_party/skills/android-cli/references/interact.md +++ /dev/null @@ -1,36 +0,0 @@ -Title: Live Content - -Description: Fetched live - -Source: https://raw.githubusercontent.com/android/skills/main/devtools/android-cli/references/interact.md - ---- - -# Tools -Run `android layout --help` and `android screen --help`. - -## UI Dump -`android layout` returns a flat JSON list of the UI elements on screen. -`android layout --diff` returns a flat JSON list of the UI elements that have changed since the last call to `layout` or `layout --diff` - -Each JSON object represents a UI element in the Android app. The following properties may be present: -- `text` - any literal text the element contains -- `resourceId` - the Android resource id used to refer to the element -- `contentDesc` - a description of a UI element for use by accessibility tools -- `interactions` - the set of user interactions the element supports. May contain one or more of: `checkable`, `clickable`, `focusable`, `scrollable`, `long-clickable`, `password` -- `state` - the set of states the element is in. May contain one or more of `checked`, `focused`, `selected` -- `bounds` - the screen coordinates of the bounding rectangle of the element, in the format `[min X,min Y][max X, max Y]` -- `center` - the screen coordinates of the center of the element, in the format `[x,y]` -- `off-screen` - if true, the element is in the UI hierarchy but not visible; it may require scrolling to view. - -Use `layout` as a primary means of examining an Android app. Use `layout --diff` to focus on changes and to keep your context small. -Example: When entering digits into a calculator, use `layout --diff` to output only the digit readout element. - -`layout` may fail due to the app displaying a WebView or animation; in these cases, use `android screen --annotate` to inspect the app. -This failure will likely resolve after navigating away from the current screen. - -## Screenshot -`android screen capture -o ` saves a PNG of the current device screen to `` - -Use `screen capture` as a secondary me - diff --git a/third_party/skills/android-cli/references/journeys.md b/third_party/skills/android-cli/references/journeys.md deleted file mode 100644 index 7ffc26fa6919..000000000000 --- a/third_party/skills/android-cli/references/journeys.md +++ /dev/null @@ -1,50 +0,0 @@ -Title: Live Content - -Description: Fetched live - -Source: https://raw.githubusercontent.com/android/skills/main/devtools/android-cli/references/journeys.md - ---- - -A journey is an XML-specified test of an Android app's behavior. It consists of a list of `` elements. For example: -```xml - - - A sample journey to illustrate the format - - - - Tap the "Home" icon - - - Verify that the app is on its Home screen - - - -``` - -Evaluate a journey by proceeding through the `` list in sequential order. Evaluate each `` block individually. -A journey succeeds if all elements in the `` list succeed. - -A journey is a test case for an app. The journey XML is the source of truth; if the app disagrees with the journey, the app has failed. -Additionally, if the app exits, crashes, or freezes, journey evaluation stops and the journey fails. - -**IMPORTANT** - Execute each step EXACTLY as written, and independently of other steps! If an action says to `"tap the first search result"`, -you MUST find the search results and tap the first one. Do this even if you believe you know the intent behind the action. - -## Taking Actions -Some `` elements specify UI interactions to perform on the running Android app. Perform the interaction and verify that the app does -not crash or behave in an unexpected manner. This is the *only* verification you should perform for an ``. - -If the interaction cannot be performed as specified, the journey fails. -Example: -```Click the red button``` -If you determine a red button is not present in the UI, the journey fails. - -If the text of an `` specifies a list of actions, break it into sub-actions and evaluate them individually: -Example: -```Search for soda and add the first result to the cart``` -This should be evaluated as: -``` -Search for soda()` objects. -- Import the generated file using the `.mocks.dart` extension. -- Execute `build_runner` to generate the mock files: `dart run build_runner build`. - -## Implementing Unit Tests -Isolate the system under test using the generated mock objects. Use `package:test` to structure the test suite. - -- **Stubbing:** Configure mock behavior before interacting with the system under test. - - Use `when(mock.method()).thenReturn(value)` for synchronous methods. - - **CRITICAL:** Always use `thenAnswer((_) async => value)` for methods - diff --git a/third_party/skills/dart-run-static-analysis/SKILL.md b/third_party/skills/dart-run-static-analysis/SKILL.md deleted file mode 100644 index d7748ad08e14..000000000000 --- a/third_party/skills/dart-run-static-analysis/SKILL.md +++ /dev/null @@ -1,30 +0,0 @@ -description: Execute `dart analyze` to identify warnings and errors, and use `dart fix --apply` to automatically resolve mechanical lint issues. Use during development to ensure code quality and before committing changes. -metadata: - model: models/gemini-3.1-pro-preview - last_modified: Fri, 24 Apr 2026 15:09:34 GMT ---- -# Analyzing and Fixing Dart Code - -## Contents -- [Analysis Configuration](#analysis-configuration) -- [Diagnostic Suppression](#diagnostic-suppression) -- [Workflow: Executing Static Analysis](#workflow-executing-static-analysis) -- [Workflow: Applying Automated Fixes](#workflow-applying-automated-fixes) -- [Examples](#examples) - -## Analysis Configuration - -Configure the Dart analyzer using the `analysis_options.yaml` file located at the package root. - -- **Base Configuration:** Always include a standard rule set (e.g., `package:lints/recommended.yaml` or `package:flutter_lints/flutter.yaml`) using the `include:` directive. -- **Strict Type Checks:** Enable strict type checks under the `analyzer: language:` node to prevent implicit downcasts and dynamic inferences. Set `strict-casts: true`, `strict-inference: true`, and `strict-raw-types: true`. -- **Linter Rules:** Explicitly enable or disable specific rules under the `linter: rules:` node. Use a key-value map (`rule_name: true/false`) when overriding included rules, or a list (`- rule_name`) when defining a fresh set. Do not mix list and map syntax in the same `rules` block. -- **Formatter Configuration:** Configure `dart format` behavior under the `formatter:` node. Set `page_width` (default 80) and `trailing_commas` (`automate` or `preserve`). -- **Analyzer Plugins:** Enable custom diagnostics by adding plugins under the `analyzer: plugins:` node. Ensure the plugin package is added as a `dev_dependency` in `pubspec.yaml`. - -## Diagnostic Suppression - -When a diagnostic (lint or warning) yields a false positive or applies to generated code, suppress it explicitly. - -- **File-level Exclusion:** Use the `analyzer: exclude:` node in `analysis_options.yaml` to exclude enti - diff --git a/third_party/skills/flutter-add-integration-test/SKILL.md b/third_party/skills/flutter-add-integration-test/SKILL.md deleted file mode 100644 index 4e0b24fbac9e..000000000000 --- a/third_party/skills/flutter-add-integration-test/SKILL.md +++ /dev/null @@ -1,48 +0,0 @@ -description: Configures Flutter Driver for app interaction and converts MCP actions into permanent integration tests. Use when adding integration testing to a project, exploring UI components via MCP, or automating user flows with the integration_test package. -metadata: - model: models/gemini-3.1-pro-preview - last_modified: Tue, 21 Apr 2026 18:29:20 GMT ---- -# Implementing Flutter Integration Tests - -## Contents -- [Project Setup and Dependencies](#project-setup-and-dependencies) -- [Interactive Exploration via MCP](#interactive-exploration-via-mcp) -- [Test Authoring Guidelines](#test-authoring-guidelines) -- [Execution and Profiling](#execution-and-profiling) -- [Workflow: End-to-End Integration Testing](#workflow-end-to-end-integration-testing) -- [Examples](#examples) - -## Project Setup and Dependencies - -Configure the project to support integration testing and Flutter Driver extensions. - -1. Add required development dependencies to `pubspec.yaml`: - ```bash - flutter pub add 'dev:integration_test:{"sdk":"flutter"}' - flutter pub add 'dev:flutter_test:{"sdk":"flutter"}' - ``` -2. Enable the Flutter Driver extension in your application entry point (typically `lib/main.dart` or a dedicated `lib/main_test.dart`): - - Import `package:flutter_driver/driver_extension.dart`. - - Call `enableFlutterDriverExtension();` before `runApp()`. -3. Add `Key` parameters (e.g., `ValueKey('login_button')`) to critical widgets in the application code to ensure reliable targeting during tests. - -## Interactive Exploration via MCP - -Use the Dart/Flutter MCP server tools to interactively explore and manipulate the application state before writing static tests. - -- **Launch**: Execute `launch_app` with `target: "lib/main_test.dart"` to start the application and acquire the DTD URI. -- **Inspect**: Execute `get_widget_tree` to discover available `Key`s, `Text` nodes, and widget `Type`s. -- **Interact**: Execute `tap`, `enter_text`, and `scroll` to simulate user flows. -- **Wait**: Always execute `waitFor` or verify state with `get_health` when navigating or triggering animations. -- **Troubleshoot Unmounted Widgets**: If a widget is not found in the tree, it may be lazily loaded in a `SliverList` or `ListView`. Execute `scroll` or `scrollIntoView` to force the widget to mount before interacting with it. - -## Test Authoring Guidelines - -Structure integration tests using the `flutter_test` API paradigm. - -- Create a dedicated `integration_test/` directory at the project root. -- Name all test files using the `_test.dart` convention. -- Initialize the binding by calling `IntegrationTestWidgetsFlutterBinding.ensureInitialized();` at the start of `main()`. -- Load the application UI using `await tester.pumpWidget(MyApp()); - diff --git a/third_party/skills/grill-me/SKILL.md b/third_party/skills/grill-me/SKILL.md deleted file mode 100644 index a7170e8e4524..000000000000 --- a/third_party/skills/grill-me/SKILL.md +++ /dev/null @@ -1,5 +0,0 @@ -description: Interview the user relentlessly about a plan or design until reaching shared understanding, resolving each branch of the decision tree. Use when user wants to stress-test a plan, get grilled on their design, or mentions "grill me". ---- - -Interview me relentlessly about every aspect of this plan until we reach a shared - diff --git a/third_party/skills/receiving-code-review/SKILL.md b/third_party/skills/receiving-code-review/SKILL.md deleted file mode 100644 index 12a3a7cc82ef..000000000000 --- a/third_party/skills/receiving-code-review/SKILL.md +++ /dev/null @@ -1,94 +0,0 @@ -description: Use when receiving code review feedback, before implementing suggestions, especially if feedback seems unclear or technically questionable - requires technical rigor and verification, not performative agreement or blind implementation ---- - -# Code Review Reception - -## Overview - -Code review requires technical evaluation, not emotional performance. - -**Core principle:** Verify before implementing. Ask before assuming. Technical correctness over social comfort. - -## The Response Pattern - -``` -WHEN receiving code review feedback: - -1. READ: Complete feedback without reacting -2. UNDERSTAND: Restate requirement in own words (or ask) -3. VERIFY: Check against codebase reality -4. EVALUATE: Technically sound for THIS codebase? -5. RESPOND: Technical acknowledgment or reasoned pushback -6. IMPLEMENT: One item at a time, test each -``` - -## Forbidden Responses - -**NEVER:** -- "You're absolutely right!" (explicit CLAUDE.md violation) -- "Great point!" / "Excellent feedback!" (performative) -- "Let me implement that now" (before verification) - -**INSTEAD:** -- Restate the technical requirement -- Ask clarifying questions -- Push back with technical reasoning if wrong -- Just start working (actions > words) - -## Handling Unclear Feedback - -``` -IF any item is unclear: - STOP - do not implement anything yet - ASK for clarification on unclear items - -WHY: Items may be related. Partial understanding = wrong implementation. -``` - -**Example:** -``` -your human partner: "Fix 1-6" -You understand 1,2,3,6. Unclear on 4,5. - -❌ WRONG: Implement 1,2,3,6 now, ask about 4,5 later -✅ RIGHT: "I understand items 1,2,3,6. Need clarification on 4 and 5 before proceeding." -``` - -## Source-Specific Handling - -### From your human partner -- **Trusted** - implement after understanding -- **Still ask** if scope unclear -- **No performative agreement** -- **Skip to action** or technical acknowledgment - -### From External Reviewers -``` -BEFORE implementing: - 1. Check: Technically correct for THIS codebase? - 2. Check: Breaks existing functionality? - 3. Check: Reason for current implementation? - 4. Check: Works on all platforms/versions? - 5. Check: Does reviewer understand full context? - -IF suggestion seems wrong: - Push back with technical reasoning - -IF can't easily verify: - Say so: "I can't verify this without [X]. Should I [investigate/ask/proceed]?" - -IF conflicts with your human partner's prior decisions: - Stop and discuss with your human partner first -``` - -**your human partner's rule:** "External feedback - be skeptical, but check carefully" - -## YAGNI Check for "Professional" Features - -``` -IF reviewer suggests "implementing properly": - grep codebase for actual usage - - IF unused: "This endpoint isn't called. Remove it (YAGNI)?" - IF used: Then - diff --git a/third_party/skills/skills-lock.json b/third_party/skills/skills-lock.json new file mode 100644 index 000000000000..1e28932a0dcc --- /dev/null +++ b/third_party/skills/skills-lock.json @@ -0,0 +1,47 @@ +{ + "version": 1, + "skills": { + "dart-add-unit-test": { + "source": "dart-lang/skills", + "sourceType": "github", + "skillPath": "skills/dart-add-unit-test/SKILL.md", + "computedHash": "326a2b6cb57bcb4f40203e063a1060e9549a8cea0ece1a5c9a0d39a2f2b85bc8" + }, + "dart-collect-coverage": { + "source": "dart-lang/skills", + "sourceType": "github", + "skillPath": "skills/dart-collect-coverage/SKILL.md", + "computedHash": "36d77c4ebc2edc7ade399ae8461776dd33a461899afda4b2b9d8e7f599d2ef6c" + }, + "dart-generate-test-mocks": { + "source": "dart-lang/skills", + "sourceType": "github", + "skillPath": "skills/dart-generate-test-mocks/SKILL.md", + "computedHash": "7bf12a98d63e96ed51ba077a24426be1b11a9fc508f7dfca60fc6e118c3fc923" + }, + "dart-run-static-analysis": { + "source": "dart-lang/skills", + "sourceType": "github", + "skillPath": "skills/dart-run-static-analysis/SKILL.md", + "computedHash": "e64ea092e216ecdc9b4a8b49b06d0b9a0b49f680c1116ada1d247b2de3fa6fe1" + }, + "flutter-add-integration-test": { + "source": "flutter/skills", + "sourceType": "github", + "skillPath": "skills/flutter-add-integration-test/SKILL.md", + "computedHash": "9ead37fef54371fed6ad07a9ba3de7a908135a0867b05baf74c28b7095343999" + }, + "grill-me": { + "source": "mattpocock/skills", + "sourceType": "github", + "skillPath": "skills/productivity/grill-me/SKILL.md", + "computedHash": "784f0dbb7403b0f00324bce9a112f715342777a0daee7bbb7385f9c6f0a170ea" + }, + "receiving-code-review": { + "source": "obra/superpowers", + "sourceType": "github", + "skillPath": "skills/receiving-code-review/SKILL.md", + "computedHash": "2760c85d4f4117b0006e7ba755f4bbd61f8f4c185f347999763c97f507274e30" + } + } +} From de7ce6b9de2d5080fedb21b46fef8323f6a7f002 Mon Sep 17 00:00:00 2001 From: Camille Simon Date: Mon, 15 Jun 2026 10:17:01 -0700 Subject: [PATCH 5/5] move flutter-add-integration-test and update symlinks --- .../.agents/skills/android-cli | 1 + .../.agents/skills/dart-add-unit-test | 1 + .../.agents/skills/dart-collect-coverage | 1 + .../.agents/skills/dart-generate-test-mocks | 1 + .../.agents/skills/dart-run-static-analysis | 1 + .../skills/flutter-add-integration-test | 1 + .../.agents/skills/grill-me | 1 + .../.agents/skills/receiving-code-review | 1 + .../camera_android_camerax/skills/android-cli | 1 - .../skills/dart-add-unit-test | 1 - .../skills/dart-collect-coverage | 1 - .../skills/dart-generate-test-mocks | 1 - .../skills/dart-run-static-analysis | 1 - .../skills/flutter-add-integration-test | 1 - .../camera_android_camerax/skills/grill-me | 1 - .../skills/receiving-code-review | 1 - .../flutter-add-integration-test/SKILL.md | 163 ------------------ 17 files changed, 8 insertions(+), 171 deletions(-) create mode 120000 packages/camera/camera_android_camerax/.agents/skills/android-cli create mode 120000 packages/camera/camera_android_camerax/.agents/skills/dart-add-unit-test create mode 120000 packages/camera/camera_android_camerax/.agents/skills/dart-collect-coverage create mode 120000 packages/camera/camera_android_camerax/.agents/skills/dart-generate-test-mocks create mode 120000 packages/camera/camera_android_camerax/.agents/skills/dart-run-static-analysis create mode 120000 packages/camera/camera_android_camerax/.agents/skills/flutter-add-integration-test create mode 120000 packages/camera/camera_android_camerax/.agents/skills/grill-me create mode 120000 packages/camera/camera_android_camerax/.agents/skills/receiving-code-review delete mode 120000 packages/camera/camera_android_camerax/skills/android-cli delete mode 120000 packages/camera/camera_android_camerax/skills/dart-add-unit-test delete mode 120000 packages/camera/camera_android_camerax/skills/dart-collect-coverage delete mode 120000 packages/camera/camera_android_camerax/skills/dart-generate-test-mocks delete mode 120000 packages/camera/camera_android_camerax/skills/dart-run-static-analysis delete mode 120000 packages/camera/camera_android_camerax/skills/flutter-add-integration-test delete mode 120000 packages/camera/camera_android_camerax/skills/grill-me delete mode 120000 packages/camera/camera_android_camerax/skills/receiving-code-review delete mode 100644 third_party/skills/.agents/skills/.agents/skills/flutter-add-integration-test/SKILL.md diff --git a/packages/camera/camera_android_camerax/.agents/skills/android-cli b/packages/camera/camera_android_camerax/.agents/skills/android-cli new file mode 120000 index 000000000000..ddba408a754a --- /dev/null +++ b/packages/camera/camera_android_camerax/.agents/skills/android-cli @@ -0,0 +1 @@ +../../../../../third_party/skills/.agents/skills/android-cli \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/.agents/skills/dart-add-unit-test b/packages/camera/camera_android_camerax/.agents/skills/dart-add-unit-test new file mode 120000 index 000000000000..393cceba6177 --- /dev/null +++ b/packages/camera/camera_android_camerax/.agents/skills/dart-add-unit-test @@ -0,0 +1 @@ +../../../../../third_party/skills/.agents/skills/dart-add-unit-test \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/.agents/skills/dart-collect-coverage b/packages/camera/camera_android_camerax/.agents/skills/dart-collect-coverage new file mode 120000 index 000000000000..cdae7f892798 --- /dev/null +++ b/packages/camera/camera_android_camerax/.agents/skills/dart-collect-coverage @@ -0,0 +1 @@ +../../../../../third_party/skills/.agents/skills/dart-collect-coverage \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/.agents/skills/dart-generate-test-mocks b/packages/camera/camera_android_camerax/.agents/skills/dart-generate-test-mocks new file mode 120000 index 000000000000..da6ca725bb9e --- /dev/null +++ b/packages/camera/camera_android_camerax/.agents/skills/dart-generate-test-mocks @@ -0,0 +1 @@ +../../../../../third_party/skills/.agents/skills/dart-generate-test-mocks \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/.agents/skills/dart-run-static-analysis b/packages/camera/camera_android_camerax/.agents/skills/dart-run-static-analysis new file mode 120000 index 000000000000..159d69a8a0ee --- /dev/null +++ b/packages/camera/camera_android_camerax/.agents/skills/dart-run-static-analysis @@ -0,0 +1 @@ +../../../../../third_party/skills/.agents/skills/dart-run-static-analysis \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/.agents/skills/flutter-add-integration-test b/packages/camera/camera_android_camerax/.agents/skills/flutter-add-integration-test new file mode 120000 index 000000000000..feeedcab42a9 --- /dev/null +++ b/packages/camera/camera_android_camerax/.agents/skills/flutter-add-integration-test @@ -0,0 +1 @@ +../../../../../third_party/skills/.agents/skills/flutter-add-integration-test \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/.agents/skills/grill-me b/packages/camera/camera_android_camerax/.agents/skills/grill-me new file mode 120000 index 000000000000..fc36fb656397 --- /dev/null +++ b/packages/camera/camera_android_camerax/.agents/skills/grill-me @@ -0,0 +1 @@ +../../../../../third_party/skills/.agents/skills/grill-me \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/.agents/skills/receiving-code-review b/packages/camera/camera_android_camerax/.agents/skills/receiving-code-review new file mode 120000 index 000000000000..8eb13bebe535 --- /dev/null +++ b/packages/camera/camera_android_camerax/.agents/skills/receiving-code-review @@ -0,0 +1 @@ +../../../../../third_party/skills/.agents/skills/receiving-code-review \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/skills/android-cli b/packages/camera/camera_android_camerax/skills/android-cli deleted file mode 120000 index 5ca76d6577eb..000000000000 --- a/packages/camera/camera_android_camerax/skills/android-cli +++ /dev/null @@ -1 +0,0 @@ -../../../../third_party/skills/android-cli \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/skills/dart-add-unit-test b/packages/camera/camera_android_camerax/skills/dart-add-unit-test deleted file mode 120000 index b6a4b4c26126..000000000000 --- a/packages/camera/camera_android_camerax/skills/dart-add-unit-test +++ /dev/null @@ -1 +0,0 @@ -../../../../third_party/skills/dart-add-unit-test \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/skills/dart-collect-coverage b/packages/camera/camera_android_camerax/skills/dart-collect-coverage deleted file mode 120000 index b6da5ac60be0..000000000000 --- a/packages/camera/camera_android_camerax/skills/dart-collect-coverage +++ /dev/null @@ -1 +0,0 @@ -../../../../third_party/skills/dart-collect-coverage \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/skills/dart-generate-test-mocks b/packages/camera/camera_android_camerax/skills/dart-generate-test-mocks deleted file mode 120000 index bbc26dd31f36..000000000000 --- a/packages/camera/camera_android_camerax/skills/dart-generate-test-mocks +++ /dev/null @@ -1 +0,0 @@ -../../../../third_party/skills/dart-generate-test-mocks \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/skills/dart-run-static-analysis b/packages/camera/camera_android_camerax/skills/dart-run-static-analysis deleted file mode 120000 index b91723a9bad2..000000000000 --- a/packages/camera/camera_android_camerax/skills/dart-run-static-analysis +++ /dev/null @@ -1 +0,0 @@ -../../../../third_party/skills/dart-run-static-analysis \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/skills/flutter-add-integration-test b/packages/camera/camera_android_camerax/skills/flutter-add-integration-test deleted file mode 120000 index caed9350e626..000000000000 --- a/packages/camera/camera_android_camerax/skills/flutter-add-integration-test +++ /dev/null @@ -1 +0,0 @@ -../../../../third_party/skills/flutter-add-integration-test \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/skills/grill-me b/packages/camera/camera_android_camerax/skills/grill-me deleted file mode 120000 index 6ce842d52593..000000000000 --- a/packages/camera/camera_android_camerax/skills/grill-me +++ /dev/null @@ -1 +0,0 @@ -../../../../third_party/skills/grill-me \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/skills/receiving-code-review b/packages/camera/camera_android_camerax/skills/receiving-code-review deleted file mode 120000 index b9170ccf97bc..000000000000 --- a/packages/camera/camera_android_camerax/skills/receiving-code-review +++ /dev/null @@ -1 +0,0 @@ -../../../../third_party/skills/receiving-code-review \ No newline at end of file diff --git a/third_party/skills/.agents/skills/.agents/skills/flutter-add-integration-test/SKILL.md b/third_party/skills/.agents/skills/.agents/skills/flutter-add-integration-test/SKILL.md deleted file mode 100644 index 60902f1aa315..000000000000 --- a/third_party/skills/.agents/skills/.agents/skills/flutter-add-integration-test/SKILL.md +++ /dev/null @@ -1,163 +0,0 @@ ---- -name: flutter-add-integration-test -description: Configures Flutter Driver for app interaction and converts MCP actions into permanent integration tests. Use when adding integration testing to a project, exploring UI components via MCP, or automating user flows with the integration_test package. -metadata: - model: models/gemini-3.1-pro-preview - last_modified: Tue, 21 Apr 2026 18:29:20 GMT ---- -# Implementing Flutter Integration Tests - -## Contents -- [Project Setup and Dependencies](#project-setup-and-dependencies) -- [Interactive Exploration via MCP](#interactive-exploration-via-mcp) -- [Test Authoring Guidelines](#test-authoring-guidelines) -- [Execution and Profiling](#execution-and-profiling) -- [Workflow: End-to-End Integration Testing](#workflow-end-to-end-integration-testing) -- [Examples](#examples) - -## Project Setup and Dependencies - -Configure the project to support integration testing and Flutter Driver extensions. - -1. Add required development dependencies to `pubspec.yaml`: - ```bash - flutter pub add 'dev:integration_test:{"sdk":"flutter"}' - flutter pub add 'dev:flutter_test:{"sdk":"flutter"}' - ``` -2. Enable the Flutter Driver extension in your application entry point (typically `lib/main.dart` or a dedicated `lib/main_test.dart`): - - Import `package:flutter_driver/driver_extension.dart`. - - Call `enableFlutterDriverExtension();` before `runApp()`. -3. Add `Key` parameters (e.g., `ValueKey('login_button')`) to critical widgets in the application code to ensure reliable targeting during tests. - -## Interactive Exploration via MCP - -Use the Dart/Flutter MCP server tools to interactively explore and manipulate the application state before writing static tests. - -- **Launch**: Execute `launch_app` with `target: "lib/main_test.dart"` to start the application and acquire the DTD URI. -- **Inspect**: Execute `get_widget_tree` to discover available `Key`s, `Text` nodes, and widget `Type`s. -- **Interact**: Execute `tap`, `enter_text`, and `scroll` to simulate user flows. -- **Wait**: Always execute `waitFor` or verify state with `get_health` when navigating or triggering animations. -- **Troubleshoot Unmounted Widgets**: If a widget is not found in the tree, it may be lazily loaded in a `SliverList` or `ListView`. Execute `scroll` or `scrollIntoView` to force the widget to mount before interacting with it. - -## Test Authoring Guidelines - -Structure integration tests using the `flutter_test` API paradigm. - -- Create a dedicated `integration_test/` directory at the project root. -- Name all test files using the `_test.dart` convention. -- Initialize the binding by calling `IntegrationTestWidgetsFlutterBinding.ensureInitialized();` at the start of `main()`. -- Load the application UI using `await tester.pumpWidget(MyApp());`. -- Trigger frames and wait for animations to complete using `await tester.pumpAndSettle();` after interactions like `tester.tap()`. -- Assert widget visibility using `expect(find.byKey(ValueKey('foo')), findsOneWidget);` or `findsNothing`. -- Scroll to specific off-screen widgets using `await tester.scrollUntilVisible(itemFinder, 500.0, scrollable: listFinder);`. - -**Conditional Logic for Legacy `flutter_driver`:** -- If maintaining or migrating legacy `flutter_driver` tests, use `driver.waitFor()`, `driver.waitForAbsent()`, `driver.tap()`, and `driver.scroll()` instead of the `WidgetTester` APIs. - -## Execution and Profiling - -Execute tests using the `flutter drive` command. Require a host driver script located in `test_driver/integration_test.dart` that calls `integrationDriver()`. - -**Conditional Execution Targets:** -- **If testing on Chrome:** Launch `chromedriver --port=4444` in a separate terminal, then run: - `flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart -d chrome` -- **If testing headless web:** Run with `-d web-server`. -- **If testing on Android (Local):** Run `flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart`. -- **If testing on Firebase Test Lab (Android):** - 1. Build debug APK: `flutter build apk --debug` - 2. Build test APK: `./gradlew app:assembleAndroidTest` - 3. Upload both APKs to the Firebase Test Lab console. - -## Workflow: End-to-End Integration Testing - -Copy and follow this checklist to implement and verify integration tests. - -- [ ] **Task Progress: Setup** - - [ ] Add `integration_test` and `flutter_test` to `pubspec.yaml`. - - [ ] Inject `enableFlutterDriverExtension()` into the app entry point. - - [ ] Assign `ValueKey`s to target widgets. -- [ ] **Task Progress: Exploration** - - [ ] Run `launch_app` via MCP. - - [ ] Map the widget tree using `get_widget_tree`. - - [ ] Validate interaction paths using MCP tools (`tap`, `enter_text`). -- [ ] **Task Progress: Authoring** - - [ ] Create `integration_test/app_test.dart`. - - [ ] Write test cases using `WidgetTester` APIs. - - [ ] Create `test_driver/integration_test.dart` with `integrationDriver()`. -- [ ] **Task Progress: Execution & Feedback Loop** - - [ ] Run `flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart`. - - [ ] **Feedback Loop**: Review test output -> If `PumpAndSettleTimedOutException` occurs, check for infinite animations -> If widget not found, add `scrollUntilVisible` -> Re-run test until passing. - -## Examples - -### Standard Integration Test (`integration_test/app_test.dart`) - -```dart -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:integration_test/integration_test.dart'; -import 'package:my_app/main.dart'; - -void main() { - IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - - group('End-to-end test', () { - testWidgets('tap on the floating action button, verify counter', (tester) async { - // Load app widget. - await tester.pumpWidget(const MyApp()); - - // Verify the counter starts at 0. - expect(find.text('0'), findsOneWidget); - - // Find the floating action button to tap on. - final fab = find.byKey(const ValueKey('increment')); - - // Emulate a tap on the floating action button. - await tester.tap(fab); - - // Trigger a frame and wait for animations. - await tester.pumpAndSettle(); - - // Verify the counter increments by 1. - expect(find.text('1'), findsOneWidget); - }); - }); -} -``` - -### Host Driver Script (`test_driver/integration_test.dart`) - -```dart -import 'package:integration_test/integration_test_driver.dart'; - -Future main() => integrationDriver(); -``` - -### Performance Profiling Driver Script (`test_driver/perf_driver.dart`) - -Use this driver script if you wrap your test actions in `binding.traceAction()` to capture performance metrics. - -```dart -import 'package:flutter_driver/flutter_driver.dart' as driver; -import 'package:integration_test/integration_test_driver.dart'; - -Future main() { - return integrationDriver( - responseDataCallback: (data) async { - if (data != null) { - final timeline = driver.Timeline.fromJson( - data['scrolling_timeline'] as Map, - ); - - final summary = driver.TimelineSummary.summarize(timeline); - - await summary.writeTimelineToFile( - 'scrolling_timeline', - pretty: true, - includeSummary: true, - ); - } - }, - ); -} -```