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,292 +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:path/path.dart' as p;
9
- import 'package:test/test.dart';
10
- import 'package:test_process/test_process.dart';
11
-
12
- void main() {
13
- group('Configuration File Integration', () {
14
- late Directory tempDir;
15
-
16
- setUp(() async {
17
- tempDir = await Directory.systemTemp.createTemp('config_test.');
18
- });
19
-
20
- tearDown(() async {
21
- if (tempDir.existsSync()) {
22
- await tempDir.delete(recursive: true);
23
- }
24
- });
25
-
26
- test('obeys disabled relative paths in config', () async {
27
- final Directory skillDir = await Directory('${tempDir.path}/test-skill').create();
28
- await File('${skillDir.path}/SKILL.md').writeAsString('''
29
- ---
30
- name: test-skill
31
- description: A test skill
32
- ---
33
- [broken](missing.md)''');
34
-
35
- await File('${tempDir.path}/dart_skills_lint.yaml').writeAsString('''
36
- dart_skills_lint:
37
- rules:
38
- check-relative-paths: disabled
39
- ''');
40
-
41
- final TestProcess process = await TestProcess.start('dart', [
42
- p.normalize(p.absolute('bin/cli.dart')),
43
- '-s',
44
- 'test-skill',
45
- ], workingDirectory: tempDir.path);
46
-
47
- final List<String> stdout = await process.stdout.rest.toList();
48
- expect(stdout.join('\n'), contains('Skill is valid.'));
49
- await process.shouldExit(0);
50
- });
51
-
52
- test('obeys warning absolute paths in config', () async {
53
- final Directory skillDir = await Directory('${tempDir.path}/test-skill').create();
54
- await File('${skillDir.path}/SKILL.md').writeAsString('''
55
- ---
56
- name: test-skill
57
- description: A test skill
58
- ---
59
- [absolute](/absolute/path.md)''');
60
-
61
- await File('${tempDir.path}/dart_skills_lint.yaml').writeAsString('''
62
- dart_skills_lint:
63
- rules:
64
- check-absolute-paths: warning
65
- ''');
66
-
67
- final TestProcess process = await TestProcess.start('dart', [
68
- p.normalize(p.absolute('bin/cli.dart')),
69
- '-s',
70
- 'test-skill',
71
- ], workingDirectory: tempDir.path);
72
-
73
- final List<String> stdout = await process.stdout.rest.toList();
74
- expect(stdout.join('\n'), contains('Warnings:'));
75
- await process.shouldExit(0);
76
- });
77
-
78
- test('CLI flags override config', () async {
79
- final Directory skillDir = await Directory('${tempDir.path}/test-skill').create();
80
- await File('${skillDir.path}/SKILL.md').writeAsString('''
81
- ---
82
- name: test-skill
83
- description: A test skill
84
- ---
85
- [broken](missing.md)''');
86
-
87
- await File('${tempDir.path}/dart_skills_lint.yaml').writeAsString('''
88
- dart_skills_lint:
89
- rules:
90
- check-relative-paths: disabled
91
- ''');
92
-
93
- final TestProcess process = await TestProcess.start('dart', [
94
- p.normalize(p.absolute('bin/cli.dart')),
95
- '-s',
96
- 'test-skill',
97
- '--check-relative-paths',
98
- ], workingDirectory: tempDir.path);
99
-
100
- final List<String> stderr = await process.stderr.rest.toList();
101
- expect(stderr.join('\n'), contains('Skill is invalid:'));
102
- await process.shouldExit(1);
103
- });
104
-
105
- test('writes empty ignore-file if missing and specified in config', () async {
106
- await Directory('${tempDir.path}/test-skill').create();
107
- await File('${tempDir.path}/test-skill/SKILL.md').writeAsString('''
108
- ---
109
- name: test-skill
110
- description: A test skill
111
- ---
112
- Body''');
113
-
114
- const ignorePath = 'custom_ignore.json';
115
- await File('${tempDir.path}/dart_skills_lint.yaml').writeAsString('''
116
- dart_skills_lint:
117
- directories:
118
- - path: "test-skill"
119
- ignore_file: "$ignorePath"
120
- ''');
121
-
122
- final TestProcess process = await TestProcess.start('dart', [
123
- p.normalize(p.absolute('bin/cli.dart')),
124
- '-s',
125
- 'test-skill',
126
- ], workingDirectory: tempDir.path);
127
-
128
- final List<String> stdout = await process.stdout.rest.toList();
129
- expect(stdout.join('\n'), contains('File not found generating-baseline'));
130
- await process.shouldExit(0);
131
-
132
- final writtenFile = File('${tempDir.path}/$ignorePath');
133
- expect(writtenFile.existsSync(), isTrue);
134
- final String fileContent = await writtenFile.readAsString();
135
- expect(fileContent, contains('"skills":'));
136
- });
137
-
138
- test('ignores config when --ignore-config is passed', () async {
139
- final Directory skillDir = await Directory('${tempDir.path}/TEST-SKILL').create();
140
- await File('${skillDir.path}/SKILL.md').writeAsString('''
141
- ---
142
- name: TEST-SKILL
143
- description: A test skill
144
- license: MIT
145
- ---
146
- Body''');
147
-
148
- await File('${tempDir.path}/dart_skills_lint.yaml').writeAsString('''
149
- dart_skills_lint:
150
- rules:
151
- invalid-skill-name: disabled
152
- ''');
153
-
154
- // 1. Run without --ignore-config. Should pass because config disables the check.
155
- final TestProcess passProcess = await TestProcess.start('dart', [
156
- p.normalize(p.absolute('bin/cli.dart')),
157
- '-s',
158
- 'TEST-SKILL',
159
- ], workingDirectory: tempDir.path);
160
- await passProcess.shouldExit(0);
161
-
162
- // 2. Run with --ignore-config. Should fail because config is ignored and default is used.
163
- final TestProcess failProcess = await TestProcess.start('dart', [
164
- p.normalize(p.absolute('bin/cli.dart')),
165
- '-s',
166
- 'TEST-SKILL',
167
- '--ignore-config',
168
- ], workingDirectory: tempDir.path);
169
- await failProcess.shouldExit(1);
170
- });
171
-
172
- test('ignores config when generating baseline with --ignore-config', () async {
173
- final Directory skillDir = await Directory('${tempDir.path}/TEST-SKILL').create();
174
- await File('${skillDir.path}/SKILL.md').writeAsString('''
175
- ---
176
- name: TEST-SKILL
177
- description: A test skill
178
- license: MIT
179
- ---
180
- Body''');
181
-
182
- await File('${tempDir.path}/dart_skills_lint.yaml').writeAsString('''
183
- dart_skills_lint:
184
- rules:
185
- invalid-skill-name: disabled
186
- ''');
187
-
188
- // 1. Generate baseline with --ignore-config. It should ignore config (so the rule is enabled) and find violations to generate baseline for!
189
- final TestProcess genProcess = await TestProcess.start('dart', [
190
- p.normalize(p.absolute('bin/cli.dart')),
191
- '-s',
192
- 'TEST-SKILL',
193
- '--generate-baseline',
194
- '--ignore-config',
195
- ], workingDirectory: tempDir.path);
196
- await genProcess.shouldExit(0); // Exits 0 if --generate-baseline passed
197
-
198
- final ignoreFile = File('${skillDir.parent.path}/$defaultIgnoreFileName');
199
- expect(ignoreFile.existsSync(), isTrue);
200
-
201
- final String content = await ignoreFile.readAsString();
202
- expect(content, contains('invalid-skill-name')); // It should generate baseline for it!
203
- });
204
-
205
- test('fails on invalid top-level key in config by default', () async {
206
- await Directory('${tempDir.path}/test-skill').create();
207
- await File('${tempDir.path}/test-skill/SKILL.md').writeAsString('''
208
- ---
209
- name: test-skill
210
- description: A test skill
211
- ---
212
- Body''');
213
-
214
- await File('${tempDir.path}/dart_skills_lint.yaml').writeAsString('''
215
- dart_skills_lint:
216
- invalid-key: value
217
- ''');
218
-
219
- final TestProcess process = await TestProcess.start('dart', [
220
- p.normalize(p.absolute('bin/cli.dart')),
221
- '-s',
222
- 'test-skill',
223
- ], workingDirectory: tempDir.path);
224
-
225
- final List<String> stderr = await process.stderr.rest.toList();
226
- expect(
227
- stderr.join('\n'),
228
- contains('Configuration error: Unrecognized top-level key "invalid-key"'),
229
- );
230
- await process.shouldExit(1);
231
- });
232
-
233
- test('fails on invalid directory key in config by default', () async {
234
- await Directory('${tempDir.path}/test-skill').create();
235
- await File('${tempDir.path}/test-skill/SKILL.md').writeAsString('''
236
- ---
237
- name: test-skill
238
- description: A test skill
239
- ---
240
- Body''');
241
-
242
- await File('${tempDir.path}/dart_skills_lint.yaml').writeAsString('''
243
- dart_skills_lint:
244
- directories:
245
- - path: "test-skill"
246
- invalid-dir-key: value
247
- ''');
248
-
249
- final TestProcess process = await TestProcess.start('dart', [
250
- p.normalize(p.absolute('bin/cli.dart')),
251
- '-s',
252
- 'test-skill',
253
- ], workingDirectory: tempDir.path);
254
-
255
- final List<String> stderr = await process.stderr.rest.toList();
256
- expect(
257
- stderr.join('\n'),
258
- contains('Configuration error: Unrecognized key "invalid-dir-key"'),
259
- );
260
- await process.shouldExit(1);
261
- });
262
-
263
- test('succeeds with warning on invalid key when --allow-misconfigured-keys passed', () async {
264
- await Directory('${tempDir.path}/test-skill').create();
265
- await File('${tempDir.path}/test-skill/SKILL.md').writeAsString('''
266
- ---
267
- name: test-skill
268
- description: A test skill
269
- ---
270
- Body''');
271
-
272
- await File('${tempDir.path}/dart_skills_lint.yaml').writeAsString('''
273
- dart_skills_lint:
274
- invalid-key: value
275
- ''');
276
-
277
- final TestProcess process = await TestProcess.start('dart', [
278
- p.normalize(p.absolute('bin/cli.dart')),
279
- '-s',
280
- 'test-skill',
281
- '--allow-misconfigured-keys',
282
- ], workingDirectory: tempDir.path);
283
-
284
- final List<String> stdout = await process.stdout.rest.toList();
285
- expect(
286
- stdout.join('\n'),
287
- contains('Configuration warning: Unrecognized top-level key "invalid-key"'),
288
- );
289
- await process.shouldExit(0);
290
- });
291
- });
292
- }
@@ -1,122 +0,0 @@
1
- import 'dart:async';
2
- import 'dart:io';
3
- import 'package:dart_skills_lint/dart_skills_lint.dart';
4
- import 'package:logging/logging.dart';
5
- import 'package:test/test.dart';
6
-
7
- class CustomRule extends SkillRule {
8
- @override
9
- final String name = 'custom-rule';
10
-
11
- @override
12
- final AnalysisSeverity severity = AnalysisSeverity.error;
13
-
14
- @override
15
- Future<List<ValidationError>> validate(SkillContext context) async {
16
- final errors = <ValidationError>[];
17
- if (context.rawContent.contains('TRIGGER_ERROR')) {
18
- errors.add(
19
- ValidationError(
20
- ruleId: name,
21
- severity: severity,
22
- file: 'SKILL.md',
23
- message: 'Custom rule triggered',
24
- ),
25
- );
26
- }
27
- return errors;
28
- }
29
- }
30
-
31
- class MismatchRule extends SkillRule {
32
- @override
33
- final String name = 'mismatch-rule';
34
-
35
- @override
36
- final AnalysisSeverity severity = AnalysisSeverity.warning;
37
-
38
- @override
39
- Future<List<ValidationError>> validate(SkillContext context) async {
40
- return [
41
- ValidationError(
42
- ruleId: name,
43
- severity: AnalysisSeverity.error, // Mismatch!
44
- file: 'SKILL.md',
45
- message: 'Triggered',
46
- ),
47
- ];
48
- }
49
- }
50
-
51
- void main() {
52
- group('Custom Rules', () {
53
- late Directory tempDir;
54
-
55
- setUp(() async {
56
- tempDir = await Directory.systemTemp.createTemp('custom_rule_test.');
57
- });
58
-
59
- tearDown(() async {
60
- if (tempDir.existsSync()) {
61
- await tempDir.delete(recursive: true);
62
- }
63
- });
64
-
65
- test('Validator runs custom rule', () async {
66
- final Directory skillDir = await Directory('${tempDir.path}/skill-name').create();
67
- await File('${skillDir.path}/SKILL.md').writeAsString('''
68
- ---
69
- name: skill-name
70
- description: A test skill
71
- ---
72
- TRIGGER_ERROR''');
73
-
74
- final validator = Validator(customRules: [CustomRule()]);
75
- final ValidationResult result = await validator.validate(skillDir);
76
-
77
- expect(result.isValid, isFalse);
78
- expect(result.errors, contains(contains('Custom rule triggered')));
79
- });
80
-
81
- test('Validator logs warning on severity mismatch', () async {
82
- final Directory skillDir = await Directory('${tempDir.path}/skill-name-3').create();
83
- await File('${skillDir.path}/SKILL.md').writeAsString('''
84
- ---
85
- name: skill-name-3
86
- description: A test skill
87
- ---
88
- Body''');
89
-
90
- final validator = Validator(customRules: [MismatchRule()]);
91
-
92
- final logs = <String>[];
93
- final StreamSubscription<LogRecord> subscription = Logger('dart_skills_lint').onRecord.listen(
94
- (record) {
95
- logs.add(record.message);
96
- },
97
- );
98
-
99
- try {
100
- await validator.validate(skillDir);
101
- } finally {
102
- await subscription.cancel();
103
- }
104
-
105
- expect(
106
- logs,
107
- contains(
108
- contains(
109
- 'Rule "mismatch-rule" used severity AnalysisSeverity.error instead of defined AnalysisSeverity.warning',
110
- ),
111
- ),
112
- );
113
- });
114
-
115
- test('Validator throws ArgumentError on duplicate rule names', () {
116
- final rule1 = CustomRule();
117
- final rule2 = CustomRule(); // Same name 'custom-rule'
118
-
119
- expect(() => Validator(customRules: [rule1, rule2]), throwsArgumentError);
120
- });
121
- });
122
- }
@@ -1,163 +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:convert';
6
- import 'dart:io';
7
-
8
- import 'package:dart_skills_lint/src/models/analysis_severity.dart';
9
- import 'package:dart_skills_lint/src/validator.dart';
10
- import 'package:path/path.dart' as p;
11
- import 'package:test/test.dart';
12
-
13
- class MockInaccessibleFile implements File {
14
- MockInaccessibleFile(this._path);
15
- final String _path;
16
-
17
- @override
18
- String get path => _path;
19
-
20
- @override
21
- bool existsSync() => true;
22
-
23
- @override
24
- Future<String> readAsString({Encoding encoding = utf8}) async {
25
- throw FileSystemException('File is inaccessible', _path);
26
- }
27
-
28
- @override
29
- dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
30
- }
31
-
32
- base class TestIOOverrides extends IOOverrides {
33
- TestIOOverrides(this.targetPath);
34
- final String targetPath;
35
-
36
- @override
37
- File createFile(String path) {
38
- if (path == targetPath) {
39
- return MockInaccessibleFile(path);
40
- }
41
- return super.createFile(path);
42
- }
43
- }
44
-
45
- void main() {
46
- group('Directory Structure Validation', () {
47
- late Directory tempDir;
48
-
49
- setUp(() async {
50
- tempDir = await Directory.systemTemp.createTemp('skill_test.');
51
- });
52
-
53
- tearDown(() async {
54
- if (tempDir.existsSync()) {
55
- await tempDir.delete(recursive: true);
56
- }
57
- });
58
-
59
- test('fails if directory does not exist', () async {
60
- final nonExistentDir = Directory('path/to/nothing');
61
- final validator = Validator();
62
- final ValidationResult result = await validator.validate(nonExistentDir);
63
-
64
- expect(result.isValid, isFalse);
65
- expect(result.errors, contains(contains('Directory does not exist')));
66
- });
67
-
68
- test('fails if path is a file', () async {
69
- final file = File('${tempDir.path}/some_file');
70
- await file.create();
71
- final validator = Validator();
72
- final ValidationResult result = await validator.validate(Directory(file.path));
73
-
74
- expect(result.isValid, isFalse);
75
- expect(result.errors, contains(contains('is not a directory')));
76
- });
77
-
78
- test('fails if SKILL.md is missing', () async {
79
- final validator = Validator();
80
- final ValidationResult result = await validator.validate(tempDir);
81
-
82
- expect(result.isValid, isFalse);
83
- expect(result.errors, contains(contains('SKILL.md is missing')));
84
- });
85
-
86
- test('fails if SKILL.md cannot be read', () async {
87
- final skillDir = Directory(p.join(tempDir.path, 'test-skill-inaccessible'));
88
- await skillDir.create();
89
- final String filePath = p.join(skillDir.path, 'SKILL.md');
90
-
91
- final overrides = TestIOOverrides(filePath);
92
- await IOOverrides.runWithIOOverrides(() async {
93
- try {
94
- final validator = Validator();
95
- final ValidationResult validationResult = await validator.validate(skillDir);
96
-
97
- // ignore: avoid_print
98
- print(
99
- 'DEBUG errors: ${validationResult.validationErrors.map((e) => "${e.ruleId}: ${e.message}").toList()}',
100
- );
101
- expect(validationResult.isValid, isFalse);
102
- expect(
103
- validationResult.validationErrors.any(
104
- (e) => e.ruleId == Validator.skillFileInaccessible,
105
- ),
106
- isTrue,
107
- );
108
- } catch (e, s) {
109
- fail('Unexpected exception during validation: $e\n$s');
110
- }
111
- }, overrides);
112
- });
113
-
114
- test('obeys skill-file-inaccessible severity override', () async {
115
- final skillDir = Directory(p.join(tempDir.path, 'test-skill-override'));
116
- await skillDir.create();
117
- final String filePath = p.join(skillDir.path, 'SKILL.md');
118
-
119
- final overrides = TestIOOverrides(filePath);
120
- await IOOverrides.runWithIOOverrides(() async {
121
- try {
122
- final validator = Validator(
123
- ruleOverrides: {Validator.skillFileInaccessible: AnalysisSeverity.warning},
124
- );
125
- final ValidationResult validationResult = await validator.validate(skillDir);
126
-
127
- // ignore: avoid_print
128
- print(
129
- 'DEBUG errors (override): ${validationResult.validationErrors.map((e) => "${e.ruleId}: ${e.message}").toList()}',
130
- );
131
- expect(validationResult.isValid, isTrue);
132
- expect(
133
- validationResult.validationErrors.any(
134
- (e) =>
135
- e.ruleId == Validator.skillFileInaccessible &&
136
- e.severity == AnalysisSeverity.warning,
137
- ),
138
- isTrue,
139
- );
140
- } catch (e, s) {
141
- fail('Unexpected exception during validation: $e\n$s');
142
- }
143
- }, overrides);
144
- });
145
-
146
- test('passes if directory exists and contains SKILL.md', () async {
147
- final skillDir = Directory(p.join(tempDir.path, 'test-skill'));
148
- await skillDir.create();
149
- await File(p.join(skillDir.path, 'SKILL.md')).writeAsString('''
150
- ---
151
- name: test-skill
152
- description: A test skill
153
- ---
154
- Body''');
155
-
156
- final validator = Validator();
157
- final ValidationResult result = await validator.validate(skillDir);
158
-
159
- expect(result.isValid, isTrue, reason: result.errors.isEmpty ? '' : result.errors.first);
160
- expect(result.errors, isEmpty);
161
- });
162
- });
163
- }