-
Notifications
You must be signed in to change notification settings - Fork 3.8k
[camera_android_camerax] Setup agent skills camerax #11930
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 14 commits
ee20fa7
26b37ae
d825767
f7f0646
ea27e43
9ac31a2
87cfaf1
acbcc3e
7eabf5f
9e0d9e5
6b68664
0942453
9471107
c4e832f
acc34a5
288e5ec
43be3d1
8d17949
81c1c52
438537c
f64190b
14d7cfc
d7f024e
bc37ae6
16e3f28
83638ff
d93c81e
7c080f9
51ecf16
2271f28
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| # Ignore everything by default | ||
| * | ||
|
|
||
| # Un-ignore specific checked-in skills | ||
| # (Add specific contributor skills here as they are created) | ||
| !check-readiness/ | ||
|
|
||
| # Keep essential configuration and docs | ||
| !.gitignore | ||
| !README.md | ||
| !ignore.json | ||
| !flutter_skills_ignore.json |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| # Agent Skills | ||
|
|
||
| This directory contains skills intended for repository maintainers and contributors. Local, checked-in skills are evaluated by `dart_skills_lint` and should be configured to prevent publishing to pub.dev. | ||
|
|
||
| **Note on Remotely Managed Skills:** | ||
| Skills that are remotely defined and managed using `npx skills` should **not** be installed directly into this directory. Instead, they must be installed into the repository root's `third_party/` directory to comply with third-party code policies. Once installed there, they should be symlinked into this directory. | ||
|
|
||
| Please see the `third_party/README.md` file at the root of the repository for specific rules and instructions on adding new remote skills. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| --- | ||
| name: check-readiness | ||
| description: Run this skill to check if the repository is ready for new work. Use this skill whenever the user asks to "check readiness", "see if we are ready to start work", or when starting a new task in the camera_android_camerax package. | ||
| metadata: | ||
| internal: true | ||
| --- | ||
| # Check Readiness | ||
|
|
||
| This skill verifies that the local environment is properly configured and clean before starting new work in the `camera_android_camerax` package. | ||
|
|
||
| ## Instructions | ||
| Run the bundled verification script ([scripts/check.sh](scripts/check.sh)) to perform the automated environment checks: | ||
| ```bash | ||
| bash .agents/skills/check-readiness/scripts/check.sh | ||
|
reidbaker marked this conversation as resolved.
|
||
| ``` | ||
|
|
||
| ### Handling the Results | ||
| 1. **If the script succeeds:** Inform the user that the environment is clean, dependencies are resolved, and it is ready for new work. | ||
| 2. **If the script fails:** Explain exactly which check failed (e.g., git is not clean, a symlink is broken, Flutter is missing from PATH) and offer to help resolve it. | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @camsim99 I have some work happening to turn this into dart code but if you are ok with it I would like to land that change independently.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| #!/bin/bash | ||
|
|
||
| # Stop on first error | ||
| set -e | ||
|
|
||
| # Get the directory of this script, then go up to camera_android_camerax root | ||
| SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" | ||
| CAMERAX_DIR="$SCRIPT_DIR/../../../.." | ||
|
|
||
| echo "🔍 Checking if environment is ready for new work..." | ||
|
|
||
| # 1. Check symlinks resolve | ||
| echo "1️⃣ Checking skill symlinks..." | ||
| broken_links=$(find "$CAMERAX_DIR/.agents/skills" -type l ! -exec test -e {} \; -print) | ||
| if [ -n "$broken_links" ]; then | ||
| echo "❌ Error: Found broken symlinks in .agents/skills:" | ||
| echo "$broken_links" | ||
| exit 1 | ||
| fi | ||
| echo "✅ All symlinks resolve correctly." | ||
|
|
||
| # 2. Check git state | ||
| echo "2️⃣ Checking git state..." | ||
| # Check the whole repository git state | ||
| if [ -n "$(git status --porcelain)" ]; then | ||
| echo "❌ Error: Git working directory is not clean. Please commit or stash your changes before starting new work." | ||
| exit 1 | ||
| fi | ||
|
reidbaker marked this conversation as resolved.
|
||
| echo "✅ Git working directory is clean." | ||
|
|
||
| # 3. Check dart and flutter | ||
| echo "3️⃣ Checking Flutter and Dart..." | ||
| if ! command -v flutter &> /dev/null; then | ||
| echo "❌ Error: 'flutter' is not on the PATH." | ||
| exit 1 | ||
| fi | ||
| if ! command -v dart &> /dev/null; then | ||
| echo "❌ Error: 'dart' is not on the PATH." | ||
| exit 1 | ||
| fi | ||
| echo "✅ Flutter and Dart are on the PATH." | ||
|
|
||
| # 4. Check dependencies in camera_android_camerax | ||
| echo "4️⃣ Checking dependencies in camera_android_camerax..." | ||
| cd "$CAMERAX_DIR" | ||
| if ! flutter pub get; then | ||
| echo "❌ Error: Failed to resolve dependencies." | ||
| exit 1 | ||
| fi | ||
| echo "✅ Dependencies are resolved and ready." | ||
|
|
||
| echo "🎉 Environment is fully ready!" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ../../../../../third_party/dart-lang-skills/.agents/skills/dart-add-unit-test |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ../../../../../third_party/dart-lang-skills/.agents/skills/dart-collect-coverage |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ../../../../../third_party/dart-lang-skills/.agents/skills/dart-generate-test-mocks |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ../../../../../third_party/dart-lang-skills/.agents/skills/dart-run-static-analysis |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ../../../../../third_party/flutter-skills/.agents/skills/flutter-add-integration-test |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ../../../../../third_party/mattpocock-skills/.agents/skills/grill-me |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ../../../../../third_party/obra-superpowers/.agents/skills/receiving-code-review |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| dart_skills_lint: | ||
| rules: | ||
| check-relative-paths: error | ||
| check-trailing-whitespace: error | ||
| directories: | ||
| - path: "skills" | ||
| individual_skills: | ||
| - path: ".agents/skills/check-readiness" | ||
| rules: | ||
| prevent-skills-sh-publishing: error |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| # Published Skills | ||
|
|
||
| This directory contains AI agent skills that are intended to be published to pub.dev. |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does this live within the camera_android_camerax plugin? Assuming this might be something we would want available to all plugins but we are just starting with it here?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also why is it in the test/ directory? Is that standard for custom skill lints?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There is already a lint that ensures that skills that have the lint enabled are not published. This is more of a meta test that makes sure that for this package (later repo) that we have configured the skills correctly.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| // Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file | ||
| // for details. All rights reserved. Use of this source code is governed by a | ||
| // BSD-style license that can be found in the LICENSE file. | ||
|
|
||
| import 'dart:io'; | ||
|
|
||
| import 'package:dart_skills_lint/dart_skills_lint.dart'; | ||
|
|
||
| /// A custom lint rule that enforces that all skills tracked in version control | ||
| /// are marked as internal. | ||
| /// | ||
| /// This rule is specifically used to prevent the accidental publishing of | ||
| /// workspace-specific agent skills to the global public skills registry. It | ||
| /// uses `git ls-files` to determine if a skill directory is checked into git, | ||
| /// and if it is, strictly requires that the `metadata: internal: true` | ||
| /// frontmatter is present in the `SKILL.md` file. | ||
| class EnforceTrackedSkillsInternalRule extends SkillRule { | ||
| @override | ||
| String get name => 'enforce-tracked-skills-internal'; | ||
|
|
||
| @override | ||
| AnalysisSeverity get severity => AnalysisSeverity.error; | ||
|
|
||
| @override | ||
| Future<List<ValidationError>> validate(SkillContext context) async { | ||
| // Check if any files in the skill directory are tracked in git | ||
| final ProcessResult processResult = await Process.run('git', ['ls-files', context.directory.path]); | ||
| final String output = (processResult.stdout as String).trim(); | ||
|
reidbaker marked this conversation as resolved.
Outdated
|
||
| if (output.isEmpty) { | ||
| // Not tracked by git, no enforcement needed | ||
| return []; | ||
| } | ||
|
|
||
| final Object? yaml = context.parsedYaml; | ||
| if (yaml == null) { | ||
| return [ | ||
| ValidationError( | ||
| ruleId: name, | ||
| severity: severity, | ||
| file: 'SKILL.md', | ||
| message: 'Tracked skills must have "metadata: internal: true" in SKILL.md frontmatter.', | ||
| ) | ||
| ]; | ||
| } | ||
|
|
||
| final Object? metadata = (yaml as Map)['metadata']; | ||
| if (metadata is! Map || metadata['internal'] != true) { | ||
|
reidbaker marked this conversation as resolved.
Outdated
|
||
| return [ | ||
| ValidationError( | ||
| ruleId: name, | ||
| severity: severity, | ||
| file: 'SKILL.md', | ||
| message: 'Tracked skills must have "metadata: internal: true" in SKILL.md frontmatter.', | ||
| ) | ||
| ]; | ||
| } | ||
|
|
||
| return []; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| import 'dart:async'; | ||
|
|
||
| import 'package:dart_skills_lint/dart_skills_lint.dart'; | ||
| import 'package:flutter/foundation.dart'; | ||
| import 'package:flutter_test/flutter_test.dart'; | ||
| import 'package:logging/logging.dart'; | ||
|
|
||
| import 'enforce_tracked_skills_internal_rule.dart'; | ||
|
|
||
| void main() { | ||
| test('Validate Skills', () async { | ||
| final Level oldLevel = Logger.root.level; | ||
| Logger.root.level = Level.ALL; | ||
| final StreamSubscription<LogRecord> subscription = Logger.root.onRecord.listen((record) { | ||
| debugPrint(record.message); | ||
| }); | ||
|
|
||
| try { | ||
| final Configuration config = await ConfigParser.loadConfig(); | ||
| final bool isValid = await validateSkills( | ||
| config: config, | ||
| customRules: [EnforceTrackedSkillsInternalRule()], | ||
| ); | ||
| expect(isValid, isTrue, reason: 'Skills validation failed. See above for details.'); | ||
| } finally { | ||
| Logger.root.level = oldLevel; | ||
| await subscription.cancel(); | ||
| } | ||
| }); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| # Third-Party Agent Skills | ||
|
|
||
| To comply with third-party code policies, all remotely managed agent skills (installed via `npx skills`) must be isolated in this `third_party/` directory before being symlinked to specific project `.agents/skills` directories. | ||
|
|
||
| ## Rules for Adding New Remote Skills | ||
|
|
||
| When adding a new remote skill, you must follow this exact structure and process: | ||
|
|
||
| 1. **Folder per Repository:** Create a new folder under `third_party/` named uniquely after the GitHub repository the skill originates from (e.g., `third_party/dart-lang-skills`). | ||
|
|
||
| 2. **Installation:** Run the `npx skills` command from *within* that new repository folder. This ensures the `skills-lock.json` file is correctly generated inside the subfolder. All `skills-lock.json` files must be generated by the CLI, not manually crafted. | ||
| ```bash | ||
| cd third_party/<repo-name> | ||
| npx skills add <author/repo> --skill <skill-name> -y | ||
| ``` | ||
|
|
||
| 3. **License Requirement:** You **must** download and retain the original `LICENSE` file from the remote repository and place it directly inside the `third_party/<repo-name>` subfolder. | ||
|
|
||
| 4. **Symlinking:** Once installed, symlink the newly downloaded skill into the appropriate plugin's `.agents/skills` directory using a relative symlink. | ||
| ```bash | ||
| cd packages/<plugin-name>/.agents/skills | ||
| ln -s ../../../../../third_party/<repo-name>/.agents/skills/<skill-name> <skill-name> | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| --- | ||
| name: dart-add-unit-test | ||
| description: Write and organize unit tests for functions, methods, and classes using `package:test`. Use when creating new logic or fixing bugs to ensure code remains correct and regression-free. | ||
| metadata: | ||
| model: models/gemini-3.1-pro-preview | ||
| last_modified: Fri, 24 Apr 2026 15:07:58 GMT | ||
| --- | ||
| # Testing Dart and Flutter Applications | ||
|
|
||
| ## Contents | ||
| - [Structuring Test Files](#structuring-test-files) | ||
| - [Writing Tests](#writing-tests) | ||
| - [Executing Tests](#executing-tests) | ||
| - [Test Implementation Workflow](#test-implementation-workflow) | ||
| - [Examples](#examples) | ||
|
|
||
| ## Structuring Test Files | ||
| Organize test files to mirror the `lib` directory structure to maintain predictability. | ||
|
|
||
| * Place all test code within the `test` directory at the root of the package. | ||
| * Append `_test.dart` to the end of all test file names (e.g., `lib/src/utils.dart` should be tested in `test/src/utils_test.dart`). | ||
| * If writing integration tests, place them in an `integration_test` directory at the root of the package. | ||
|
|
||
| ## Writing Tests | ||
| Utilize `package:test` as the standard testing library for Dart applications. | ||
|
|
||
| * Import `package:test/test.dart` (or `package:flutter_test/flutter_test.dart` for Flutter). | ||
| * Group related tests using the `group()` function to provide shared context. | ||
| * Define individual test cases using the `test()` function. | ||
| * Validate outcomes using the `expect()` function alongside matchers (e.g., `equals()`, `isTrue`, `throwsA()`). | ||
| * Write asynchronous tests using standard `async`/`await` syntax. The test runner automatically waits for the `Future` to complete. | ||
| * Manage test setup and teardown using `setUp()` and `tearDown()` callbacks. | ||
| * If testing code that relies on dependency injection, use `package:mockito` alongside `package:test` to generate mock objects, configure fixed scenarios, and verify interactions. | ||
|
|
||
| ## Executing Tests | ||
| Select the appropriate test runner based on the project type and test location. | ||
|
|
||
| * If working on a pure Dart project, execute tests using the `dart test` command. | ||
| * If working on a Flutter project, execute tests using the `flutter test` command. | ||
| * If running integration tests, explicitly specify the directory path, as the default runner ignores it: `dart test integration_test` or `flutter test integration_test`. | ||
|
|
||
| ## Test Implementation Workflow | ||
|
|
||
| Follow this sequential workflow when implementing new test suites. Copy the checklist to track your progress. | ||
|
|
||
| ### Task Progress | ||
| - [ ] 1. Create the test file in the `test/` directory, ensuring the `_test.dart` suffix. | ||
| - [ ] 2. Import `package:test/test.dart` and the target library. | ||
| - [ ] 3. Define a `main()` function. | ||
| - [ ] 4. Initialize shared resources or mocks using `setUp()`. | ||
| - [ ] 5. Write `test()` cases grouped by functionality using `group()`. | ||
| - [ ] 6. Execute the test suite using the appropriate CLI command. | ||
| - [ ] 7. **Feedback Loop**: Run test -> 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<ApiClient>()]) | ||
| 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); | ||
| }); | ||
| }); | ||
| } | ||
| ``` |
Uh oh!
There was an error while loading. Please reload this page.