ワンクリックで
add-dart-lint-validation-rule
// Instructions for adding a new validation rule and CLI flag to dart_skills_lint.
// Instructions for adding a new validation rule and CLI flag to dart_skills_lint.
How to integrate, update, and configure the dart_skills_lint validation tool within a repository. Make sure to use this skill whenever the user asks to update dart_skills_lint, configure skills validation tests, fix skills linter dependency drifts, verify repository state before editing, optimize lint rules execution, or draft pull request submission commands.
Contains well-defined rules for creating natural, accurate, and readable writing. Use whenever authoring longer text, like analysis documents, PR or CL descriptions, or documentation.
Mandatory checks to run before completing any task that touches md files or dart code in this repository.
Use this skill when you need to set up validation for AI agent skills in a Dart project for the first time. This includes adding dependencies, configuring the linter, setting up tests, and creating a CI workflow.
Use this skill when you need to validate that AI agent skills meet the specification. This includes running the linter via CLI, authoring custom rules, and following the validation workflow.
Performs a comprehensive, multi-step code review of pull requests or local code changes, using iterative refinement (generation, critique, synthesis) to ensure high-quality, actionable feedback. Use when you need to review code changes thoroughly.
| name | add-dart-lint-validation-rule |
| description | Instructions for adding a new validation rule and CLI flag to dart_skills_lint. |
Use this skill when you need to add a new validation rule to the dart_skills_lint package, expose it as a toggleable CLI flag, and verify its behavior.
Create a new file in lib/src/rules/ extending SkillRule.
[!TIP] If your rule expects a specific structure in the skill's YAML frontmatter (e.g., inside
metadata), document this structure clearly in the class Dart docstring.
// lib/src/rules/my_new_rule.dart
import '../models/analysis_severity.dart';
import '../models/skill_context.dart';
import '../models/skill_rule.dart';
import '../models/validation_error.dart';
class MyNewRule extends SkillRule {
MyNewRule({super.severity});
@override
Future<List<ValidationError>> validate(SkillContext context) async {
final errors = <ValidationError>[];
// Add validation logic here using context.rawContent or context.directory
return errors;
}
}
If your rule needs configuration from the skill's YAML frontmatter, you can access it via context.parsedYaml.
@override
Future<List<ValidationError>> validate(SkillContext context) async {
final errors = <ValidationError>[];
final yaml = context.parsedYaml;
if (yaml != null) {
final metadata = yaml['metadata'];
if (metadata is Map) {
// Read your custom config here
}
}
return errors;
}
lib/src/rule_registry.dartAdd a new CheckType instance to RuleRegistry.allChecks list. This automatically exposes it as a CLI flag.
// lib/src/rule_registry.dart in allChecks list
const CheckType(
name: MyNewRule.ruleName,
defaultSeverity: MyNewRule.defaultSeverity,
help: 'Description of what the rule does for CLI help.',
),
Then, add a case to RuleRegistry.createRule to instantiate your rule:
// lib/src/rule_registry.dart in createRule method
static SkillRule? createRule(String name, AnalysisSeverity severity) {
switch (name) {
// ... other rules
case MyNewRule.ruleName:
return MyNewRule(severity: severity);
default:
return null;
}
}
If the rule is disabled by default (defaultSeverity: AnalysisSeverity.disabled), passing the flag --check-my-new-rule will automatically enable it with AnalysisSeverity.error severity (handled in entry_point.dart).
You must write automated tests verifying your rule triggers when it should and skips when it shouldn't.
Instead of writing files to disk, test the rule directly using a mock SkillContext. This is faster and avoids I/O dependencies.
// test/my_new_rule_test.dart
import 'dart:io';
import 'package:dart_skills_lint/src/models/analysis_severity.dart';
import 'package:dart_skills_lint/src/models/skill_context.dart';
import 'package:dart_skills_lint/src/models/validation_error.dart';
import 'package:dart_skills_lint/src/rules/my_new_rule.dart';
import 'package:test/test.dart';
void main() {
group('MyNewRule', () {
test('flags invalid content', () async {
final rule = MyNewRule(severity: AnalysisSeverity.warning);
final context = SkillContext(
directory: Directory('dummy'),
rawContent: 'Invalid content',
);
final List<ValidationError> errors = await rule.validate(context);
expect(errors, isNotEmpty);
expect(errors.first.message, contains('Expected error message'));
});
test('passes valid content', () async {
final rule = MyNewRule(severity: AnalysisSeverity.warning);
final context = SkillContext(
directory: Directory('dummy'),
rawContent: 'Valid content',
);
final List<ValidationError> errors = await rule.validate(context);
expect(errors, isEmpty);
});
});
}
If the rule interacts with the file system or wraps an external CLI tool (like popmark), you should use a temporary directory for testing instead of in-memory mocks.
late Directory tempDir;
setUp(() async {
tempDir = await Directory.systemTemp.createTemp('my_rule_test.');
});
tearDown(() async {
if (tempDir.existsSync()) {
await tempDir.delete(recursive: true);
}
});
test('flags invalid file content', () async {
final Directory skillDir = await Directory('${tempDir.path}/test-skill').create();
await File('${skillDir.path}/SKILL.md').writeAsString('Invalid content');
final rule = MyNewRule(severity: AnalysisSeverity.warning);
final context = SkillContext(directory: skillDir, rawContent: 'Invalid content');
final List<ValidationError> errors = await rule.validate(context);
expect(errors, isNotEmpty);
});
If the rule interacts with CLI flags or configuration files, add a test in test/cli_integration_test.dart using TestProcess.
[!IMPORTANT] When writing integration tests that use config files and
TestProcess, ensure that paths in the config file and paths passed to the CLI match in style (both relative or both absolute) to avoid issues with path matching inentry_point.dart.
When a new rule is introduced, verify that you synchronize sibling markdown files!
README.md:
documentation/knowledge/SPECIFICATION.md:
lib/src/rules/.lib/src/rule_registry.dart.test/ using in-memory SkillContext.README.md.documentation/knowledge/SPECIFICATION.md (if applicable).dart format . to format code.dart analyze --fatal-infos to ensure no issues.dart test to ensure tests passing.