sdd-full 4.8.0 → 4.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/bin.js +1 -1
  2. package/index.js +18 -12
  3. package/package.json +1 -1
  4. package/skills/VERSION.md +61 -175
  5. package/skills/design-planning/ai-coding-rules/SKILL.md +13 -5
  6. package/skills/design-planning/design-to-code/SKILL.md +14 -5
  7. package/skills/design-planning/enterprise-spec/SKILL.md +13 -5
  8. package/skills/design-planning/flutter-av/SKILL.md +16 -5
  9. package/skills/design-planning/flutter-map/SKILL.md +14 -5
  10. package/skills/design-planning/function-sdd/SKILL.md +13 -5
  11. package/skills/design-planning/global-overlay-stack-standard/SKILL.md +14 -4
  12. package/skills/design-planning/ui-motion-interaction-standard/SKILL.md +14 -4
  13. package/skills/design-planning/ui-sdd-specialized/SKILL.md +14 -5
  14. package/skills/development-execution/flutter-errors/SKILL.md +15 -5
  15. package/skills/quality-assurance/bdd-acceptance/SKILL.md +14 -5
  16. package/skills/quality-assurance/flutter-test/SKILL.md +16 -5
  17. package/skills/requirement-analysis/sdd/mock_sdd.md +156 -0
  18. package/skills/rules/project_rules.md +127 -538
  19. package/skills/rules/user_rules.md +263 -0
  20. package/skills/special-tools/env-check/SKILL.md +13 -5
  21. package/skills/special-tools/ios-full-auto-debug/SKILL.md +15 -5
  22. package/skills/flutter-skills/.github/dependabot.yaml +0 -15
  23. package/skills/flutter-skills/.github/workflows/dart_skills_lint_workflow.yaml +0 -68
  24. package/skills/flutter-skills/.github/workflows/skills_tool.yaml +0 -51
  25. package/skills/flutter-skills/CODE_OF_CONDUCT.md +0 -3
  26. package/skills/flutter-skills/CONTRIBUTING.md +0 -36
  27. package/skills/flutter-skills/LICENSE +0 -26
  28. package/skills/flutter-skills/README.md +0 -50
  29. package/skills/flutter-skills/pubspec.yaml +0 -9
  30. package/skills/flutter-skills/resources/flutter_skills.yaml +0 -434
  31. package/skills/flutter-skills/skills/flutter-add-integration-test/SKILL.md +0 -163
  32. package/skills/flutter-skills/skills/flutter-add-widget-preview/SKILL.md +0 -145
  33. package/skills/flutter-skills/skills/flutter-add-widget-test/SKILL.md +0 -154
  34. package/skills/flutter-skills/skills/flutter-apply-architecture-best-practices/SKILL.md +0 -162
  35. package/skills/flutter-skills/skills/flutter-build-responsive-layout/SKILL.md +0 -139
  36. package/skills/flutter-skills/skills/flutter-fix-layout-issues/SKILL.md +0 -130
  37. package/skills/flutter-skills/skills/flutter-implement-json-serialization/SKILL.md +0 -153
  38. package/skills/flutter-skills/skills/flutter-setup-declarative-routing/SKILL.md +0 -255
  39. package/skills/flutter-skills/skills/flutter-setup-localization/SKILL.md +0 -210
  40. package/skills/flutter-skills/skills/flutter-use-http-package/SKILL.md +0 -175
  41. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/add-dart-lint-validation-rule/SKILL.md +0 -196
  42. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-best-practices/SKILL.md +0 -65
  43. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-checks-migration/SKILL.md +0 -158
  44. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-cli-app-best-practices/SKILL.md +0 -168
  45. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-doc-validation/SKILL.md +0 -87
  46. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-long-lines/SKILL.md +0 -101
  47. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-matcher-best-practices/SKILL.md +0 -136
  48. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-modern-features/SKILL.md +0 -266
  49. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-package-maintenance/SKILL.md +0 -92
  50. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-coverage/SKILL.md +0 -92
  51. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-coverage/example/lib/src/calculator.dart +0 -7
  52. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-coverage/example/pubspec.yaml +0 -8
  53. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-coverage/example/test/calculator_test.dart +0 -11
  54. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-coverage/scripts/interpret_coverage.dart +0 -95
  55. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-coverage/scripts/pubspec.yaml +0 -6
  56. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-coverage/scripts/test/interpret_coverage_test.dart +0 -93
  57. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-fundamentals/SKILL.md +0 -173
  58. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/definition-of-done/SKILL.md +0 -27
  59. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/flutter_skills_ignore.json +0 -3
  60. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/grill-me/SKILL.md +0 -10
  61. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/ignore.json +0 -3
  62. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/test-driven-development/SKILL.md +0 -371
  63. package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/test-driven-development/testing-anti-patterns.md +0 -299
  64. package/skills/flutter-skills/tool/dart_skills_lint/AUTHORS +0 -7
  65. package/skills/flutter-skills/tool/dart_skills_lint/CHANGELOG.md +0 -12
  66. package/skills/flutter-skills/tool/dart_skills_lint/CONTRIBUTING.md +0 -51
  67. package/skills/flutter-skills/tool/dart_skills_lint/LICENSE +0 -27
  68. package/skills/flutter-skills/tool/dart_skills_lint/README.md +0 -203
  69. package/skills/flutter-skills/tool/dart_skills_lint/analysis_options.yaml +0 -296
  70. package/skills/flutter-skills/tool/dart_skills_lint/bench/README.md +0 -23
  71. package/skills/flutter-skills/tool/dart_skills_lint/bench/baseline_throughput.dart +0 -230
  72. package/skills/flutter-skills/tool/dart_skills_lint/bin/cli.dart +0 -10
  73. package/skills/flutter-skills/tool/dart_skills_lint/dart_skills_lint.yaml +0 -14
  74. package/skills/flutter-skills/tool/dart_skills_lint/documentation/feature_design_docs/PRODUCTION_READYNESS.md +0 -48
  75. package/skills/flutter-skills/tool/dart_skills_lint/documentation/feature_design_docs/completion_migration_plan.md +0 -99
  76. package/skills/flutter-skills/tool/dart_skills_lint/documentation/feature_design_docs/legacy_patterns_report.md +0 -110
  77. package/skills/flutter-skills/tool/dart_skills_lint/documentation/feature_design_docs/pub_vs_skill_report.md +0 -56
  78. package/skills/flutter-skills/tool/dart_skills_lint/documentation/knowledge/SPECIFICATION.md +0 -79
  79. package/skills/flutter-skills/tool/dart_skills_lint/documentation/knowledge/architecture_overview.md +0 -64
  80. package/skills/flutter-skills/tool/dart_skills_lint/lib/dart_skills_lint.dart +0 -11
  81. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/config_parser.dart +0 -156
  82. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/entry_point.dart +0 -354
  83. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/fixable_rule.dart +0 -20
  84. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/analysis_severity.dart +0 -15
  85. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/check_type.dart +0 -17
  86. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/ignore_entry.dart +0 -34
  87. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/ignore_entry.g.dart +0 -19
  88. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/skill_context.dart +0 -27
  89. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/skill_rule.dart +0 -27
  90. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/skills_ignores.dart +0 -26
  91. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/skills_ignores.g.dart +0 -24
  92. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/validation_error.dart +0 -31
  93. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rule_registry.dart +0 -79
  94. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rules/absolute_paths_rule.dart +0 -74
  95. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rules/description_length_rule.dart +0 -49
  96. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rules/disallowed_field_rule.dart +0 -61
  97. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rules/name_format_rule.dart +0 -167
  98. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rules/relative_paths_rule.dart +0 -72
  99. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rules/trailing_whitespace_rule.dart +0 -93
  100. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rules/valid_yaml_metadata_rule.dart +0 -74
  101. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/skills_ignores_storage.dart +0 -36
  102. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/validation_session.dart +0 -559
  103. package/skills/flutter-skills/tool/dart_skills_lint/lib/src/validator.dart +0 -238
  104. package/skills/flutter-skills/tool/dart_skills_lint/pubspec.yaml +0 -28
  105. package/skills/flutter-skills/tool/dart_skills_lint/skills/README.md +0 -10
  106. package/skills/flutter-skills/tool/dart_skills_lint/skills/dart-skills-lint-validation/SKILL.md +0 -195
  107. package/skills/flutter-skills/tool/dart_skills_lint/skills-lock.json +0 -75
  108. package/skills/flutter-skills/tool/dart_skills_lint/test/absolute_paths_test.dart +0 -167
  109. package/skills/flutter-skills/tool/dart_skills_lint/test/cli_integration_test.dart +0 -683
  110. package/skills/flutter-skills/tool/dart_skills_lint/test/config_file_test.dart +0 -292
  111. package/skills/flutter-skills/tool/dart_skills_lint/test/custom_rule_test.dart +0 -122
  112. package/skills/flutter-skills/tool/dart_skills_lint/test/directory_structure_test.dart +0 -163
  113. package/skills/flutter-skills/tool/dart_skills_lint/test/field_constraints_test.dart +0 -178
  114. package/skills/flutter-skills/tool/dart_skills_lint/test/fixer_test.dart +0 -172
  115. package/skills/flutter-skills/tool/dart_skills_lint/test/ignore_models_test.dart +0 -63
  116. package/skills/flutter-skills/tool/dart_skills_lint/test/metadata_validation_test.dart +0 -116
  117. package/skills/flutter-skills/tool/dart_skills_lint/test/relative_path_flag_test.dart +0 -70
  118. package/skills/flutter-skills/tool/dart_skills_lint/test/relative_paths_test.dart +0 -172
  119. package/skills/flutter-skills/tool/dart_skills_lint/test/resolve_rules_test.dart +0 -82
  120. package/skills/flutter-skills/tool/dart_skills_lint/test/rule_naming_test.dart +0 -29
  121. package/skills/flutter-skills/tool/dart_skills_lint/test/skills_ignores_storage_test.dart +0 -89
  122. package/skills/flutter-skills/tool/dart_skills_lint/test/test_utils.dart +0 -19
  123. package/skills/flutter-skills/tool/dart_skills_lint/test/trailing_whitespace_test.dart +0 -152
  124. package/skills/flutter-skills/tool/generator/README.md +0 -150
  125. package/skills/flutter-skills/tool/generator/analysis_options.yaml +0 -143
  126. package/skills/flutter-skills/tool/generator/bin/skills.dart +0 -73
  127. package/skills/flutter-skills/tool/generator/lib/src/commands/base_skill_command.dart +0 -87
  128. package/skills/flutter-skills/tool/generator/lib/src/commands/base_yaml_command.dart +0 -83
  129. package/skills/flutter-skills/tool/generator/lib/src/commands/generate_skill_command.dart +0 -92
  130. package/skills/flutter-skills/tool/generator/lib/src/commands/update_readme_command.dart +0 -150
  131. package/skills/flutter-skills/tool/generator/lib/src/commands/update_skill_command.dart +0 -97
  132. package/skills/flutter-skills/tool/generator/lib/src/commands/validate_skill_command.dart +0 -284
  133. package/skills/flutter-skills/tool/generator/lib/src/models/skill_params.dart +0 -41
  134. package/skills/flutter-skills/tool/generator/lib/src/services/gemini_service.dart +0 -310
  135. package/skills/flutter-skills/tool/generator/lib/src/services/markdown_converter.dart +0 -226
  136. package/skills/flutter-skills/tool/generator/lib/src/services/prompts.dart +0 -72
  137. package/skills/flutter-skills/tool/generator/lib/src/services/resource_fetcher_service.dart +0 -84
  138. package/skills/flutter-skills/tool/generator/lib/src/services/skill_instructions.dart +0 -30
  139. package/skills/flutter-skills/tool/generator/pubspec.yaml +0 -32
  140. package/skills/flutter-skills/tool/generator/test/commands/base_skill_command_test.dart +0 -131
  141. package/skills/flutter-skills/tool/generator/test/commands/validate_skills_input_test.dart +0 -263
  142. package/skills/flutter-skills/tool/generator/test/custom_skill_rules/last_modified_rule.dart +0 -32
  143. package/skills/flutter-skills/tool/generator/test/generate_skills_retry_test.dart +0 -105
  144. package/skills/flutter-skills/tool/generator/test/generate_skills_test.dart +0 -519
  145. package/skills/flutter-skills/tool/generator/test/lint_skills_test.dart +0 -34
  146. package/skills/flutter-skills/tool/generator/test/markdown_converter_test.dart +0 -103
  147. package/skills/flutter-skills/tool/generator/test/markdown_table_test.dart +0 -131
  148. package/skills/flutter-skills/tool/generator/test/models/skill_params_test.dart +0 -37
  149. package/skills/flutter-skills/tool/generator/test/services/gemini_service_test.dart +0 -291
  150. package/skills/flutter-skills/tool/generator/test/services/markdown_converter_test.dart +0 -156
  151. package/skills/flutter-skills/tool/generator/test/services/resource_fetcher_service_test.dart +0 -188
  152. package/skills/flutter-skills/tool/generator/test/update_skills_test.dart +0 -241
  153. package/skills/flutter-skills/tool/generator/test/validate_skills_test.dart +0 -728
  154. /package/skills/{.agents → flutter}/skills/flutter-add-integration-test/SKILL.md +0 -0
  155. /package/skills/{.agents → flutter}/skills/flutter-add-widget-preview/SKILL.md +0 -0
  156. /package/skills/{.agents → flutter}/skills/flutter-add-widget-test/SKILL.md +0 -0
  157. /package/skills/{.agents → flutter}/skills/flutter-apply-architecture-best-practices/SKILL.md +0 -0
  158. /package/skills/{.agents → flutter}/skills/flutter-build-responsive-layout/SKILL.md +0 -0
  159. /package/skills/{.agents → flutter}/skills/flutter-fix-layout-issues/SKILL.md +0 -0
  160. /package/skills/{.agents → flutter}/skills/flutter-implement-json-serialization/SKILL.md +0 -0
  161. /package/skills/{.agents → flutter}/skills/flutter-setup-declarative-routing/SKILL.md +0 -0
  162. /package/skills/{.agents → flutter}/skills/flutter-setup-localization/SKILL.md +0 -0
  163. /package/skills/{.agents → flutter}/skills/flutter-use-http-package/SKILL.md +0 -0
