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.
- package/bin.js +1 -1
- package/index.js +18 -12
- package/package.json +1 -1
- package/skills/VERSION.md +61 -175
- package/skills/design-planning/ai-coding-rules/SKILL.md +13 -5
- package/skills/design-planning/design-to-code/SKILL.md +14 -5
- package/skills/design-planning/enterprise-spec/SKILL.md +13 -5
- package/skills/design-planning/flutter-av/SKILL.md +16 -5
- package/skills/design-planning/flutter-map/SKILL.md +14 -5
- package/skills/design-planning/function-sdd/SKILL.md +13 -5
- package/skills/design-planning/global-overlay-stack-standard/SKILL.md +14 -4
- package/skills/design-planning/ui-motion-interaction-standard/SKILL.md +14 -4
- package/skills/design-planning/ui-sdd-specialized/SKILL.md +14 -5
- package/skills/development-execution/flutter-errors/SKILL.md +15 -5
- package/skills/quality-assurance/bdd-acceptance/SKILL.md +14 -5
- package/skills/quality-assurance/flutter-test/SKILL.md +16 -5
- package/skills/requirement-analysis/sdd/mock_sdd.md +156 -0
- package/skills/rules/project_rules.md +127 -538
- package/skills/rules/user_rules.md +263 -0
- package/skills/special-tools/env-check/SKILL.md +13 -5
- package/skills/special-tools/ios-full-auto-debug/SKILL.md +15 -5
- package/skills/flutter-skills/.github/dependabot.yaml +0 -15
- package/skills/flutter-skills/.github/workflows/dart_skills_lint_workflow.yaml +0 -68
- package/skills/flutter-skills/.github/workflows/skills_tool.yaml +0 -51
- package/skills/flutter-skills/CODE_OF_CONDUCT.md +0 -3
- package/skills/flutter-skills/CONTRIBUTING.md +0 -36
- package/skills/flutter-skills/LICENSE +0 -26
- package/skills/flutter-skills/README.md +0 -50
- package/skills/flutter-skills/pubspec.yaml +0 -9
- package/skills/flutter-skills/resources/flutter_skills.yaml +0 -434
- package/skills/flutter-skills/skills/flutter-add-integration-test/SKILL.md +0 -163
- package/skills/flutter-skills/skills/flutter-add-widget-preview/SKILL.md +0 -145
- package/skills/flutter-skills/skills/flutter-add-widget-test/SKILL.md +0 -154
- package/skills/flutter-skills/skills/flutter-apply-architecture-best-practices/SKILL.md +0 -162
- package/skills/flutter-skills/skills/flutter-build-responsive-layout/SKILL.md +0 -139
- package/skills/flutter-skills/skills/flutter-fix-layout-issues/SKILL.md +0 -130
- package/skills/flutter-skills/skills/flutter-implement-json-serialization/SKILL.md +0 -153
- package/skills/flutter-skills/skills/flutter-setup-declarative-routing/SKILL.md +0 -255
- package/skills/flutter-skills/skills/flutter-setup-localization/SKILL.md +0 -210
- package/skills/flutter-skills/skills/flutter-use-http-package/SKILL.md +0 -175
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/add-dart-lint-validation-rule/SKILL.md +0 -196
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-best-practices/SKILL.md +0 -65
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-checks-migration/SKILL.md +0 -158
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-cli-app-best-practices/SKILL.md +0 -168
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-doc-validation/SKILL.md +0 -87
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-long-lines/SKILL.md +0 -101
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-matcher-best-practices/SKILL.md +0 -136
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-modern-features/SKILL.md +0 -266
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-package-maintenance/SKILL.md +0 -92
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-coverage/SKILL.md +0 -92
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-coverage/example/lib/src/calculator.dart +0 -7
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-coverage/example/pubspec.yaml +0 -8
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-coverage/example/test/calculator_test.dart +0 -11
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-coverage/scripts/interpret_coverage.dart +0 -95
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-coverage/scripts/pubspec.yaml +0 -6
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-coverage/scripts/test/interpret_coverage_test.dart +0 -93
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-fundamentals/SKILL.md +0 -173
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/definition-of-done/SKILL.md +0 -27
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/flutter_skills_ignore.json +0 -3
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/grill-me/SKILL.md +0 -10
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/ignore.json +0 -3
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/test-driven-development/SKILL.md +0 -371
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/test-driven-development/testing-anti-patterns.md +0 -299
- package/skills/flutter-skills/tool/dart_skills_lint/AUTHORS +0 -7
- package/skills/flutter-skills/tool/dart_skills_lint/CHANGELOG.md +0 -12
- package/skills/flutter-skills/tool/dart_skills_lint/CONTRIBUTING.md +0 -51
- package/skills/flutter-skills/tool/dart_skills_lint/LICENSE +0 -27
- package/skills/flutter-skills/tool/dart_skills_lint/README.md +0 -203
- package/skills/flutter-skills/tool/dart_skills_lint/analysis_options.yaml +0 -296
- package/skills/flutter-skills/tool/dart_skills_lint/bench/README.md +0 -23
- package/skills/flutter-skills/tool/dart_skills_lint/bench/baseline_throughput.dart +0 -230
- package/skills/flutter-skills/tool/dart_skills_lint/bin/cli.dart +0 -10
- package/skills/flutter-skills/tool/dart_skills_lint/dart_skills_lint.yaml +0 -14
- package/skills/flutter-skills/tool/dart_skills_lint/documentation/feature_design_docs/PRODUCTION_READYNESS.md +0 -48
- package/skills/flutter-skills/tool/dart_skills_lint/documentation/feature_design_docs/completion_migration_plan.md +0 -99
- package/skills/flutter-skills/tool/dart_skills_lint/documentation/feature_design_docs/legacy_patterns_report.md +0 -110
- package/skills/flutter-skills/tool/dart_skills_lint/documentation/feature_design_docs/pub_vs_skill_report.md +0 -56
- package/skills/flutter-skills/tool/dart_skills_lint/documentation/knowledge/SPECIFICATION.md +0 -79
- package/skills/flutter-skills/tool/dart_skills_lint/documentation/knowledge/architecture_overview.md +0 -64
- package/skills/flutter-skills/tool/dart_skills_lint/lib/dart_skills_lint.dart +0 -11
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/config_parser.dart +0 -156
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/entry_point.dart +0 -354
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/fixable_rule.dart +0 -20
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/analysis_severity.dart +0 -15
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/check_type.dart +0 -17
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/ignore_entry.dart +0 -34
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/ignore_entry.g.dart +0 -19
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/skill_context.dart +0 -27
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/skill_rule.dart +0 -27
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/skills_ignores.dart +0 -26
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/skills_ignores.g.dart +0 -24
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/validation_error.dart +0 -31
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rule_registry.dart +0 -79
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rules/absolute_paths_rule.dart +0 -74
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rules/description_length_rule.dart +0 -49
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rules/disallowed_field_rule.dart +0 -61
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rules/name_format_rule.dart +0 -167
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rules/relative_paths_rule.dart +0 -72
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rules/trailing_whitespace_rule.dart +0 -93
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rules/valid_yaml_metadata_rule.dart +0 -74
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/skills_ignores_storage.dart +0 -36
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/validation_session.dart +0 -559
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/validator.dart +0 -238
- package/skills/flutter-skills/tool/dart_skills_lint/pubspec.yaml +0 -28
- package/skills/flutter-skills/tool/dart_skills_lint/skills/README.md +0 -10
- package/skills/flutter-skills/tool/dart_skills_lint/skills/dart-skills-lint-validation/SKILL.md +0 -195
- package/skills/flutter-skills/tool/dart_skills_lint/skills-lock.json +0 -75
- package/skills/flutter-skills/tool/dart_skills_lint/test/absolute_paths_test.dart +0 -167
- package/skills/flutter-skills/tool/dart_skills_lint/test/cli_integration_test.dart +0 -683
- package/skills/flutter-skills/tool/dart_skills_lint/test/config_file_test.dart +0 -292
- package/skills/flutter-skills/tool/dart_skills_lint/test/custom_rule_test.dart +0 -122
- package/skills/flutter-skills/tool/dart_skills_lint/test/directory_structure_test.dart +0 -163
- package/skills/flutter-skills/tool/dart_skills_lint/test/field_constraints_test.dart +0 -178
- package/skills/flutter-skills/tool/dart_skills_lint/test/fixer_test.dart +0 -172
- package/skills/flutter-skills/tool/dart_skills_lint/test/ignore_models_test.dart +0 -63
- package/skills/flutter-skills/tool/dart_skills_lint/test/metadata_validation_test.dart +0 -116
- package/skills/flutter-skills/tool/dart_skills_lint/test/relative_path_flag_test.dart +0 -70
- package/skills/flutter-skills/tool/dart_skills_lint/test/relative_paths_test.dart +0 -172
- package/skills/flutter-skills/tool/dart_skills_lint/test/resolve_rules_test.dart +0 -82
- package/skills/flutter-skills/tool/dart_skills_lint/test/rule_naming_test.dart +0 -29
- package/skills/flutter-skills/tool/dart_skills_lint/test/skills_ignores_storage_test.dart +0 -89
- package/skills/flutter-skills/tool/dart_skills_lint/test/test_utils.dart +0 -19
- package/skills/flutter-skills/tool/dart_skills_lint/test/trailing_whitespace_test.dart +0 -152
- package/skills/flutter-skills/tool/generator/README.md +0 -150
- package/skills/flutter-skills/tool/generator/analysis_options.yaml +0 -143
- package/skills/flutter-skills/tool/generator/bin/skills.dart +0 -73
- package/skills/flutter-skills/tool/generator/lib/src/commands/base_skill_command.dart +0 -87
- package/skills/flutter-skills/tool/generator/lib/src/commands/base_yaml_command.dart +0 -83
- package/skills/flutter-skills/tool/generator/lib/src/commands/generate_skill_command.dart +0 -92
- package/skills/flutter-skills/tool/generator/lib/src/commands/update_readme_command.dart +0 -150
- package/skills/flutter-skills/tool/generator/lib/src/commands/update_skill_command.dart +0 -97
- package/skills/flutter-skills/tool/generator/lib/src/commands/validate_skill_command.dart +0 -284
- package/skills/flutter-skills/tool/generator/lib/src/models/skill_params.dart +0 -41
- package/skills/flutter-skills/tool/generator/lib/src/services/gemini_service.dart +0 -310
- package/skills/flutter-skills/tool/generator/lib/src/services/markdown_converter.dart +0 -226
- package/skills/flutter-skills/tool/generator/lib/src/services/prompts.dart +0 -72
- package/skills/flutter-skills/tool/generator/lib/src/services/resource_fetcher_service.dart +0 -84
- package/skills/flutter-skills/tool/generator/lib/src/services/skill_instructions.dart +0 -30
- package/skills/flutter-skills/tool/generator/pubspec.yaml +0 -32
- package/skills/flutter-skills/tool/generator/test/commands/base_skill_command_test.dart +0 -131
- package/skills/flutter-skills/tool/generator/test/commands/validate_skills_input_test.dart +0 -263
- package/skills/flutter-skills/tool/generator/test/custom_skill_rules/last_modified_rule.dart +0 -32
- package/skills/flutter-skills/tool/generator/test/generate_skills_retry_test.dart +0 -105
- package/skills/flutter-skills/tool/generator/test/generate_skills_test.dart +0 -519
- package/skills/flutter-skills/tool/generator/test/lint_skills_test.dart +0 -34
- package/skills/flutter-skills/tool/generator/test/markdown_converter_test.dart +0 -103
- package/skills/flutter-skills/tool/generator/test/markdown_table_test.dart +0 -131
- package/skills/flutter-skills/tool/generator/test/models/skill_params_test.dart +0 -37
- package/skills/flutter-skills/tool/generator/test/services/gemini_service_test.dart +0 -291
- package/skills/flutter-skills/tool/generator/test/services/markdown_converter_test.dart +0 -156
- package/skills/flutter-skills/tool/generator/test/services/resource_fetcher_service_test.dart +0 -188
- package/skills/flutter-skills/tool/generator/test/update_skills_test.dart +0 -241
- package/skills/flutter-skills/tool/generator/test/validate_skills_test.dart +0 -728
- /package/skills/{.agents → flutter}/skills/flutter-add-integration-test/SKILL.md +0 -0
- /package/skills/{.agents → flutter}/skills/flutter-add-widget-preview/SKILL.md +0 -0
- /package/skills/{.agents → flutter}/skills/flutter-add-widget-test/SKILL.md +0 -0
- /package/skills/{.agents → flutter}/skills/flutter-apply-architecture-best-practices/SKILL.md +0 -0
- /package/skills/{.agents → flutter}/skills/flutter-build-responsive-layout/SKILL.md +0 -0
- /package/skills/{.agents → flutter}/skills/flutter-fix-layout-issues/SKILL.md +0 -0
- /package/skills/{.agents → flutter}/skills/flutter-implement-json-serialization/SKILL.md +0 -0
- /package/skills/{.agents → flutter}/skills/flutter-setup-declarative-routing/SKILL.md +0 -0
- /package/skills/{.agents → flutter}/skills/flutter-setup-localization/SKILL.md +0 -0
- /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
|
-
}
|