Add dart_skills_lint to devtools and configure it to run in the cli and in tests (#9770)
* add dart skills lint test and yaml config with instructions for how to use
* Add ignore file for valid links that are triggering false positives
* resolve readme to correct location
* Copyright added to new files and issue linked in pubspec
* Add link to yaml configuration feature
* presubmit feedback
* Update tool/test/validate_skills_test.dart
Co-authored-by: Kenzie Davisson <43759233+kenzieschmoll@users.noreply.github.com>
* Update pubspec.yaml
Co-authored-by: Kenzie Davisson <43759233+kenzieschmoll@users.noreply.github.com>
* Fix one relative path issues, update version of dart_skills_lint
* remove the root dependency on dart_skills_lint
* Change todo format
* Remove double trailing line
---------
Co-authored-by: Kenzie Davisson <43759233+kenzieschmoll@users.noreply.github.com>
diff --git a/.agents/skills/README.md b/.agents/skills/README.md
new file mode 100644
index 0000000..8555a78
--- /dev/null
+++ b/.agents/skills/README.md
@@ -0,0 +1,40 @@
+<!--
+Copyright 2026 The Flutter Authors
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
+-->
+
+# Agent Skills
+
+This directory contains AI agent skills for this repository.
+
+## Validation
+
+To ensure skills meet the required specification, they are automatically validated in pre-submit checks.
+You should also validate your skills locally before submitting a review.
+
+### Running the Linter Locally
+
+To validate skills locally before review, run the linter from the `tool` directory:
+
+```bash
+cd tool && dart run dart_skills_lint:cli
+```
+
+This will use the configuration in `tool/dart_skills_lint.yaml` to validate all skills in the `.agents/skills` directory.
+
+Or for a single skill (also from the `tool` directory):
+
+```bash
+cd tool && dart run dart_skills_lint:cli --skill ../.agents/skills/my-skill
+```
+
+### Running via Dart Test
+
+Alternatively, you can run the validation as a test from the `tool` directory:
+
+```bash
+cd tool && dart test test/validate_skills_test.dart
+```
+
+This ensures that the validation logic is executed in the same way as in CI.
diff --git a/.agents/skills/adding-release-notes/SKILL.md b/.agents/skills/adding-release-notes/SKILL.md
index c47b3e6..59853bf 100644
--- a/.agents/skills/adding-release-notes/SKILL.md
+++ b/.agents/skills/adding-release-notes/SKILL.md
@@ -84,4 +84,4 @@
**Constraint**: Use **dark mode** for screenshots.
## Resources
-- [README.md](../../packages/devtools_app/release_notes/README.md): Official project guidance.
+- [README.md](../../../packages/devtools_app/release_notes/README.md): Official project guidance.
diff --git a/.agents/skills/authoring-skills/SKILL.md b/.agents/skills/authoring-skills/SKILL.md
index ab87119..da0bdcf 100644
--- a/.agents/skills/authoring-skills/SKILL.md
+++ b/.agents/skills/authoring-skills/SKILL.md
@@ -17,6 +17,7 @@
- **Naming**: Use the gerund form (**verb-ing-noun**) or **noun-phrase** (e.g., `authoring-skills`, `adding-release-notes`). Use only lowercase letters, numbers, and hyphens.
- **Conciseness**: Prioritize brevity in `SKILL.md`. Agents are already highly capable; only provide context they don't already have.
- **Automation**: Any utility scripts placed in the `scripts/` directory MUST be written in **Dart**.
+- **Validation**: Skills are automatically validated using `dart_skills_lint`. Ensure your skills pass the linter before submitting. See the `README.md` in `.agents/skills/` for instructions on how to run the linter locally.
- **Progressive Disclosure**: Use the patterns below to organize instructions effectively:
- [CHECKLIST.md](CHECKLIST.md): Template for tracking skill development progress.
- [EXAMPLES.md](EXAMPLES.md): Local examples and anti-patterns.
diff --git a/.agents/skills/dart_skills_lint_ignore.json b/.agents/skills/dart_skills_lint_ignore.json
new file mode 100644
index 0000000..a35a789
--- /dev/null
+++ b/.agents/skills/dart_skills_lint_ignore.json
@@ -0,0 +1,10 @@
+{
+ "skills": {
+ "adding-release-notes": [
+ {
+ "rule_id": "check-relative-paths",
+ "file_name": "SKILL.md"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/pubspec.lock b/pubspec.lock
index 0bd580b..a55f54d 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -209,6 +209,15 @@
url: "https://pub.dev"
source: hosted
version: "0.0.3"
+ dart_skills_lint:
+ dependency: transitive
+ description:
+ path: "tool/dart_skills_lint"
+ ref: "2420128e11101002e2eac98eb90512103a388714"
+ resolved-ref: "2420128e11101002e2eac98eb90512103a388714"
+ url: "https://github.com/flutter/skills"
+ source: git
+ version: "0.2.0"
dart_style:
dependency: transitive
description:
diff --git a/tool/dart_skills_lint.yaml b/tool/dart_skills_lint.yaml
new file mode 100644
index 0000000..150e390
--- /dev/null
+++ b/tool/dart_skills_lint.yaml
@@ -0,0 +1,10 @@
+# Copyright 2026 The Flutter Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
+dart_skills_lint:
+ rules:
+ check-relative-paths: error
+ check-absolute-paths: error
+ check-trailing-whitespace: error
+ directories:
+ - path: "../.agents/skills"
diff --git a/tool/pubspec.yaml b/tool/pubspec.yaml
index 90ccf11..68671b4 100644
--- a/tool/pubspec.yaml
+++ b/tool/pubspec.yaml
@@ -21,6 +21,13 @@
meta: ^1.18.0
path: ^1.9.0
yaml: ^3.1.2
-
+
dev_dependencies:
+ # TODO(https://github.com/flutter/devtools/issues/9771): Update to published version
+ dart_skills_lint:
+ git:
+ url: https://github.com/flutter/skills
+ path: tool/dart_skills_lint
+ ref: 2420128e11101002e2eac98eb90512103a388714
+ logging: ^1.1.1
test: ^1.25.8
diff --git a/tool/test/validate_skills_test.dart b/tool/test/validate_skills_test.dart
new file mode 100644
index 0000000..7c50d63
--- /dev/null
+++ b/tool/test/validate_skills_test.dart
@@ -0,0 +1,35 @@
+// Copyright 2026 The Flutter Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
+
+import 'dart:async';
+import 'package:dart_skills_lint/dart_skills_lint.dart';
+import 'package:logging/logging.dart';
+import 'package:test/test.dart';
+
+void main() {
+ test('Validate DevTools Skills', () async {
+ final Level oldLevel = Logger.root.level;
+ Logger.root.level = Level.ALL;
+ final StreamSubscription<LogRecord> subscription = Logger.root.onRecord.listen((record) {
+ print(record.message);
+ });
+
+ try {
+ // TODO(https://github.com/flutter/skills/issues/85): Update test
+ // to use dart_skills_lint.yaml for config when available.
+ final bool isValid = await validateSkills(
+ skillDirPaths: ['../.agents/skills'],
+ resolvedRules: {
+ 'check-relative-paths': AnalysisSeverity.error,
+ 'check-absolute-paths': AnalysisSeverity.error,
+ 'check-trailing-whitespace': AnalysisSeverity.error,
+ },
+ );
+ expect(isValid, isTrue, reason: 'Skills validation failed. See above for details.');
+ } finally {
+ Logger.root.level = oldLevel;
+ await subscription.cancel();
+ }
+ });
+}