@@ -1,178 +0,0 @@
1
- // Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
2
- // for details. All rights reserved. Use of this source code is governed by a
3
- // BSD-style license that can be found in the LICENSE file.
4
-
5
- import 'dart:io';
6
-
7
- import 'package:dart_skills_lint/src/models/skill_context.dart';
8
- import 'package:dart_skills_lint/src/rules/description_length_rule.dart';
9
- import 'package:dart_skills_lint/src/rules/name_format_rule.dart';
10
- import 'package:dart_skills_lint/src/rules/valid_yaml_metadata_rule.dart';
11
- import 'package:dart_skills_lint/src/validator.dart';
12
- import 'package:test/test.dart';
13
- import 'package:yaml/yaml.dart';
14
-
15
- import 'test_utils.dart';
16
-
17
- void main() {
18
- group('Field Specific Constraints Validation', () {
19
- late Directory tempDir;
20
-
21
- setUp(() async {
22
- tempDir = await Directory.systemTemp.createTemp('fields_test.');
23
- });
24
-
25
- tearDown(() async {
26
- if (tempDir.existsSync()) {
27
- await tempDir.delete(recursive: true);
28
- }
29
- });
30
-
31
- group('Skill Name', () {
32
- test('fails if not lowercase', () async {
33
- final Directory skillDir = await Directory('${tempDir.path}/Skill-Name').create();
34
- await File('${skillDir.path}/SKILL.md').writeAsString('${buildFrontmatter()}Body');
35
- final validator = Validator();
36
- final ValidationResult result = await validator.validate(skillDir);
37
- expect(result.isValid, isFalse);
38
- expect(result.errors, contains(contains('lowercase')));
39
- });
40
-
41
- test('fails if too long (> ${NameFormatRule.maxNameLength} chars)', () async {
42
- final String longName = 'a' * (NameFormatRule.maxNameLength + 1);
43
- final Directory skillDir = await Directory('${tempDir.path}/$longName').create();
44
- await File(
45
- '${skillDir.path}/SKILL.md',
46
- ).writeAsString('${buildFrontmatter(name: longName)}Body');
47
- final validator = Validator();
48
- final ValidationResult result = await validator.validate(skillDir);
49
- expect(result.isValid, isFalse);
50
- expect(
51
- result.errors,
52
- contains(contains('Maximum ${NameFormatRule.maxNameLength} characters')),
53
- );
54
- });
55
-
56
- test('fails if contains invalid characters', () async {
57
- final Directory skillDir = await Directory('${tempDir.path}/skill_name').create();
58
- await File(
59
- '${skillDir.path}/SKILL.md',
60
- ).writeAsString('${buildFrontmatter(name: 'skill_name')}Body');
61
- final validator = Validator();
62
- final ValidationResult result = await validator.validate(skillDir);
63
- expect(result.isValid, isFalse);
64
- expect(result.errors, contains(contains('lowercase letters, digits, and hyphens')));
65
- });
66
-
67
- test('fails if has leading hyphen', () async {
68
- final Directory skillDir = await Directory('${tempDir.path}/-skill-name').create();
69
- await File(
70
- '${skillDir.path}/SKILL.md',
71
- ).writeAsString('${buildFrontmatter(name: '-skill-name')}Body');
72
- final validator = Validator();
73
- final ValidationResult result = await validator.validate(skillDir);
74
- expect(result.isValid, isFalse);
75
- expect(result.errors, contains(contains('leading or trailing hyphens')));
76
- });
77
-
78
- test('fails if has trailing hyphen', () async {
79
- final Directory skillDir = await Directory('${tempDir.path}/skill-name-').create();
80
- await File(
81
- '${skillDir.path}/SKILL.md',
82
- ).writeAsString('${buildFrontmatter(name: 'skill-name-')}Body');
83
- final validator = Validator();
84
- final ValidationResult result = await validator.validate(skillDir);
85
- expect(result.isValid, isFalse);
86
- expect(result.errors, contains(contains('leading or trailing hyphens')));
87
- });
88
-
89
- test('fails if has consecutive hyphens', () async {
90
- final Directory skillDir = await Directory('${tempDir.path}/skill--name').create();
91
- await File(
92
- '${skillDir.path}/SKILL.md',
93
- ).writeAsString('${buildFrontmatter(name: 'skill--name')}Body');
94
- final validator = Validator();
95
- final ValidationResult result = await validator.validate(skillDir);
96
- expect(result.isValid, isFalse);
97
- expect(result.errors, contains(contains('consecutive hyphens')));
98
- });
99
-
100
- test('fails if name does not match directory name', () async {
101
- final Directory skillDir = await Directory('${tempDir.path}/wrong-name').create();
102
- await File(
103
- '${skillDir.path}/SKILL.md',
104
- ).writeAsString('${buildFrontmatter(name: 'right-name')}Body');
105
- final validator = Validator();
106
- final ValidationResult result = await validator.validate(skillDir);
107
- expect(result.isValid, isFalse);
108
- expect(result.errors, contains(contains('must exactly match the parent directory name')));
109
- });
110
-
111
- test('fixes name to match directory name (not replacing underscores)', () async {
112
- final Directory skillDir = await Directory('${tempDir.path}/my_skill').create();
113
- final file = File('${skillDir.path}/SKILL.md');
114
- await file.writeAsString('''
115
- ---
116
- name: wrong-name
117
- description: A test skill
118
- ---
119
- Body''');
120
-
121
- final rule = NameFormatRule();
122
- final String content = await file.readAsString();
123
- final RegExpMatch? match = RegExp(
124
- r'^---\s*\n(.*?)\n---\s*\n',
125
- dotAll: true,
126
- ).firstMatch(content);
127
- final parsedYaml = loadYaml(match!.group(1)!) as YamlMap?;
128
- final context = SkillContext(
129
- directory: skillDir,
130
- rawContent: content,
131
- parsedYaml: parsedYaml,
132
- );
133
-
134
- final String fixedContent = await rule.fix('SKILL.md', content, context.directory);
135
-
136
- expect(fixedContent, contains('name: my_skill'));
137
- });
138
- });
139
-
140
- group('Description', () {
141
- test('fails if too long (> ${DescriptionLengthRule.maxDescriptionLength} chars)', () async {
142
- final String longDesc = 'a' * (DescriptionLengthRule.maxDescriptionLength + 1);
143
- final Directory skillDir = await Directory('${tempDir.path}/skill-name').create();
144
- await File(
145
- '${skillDir.path}/SKILL.md',
146
- ).writeAsString('${buildFrontmatter(name: 'skill-name', description: longDesc)}Body');
147
- final validator = Validator();
148
- final ValidationResult result = await validator.validate(skillDir);
149
- expect(result.isValid, isFalse);
150
- expect(
151
- result.errors,
152
- contains(contains('Maximum ${DescriptionLengthRule.maxDescriptionLength} characters')),
153
- );
154
- });
155
- });
156
-
157
- group('Compatibility', () {
158
- test('fails if too long (> ${ValidYamlMetadataRule.maxCompatibilityLength} chars)', () async {
159
- final String longComp = 'a' * (ValidYamlMetadataRule.maxCompatibilityLength + 1);
160
- final Directory skillDir = await Directory('${tempDir.path}/skill-name').create();
161
- await File('${skillDir.path}/SKILL.md').writeAsString('''
162
- ---
163
- name: skill-name
164
- description: A test skill
165
- compatibility: $longComp
166
- ---
167
- Body''');
168
- final validator = Validator();
169
- final ValidationResult result = await validator.validate(skillDir);
170
- expect(result.isValid, isFalse);
171
- expect(
172
- result.errors,
173
- contains(contains('Maximum ${ValidYamlMetadataRule.maxCompatibilityLength} characters')),
174
- );
175
- });
176
- });
177
- });
178
- }
@@ -1,172 +0,0 @@
1
- // Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
2
- // for details. All rights reserved. Use of this source code is governed by a
3
- // BSD-style license that can be found in the LICENSE file.
4
-
5
- import 'dart:io';
6
-
7
- import 'package:dart_skills_lint/src/entry_point.dart';
8
- import 'package:dart_skills_lint/src/fixable_rule.dart';
9
- import 'package:dart_skills_lint/src/models/analysis_severity.dart';
10
- import 'package:dart_skills_lint/src/models/skill_context.dart';
11
- import 'package:dart_skills_lint/src/models/skill_rule.dart';
12
- import 'package:dart_skills_lint/src/models/validation_error.dart';
13
- import 'package:path/path.dart' as p;
14
- import 'package:test/test.dart';
15
-
16
- class RuleA extends SkillRule implements FixableRule {
17
- @override
18
- String get name => 'rule-a';
19
-
20
- @override
21
- AnalysisSeverity get severity => AnalysisSeverity.warning;
22
-
23
- @override
24
- Future<List<ValidationError>> validate(SkillContext context) async {
25
- return [
26
- ValidationError(
27
- ruleId: name,
28
- message: 'Error A',
29
- severity: AnalysisSeverity.warning,
30
- file: 'SKILL.md',
31
- ),
32
- ];
33
- }
34
-
35
- @override
36
- Future<String> fix(String filePath, String currentContent, Directory directory) async {
37
- return '$currentContent A';
38
- }
39
- }
40
-
41
- class RuleB extends SkillRule implements FixableRule {
42
- @override
43
- String get name => 'rule-b';
44
-
45
- @override
46
- AnalysisSeverity get severity => AnalysisSeverity.warning;
47
-
48
- @override
49
- Future<List<ValidationError>> validate(SkillContext context) async {
50
- return [
51
- ValidationError(
52
- ruleId: name,
53
- message: 'Error B',
54
- severity: AnalysisSeverity.warning,
55
- file: 'SKILL.md',
56
- ),
57
- ];
58
- }
59
-
60
- @override
61
- Future<String> fix(String filePath, String currentContent, Directory directory) async {
62
- return '$currentContent B';
63
- }
64
- }
65
-
66
- class RuleThrows extends SkillRule implements FixableRule {
67
- @override
68
- String get name => 'rule-throws';
69
-
70
- @override
71
- AnalysisSeverity get severity => AnalysisSeverity.warning;
72
-
73
- @override
74
- Future<List<ValidationError>> validate(SkillContext context) async {
75
- return [
76
- ValidationError(
77
- ruleId: name,
78
- message: 'Error Throws',
79
- severity: AnalysisSeverity.warning,
80
- file: 'SKILL.md',
81
- ),
82
- ];
83
- }
84
-
85
- @override
86
- Future<String> fix(String filePath, String currentContent, Directory directory) async {
87
- throw Exception('Fix failed');
88
- }
89
- }
90
-
91
- void main() {
92
- group('Fixer Sequential Execution', () {
93
- late Directory tempDir;
94
-
95
- setUp(() async {
96
- tempDir = await Directory.systemTemp.createTemp('fixer_test.');
97
- });
98
-
99
- tearDown(() async {
100
- await tempDir.delete(recursive: true);
101
- });
102
-
103
- test('applies fixes in order', () async {
104
- final skillDir = Directory(p.join(tempDir.path, 'test-skill'));
105
- await skillDir.create();
106
- final skillFile = File(p.join(skillDir.path, 'SKILL.md'));
107
- await skillFile.writeAsString('Original');
108
-
109
- final bool success = await validateSkillsInternal(
110
- individualSkillPaths: [skillDir.path],
111
- fixApply: true,
112
- quiet: true,
113
- customRules: [RuleA(), RuleB()],
114
- );
115
-
116
- expect(success, isFalse);
117
-
118
- final String content = await skillFile.readAsString();
119
- expect(content, 'Original A B');
120
- });
121
-
122
- test(
123
- '--fast-fail stops processing subsequent skills but completes current skill fixes',
124
- () async {
125
- final skillDir1 = Directory(p.join(tempDir.path, 'test-skill-1'));
126
- await skillDir1.create();
127
- final skillFile1 = File(p.join(skillDir1.path, 'SKILL.md'));
128
- await skillFile1.writeAsString('Original1');
129
-
130
- final skillDir2 = Directory(p.join(tempDir.path, 'test-skill-2'));
131
- await skillDir2.create();
132
- final skillFile2 = File(p.join(skillDir2.path, 'SKILL.md'));
133
- await skillFile2.writeAsString('Original2');
134
-
135
- final bool success = await validateSkillsInternal(
136
- individualSkillPaths: [skillDir1.path, skillDir2.path],
137
- fixApply: true,
138
- fastFail: true,
139
- quiet: true,
140
- customRules: [RuleA()],
141
- );
142
-
143
- expect(success, isFalse);
144
-
145
- final String content1 = await skillFile1.readAsString();
146
- expect(content1, 'Original1 A');
147
-
148
- final String content2 = await skillFile2.readAsString();
149
- expect(content2, 'Original2');
150
- },
151
- );
152
-
153
- test('handles exceptions in fix method gracefully', () async {
154
- final skillDir = Directory(p.join(tempDir.path, 'test-skill'));
155
- await skillDir.create();
156
- final skillFile = File(p.join(skillDir.path, 'SKILL.md'));
157
- await skillFile.writeAsString('Original');
158
-
159
- final bool success = await validateSkillsInternal(
160
- individualSkillPaths: [skillDir.path],
161
- fixApply: true,
162
- quiet: true,
163
- customRules: [RuleThrows()],
164
- );
165
-
166
- expect(success, isFalse);
167
-
168
- final String content = await skillFile.readAsString();
169
- expect(content, 'Original');
170
- });
171
- });
172
- }
@@ -1,63 +0,0 @@
1
- // Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
2
- // for details. All rights reserved. Use of this source code is governed by a
3
- // BSD-style license that can be found in the LICENSE file.
4
-
5
- import 'package:dart_skills_lint/src/models/ignore_entry.dart';
6
- import 'package:dart_skills_lint/src/models/skills_ignores.dart';
7
- import 'package:test/test.dart';
8
-
9
- void main() {
10
- group('IgnoreEntry Serialization', () {
11
- test('fromJson parses rule_id and file_name', () {
12
- final Map<String, dynamic> json = {
13
- IgnoreEntry.ruleIdKey: 'description_too_long',
14
- IgnoreEntry.fileNameKey: 'SKILL.md',
15
- };
16
- final entry = IgnoreEntry.fromJson(json);
17
- expect(entry.ruleId, equals('description_too_long'));
18
- expect(entry.fileName, equals('SKILL.md'));
19
- expect(entry.used, isFalse); // Default
20
- });
21
-
22
- test('toJson serializes rule_id and file_name', () {
23
- final entry = IgnoreEntry(ruleId: 'description_too_long', fileName: 'SKILL.md');
24
- final Map<String, dynamic> json = entry.toJson();
25
- expect(json[IgnoreEntry.ruleIdKey], equals('description_too_long'));
26
- expect(json[IgnoreEntry.fileNameKey], equals('SKILL.md'));
27
- expect(json.containsKey('used'), isFalse); // Suppressed
28
- });
29
- });
30
-
31
- group('SkillsIgnores Serialization', () {
32
- test('fromJson parses nested skills map', () {
33
- final Map<String, dynamic> json = {
34
- SkillsIgnores.skillsKey: {
35
- 'skill-a': [
36
- {IgnoreEntry.ruleIdKey: 'rule1', IgnoreEntry.fileNameKey: 'file1.md'},
37
- ],
38
- },
39
- };
40
- final ignores = SkillsIgnores.fromJson(json);
41
- expect(ignores.skills.containsKey('skill-a'), isTrue);
42
- expect(ignores.skills['skill-a']!.length, equals(1));
43
- expect(ignores.skills['skill-a']![0].ruleId, equals('rule1'));
44
- });
45
-
46
- test('toJson serializes nested skills map', () {
47
- final entry = IgnoreEntry(ruleId: 'rule1', fileName: 'file1.md');
48
- final ignores = SkillsIgnores(
49
- skills: {
50
- 'skill-a': [entry],
51
- },
52
- );
53
- final Map<String, dynamic> json = ignores.toJson();
54
-
55
- expect(json.containsKey(SkillsIgnores.skillsKey), isTrue);
56
- final skillsJson = json[SkillsIgnores.skillsKey] as Map<String, dynamic>;
57
- expect(skillsJson.containsKey('skill-a'), isTrue);
58
- final skillAList = skillsJson['skill-a'] as List<dynamic>;
59
- final firstItem = skillAList[0] as Map<String, dynamic>;
60
- expect(firstItem[IgnoreEntry.ruleIdKey], equals('rule1'));
61
- });
62
- });
63
- }
@@ -1,116 +0,0 @@
1
- // Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
2
- // for details. All rights reserved. Use of this source code is governed by a
3
- // BSD-style license that can be found in the LICENSE file.
4
-
5
- import 'dart:io';
6
-
7
- import 'package:dart_skills_lint/src/models/validation_error.dart';
8
- import 'package:dart_skills_lint/src/rules/disallowed_field_rule.dart';
9
- import 'package:dart_skills_lint/src/validator.dart';
10
- import 'package:test/test.dart';
11
-
12
- import 'test_utils.dart';
13
-
14
- void main() {
15
- group('Metadata (YAML) Validation', () {
16
- late Directory tempDir;
17
-
18
- setUp(() async {
19
- tempDir = await Directory.systemTemp.createTemp('metadata_test.');
20
- });
21
-
22
- tearDown(() async {
23
- if (tempDir.existsSync()) {
24
- await tempDir.delete(recursive: true);
25
- }
26
- });
27
-
28
- test('fails if YAML metadata is invalid', () async {
29
- await File('${tempDir.path}/SKILL.md').writeAsString('''
30
- ---
31
- invalid: yaml: frontmatter
32
- ---
33
- Body''');
34
- final validator = Validator();
35
- final ValidationResult result = await validator.validate(tempDir);
36
-
37
- expect(result.isValid, isFalse);
38
- expect(result.errors, contains(contains('Invalid YAML metadata')));
39
- });
40
-
41
- test('fails if required field "name" is missing', () async {
42
- await File('${tempDir.path}/SKILL.md').writeAsString('''
43
- ---
44
- description: A test skill
45
- ---
46
- Body''');
47
- final validator = Validator();
48
- final ValidationResult result = await validator.validate(tempDir);
49
-
50
- expect(result.isValid, isFalse);
51
- expect(result.errors, contains(contains('Missing required field: name')));
52
- });
53
-
54
- test('fails if required field "description" is missing', () async {
55
- await File('${tempDir.path}/SKILL.md').writeAsString('''
56
- ---
57
- name: metadata-test
58
- ---
59
- Body''');
60
- final validator = Validator();
61
- final ValidationResult result = await validator.validate(tempDir);
62
-
63
- expect(result.isValid, isFalse);
64
- expect(result.errors, contains(contains('Missing required field: description')));
65
- });
66
-
67
- test('passes without warning if disallowed fields are present', () async {
68
- final skillDir = Directory('${tempDir.path}/metadata-test');
69
- await skillDir.create();
70
- await File('${skillDir.path}/SKILL.md').writeAsString('''
71
- ---
72
- name: metadata-test
73
- description: A test skill
74
- extra-field: not allowed
75
- ---
76
- Body''');
77
-
78
- final validator = Validator();
79
- final ValidationResult result = await validator.validate(skillDir);
80
-
81
- expect(result.isValid, isTrue);
82
- expect(result.warnings, isEmpty);
83
-
84
- final Iterable<ValidationError> disallowedErrors = result.validationErrors.where(
85
- (e) => e.ruleId == DisallowedFieldRule.ruleName,
86
- );
87
- expect(disallowedErrors, isEmpty);
88
- });
89
-
90
- test('passes with all allowed fields and valid YAML', () async {
91
- await File('${tempDir.path}/SKILL.md').writeAsString('''
92
- ---
93
- name: metadata-test
94
- description: A test skill
95
- license: MIT
96
- compatibility: Python 3.10
97
- metadata:
98
- version: 1.0.0
99
- allowed-tools: git
100
- ---
101
- Body''');
102
- final validator = Validator();
103
- // We need to make sure directory name matches name in metadata
104
- final skillDir = Directory('${tempDir.path}/metadata-test');
105
- await skillDir.create();
106
- await File(
107
- '${skillDir.path}/SKILL.md',
108
- ).writeAsString('${buildFrontmatter(name: 'metadata-test')}Body');
109
-
110
- final ValidationResult result = await validator.validate(skillDir);
111
-
112
- expect(result.isValid, isTrue, reason: result.errors.isEmpty ? '' : result.errors.first);
113
- expect(result.errors, isEmpty);
114
- });
115
- });
116
- }
@@ -1,70 +0,0 @@
1
- // Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
2
- // for details. All rights reserved. Use of this source code is governed by a
3
- // BSD-style license that can be found in the LICENSE file.
4
-
5
- import 'dart:io';
6
-
7
- import 'package:dart_skills_lint/src/models/analysis_severity.dart';
8
- import 'package:dart_skills_lint/src/rules/absolute_paths_rule.dart';
9
- import 'package:dart_skills_lint/src/rules/relative_paths_rule.dart';
10
- import 'package:dart_skills_lint/src/validator.dart';
11
- import 'package:test/test.dart';
12
-
13
- import 'test_utils.dart';
14
-
15
- void main() {
16
- group('Relative Path Flag Validation', () {
17
- late Directory tempDir;
18
-
19
- setUp(() async {
20
- tempDir = await Directory.systemTemp.createTemp('relative_path_test.');
21
- });
22
-
23
- tearDown(() async {
24
- if (tempDir.existsSync()) {
25
- await tempDir.delete(recursive: true);
26
- }
27
- });
28
-
29
- test('validates links when relativePathsSeverity = warning', () async {
30
- final skillDir = Directory('${tempDir.path}/test-skill');
31
- await skillDir.create();
32
- await File('${skillDir.path}/SKILL.md').writeAsString(
33
- '${buildFrontmatter(name: 'test-skill')}Body with [broken link](missing.md) and [absolute link](/absolute/path.md)',
34
- );
35
-
36
- final validator = Validator(
37
- ruleOverrides: {
38
- RelativePathsRule.ruleName: AnalysisSeverity.warning,
39
- AbsolutePathsRule.ruleName: AnalysisSeverity.error,
40
- },
41
- );
42
- final ValidationResult result = await validator.validate(skillDir);
43
-
44
- expect(result.isValid, isFalse);
45
- expect(
46
- result.errors,
47
- contains(contains('Absolute filepath found in link: /absolute/path.md')),
48
- );
49
- expect(result.warnings, contains(contains('Linked file does not exist: missing.md')));
50
- });
51
-
52
- test('passes when relativePathsSeverity = warning and links are valid', () async {
53
- final skillDir = Directory('${tempDir.path}/test-skill');
54
- await skillDir.create();
55
- await File('${skillDir.path}/SKILL.md').writeAsString(
56
- '${buildFrontmatter(name: 'test-skill')}Body with [valid relative link](valid.md)',
57
- );
58
- await File('${skillDir.path}/valid.md').writeAsString('Valid file content');
59
-
60
- final validator = Validator(
61
- ruleOverrides: {RelativePathsRule.ruleName: AnalysisSeverity.warning},
62
- );
63
- final ValidationResult result = await validator.validate(skillDir);
64
-
65
- expect(result.isValid, isTrue);
66
- expect(result.errors, isEmpty);
67
- expect(result.warnings, isEmpty);
68
- });
69
- });
70
- }