@mrciphersmith/keryx 0.3.2 → 0.3.5

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 (164) hide show
  1. package/dist/cli.js +4745 -2482
  2. package/dist/core.js +66 -10
  3. package/package.json +1 -1
  4. package/src/gdskills/bundled/install-manifest.json +578 -2
  5. package/src/gdskills/bundled/rules/core/model-selection.mdc +18 -0
  6. package/src/gdskills/bundled/skills/orchestration/job-orchestrator/SKILL.md +1 -1
  7. package/src/gdskills/bundled/skills/planning/brainstorm/SKILL.md +1 -1
  8. package/src/gdskills/bundled/skills/planning/interviewer/SKILL.md +1 -1
  9. package/src/gdskills/bundled/skills/quality/deploy/SKILL.md +1 -1
  10. package/src/gdskills/bundled/skills/review/review-jev-contract/SKILL.md +193 -0
  11. package/src/gdskills/bundled/skills/review/review-orchestrator/SKILL.detail.md +81 -21
  12. package/src/gdskills/bundled/skills/review/review-orchestrator/SKILL.md +4 -4
  13. package/src/gdskills/bundled/stacks/c-cpp/agent-refs.json +4 -0
  14. package/src/gdskills/bundled/stacks/c-cpp/governance/eval.json +1777 -0
  15. package/src/gdskills/bundled/stacks/c-cpp/governance/scout.json +31 -0
  16. package/src/gdskills/bundled/stacks/c-cpp/pack.json +42 -0
  17. package/src/gdskills/bundled/stacks/c-cpp/rules/coding-style.mdc +80 -0
  18. package/src/gdskills/bundled/stacks/c-cpp/rules/patterns.mdc +87 -0
  19. package/src/gdskills/bundled/stacks/c-cpp/rules/security.mdc +90 -0
  20. package/src/gdskills/bundled/stacks/c-cpp/rules/testing.mdc +83 -0
  21. package/src/gdskills/bundled/stacks/c-cpp/skills/c-cpp-build-fix/SKILL.md +153 -0
  22. package/src/gdskills/bundled/stacks/c-cpp/skills/c-cpp-build-fix/evals.json +74 -0
  23. package/src/gdskills/bundled/stacks/c-cpp/skills/c-cpp-code-review/SKILL.md +132 -0
  24. package/src/gdskills/bundled/stacks/c-cpp/skills/c-cpp-code-review/evals.json +73 -0
  25. package/src/gdskills/bundled/stacks/c-cpp/skills/c-cpp-implementation/SKILL.md +151 -0
  26. package/src/gdskills/bundled/stacks/c-cpp/skills/c-cpp-implementation/evals.json +74 -0
  27. package/src/gdskills/bundled/stacks/c-cpp/skills/c-cpp-testing/SKILL.md +152 -0
  28. package/src/gdskills/bundled/stacks/c-cpp/skills/c-cpp-testing/evals.json +74 -0
  29. package/src/gdskills/bundled/stacks/ci-github-gitlab/agent-refs.json +4 -0
  30. package/src/gdskills/bundled/stacks/ci-github-gitlab/governance/eval.json +1295 -0
  31. package/src/gdskills/bundled/stacks/ci-github-gitlab/governance/scout.json +26 -0
  32. package/src/gdskills/bundled/stacks/ci-github-gitlab/pack.json +41 -0
  33. package/src/gdskills/bundled/stacks/ci-github-gitlab/rules/patterns.mdc +77 -0
  34. package/src/gdskills/bundled/stacks/ci-github-gitlab/rules/security.mdc +144 -0
  35. package/src/gdskills/bundled/stacks/ci-github-gitlab/skills/ci-pipeline-build-fix/SKILL.md +121 -0
  36. package/src/gdskills/bundled/stacks/ci-github-gitlab/skills/ci-pipeline-build-fix/evals.json +73 -0
  37. package/src/gdskills/bundled/stacks/ci-github-gitlab/skills/ci-pipeline-code-review/SKILL.md +139 -0
  38. package/src/gdskills/bundled/stacks/ci-github-gitlab/skills/ci-pipeline-code-review/evals.json +73 -0
  39. package/src/gdskills/bundled/stacks/ci-github-gitlab/skills/ci-pipeline-implementation/SKILL.md +147 -0
  40. package/src/gdskills/bundled/stacks/ci-github-gitlab/skills/ci-pipeline-implementation/evals.json +74 -0
  41. package/src/gdskills/bundled/stacks/csharp-dotnet/agent-refs.json +4 -0
  42. package/src/gdskills/bundled/stacks/csharp-dotnet/governance/eval.json +1881 -0
  43. package/src/gdskills/bundled/stacks/csharp-dotnet/governance/scout.json +33 -0
  44. package/src/gdskills/bundled/stacks/csharp-dotnet/pack.json +38 -0
  45. package/src/gdskills/bundled/stacks/csharp-dotnet/rules/coding-style.mdc +100 -0
  46. package/src/gdskills/bundled/stacks/csharp-dotnet/rules/patterns.mdc +107 -0
  47. package/src/gdskills/bundled/stacks/csharp-dotnet/rules/security.mdc +86 -0
  48. package/src/gdskills/bundled/stacks/csharp-dotnet/rules/testing.mdc +89 -0
  49. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-build-fix/SKILL.md +143 -0
  50. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-build-fix/evals.json +77 -0
  51. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-code-review/SKILL.md +121 -0
  52. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-code-review/evals.json +77 -0
  53. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-implementation/SKILL.md +134 -0
  54. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-implementation/evals.json +76 -0
  55. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-testing/SKILL.md +130 -0
  56. package/src/gdskills/bundled/stacks/csharp-dotnet/skills/dotnet-testing/evals.json +77 -0
  57. package/src/gdskills/bundled/stacks/docker-k8s-terraform/agent-refs.json +4 -0
  58. package/src/gdskills/bundled/stacks/docker-k8s-terraform/governance/eval.json +865 -0
  59. package/src/gdskills/bundled/stacks/docker-k8s-terraform/governance/scout.json +16 -0
  60. package/src/gdskills/bundled/stacks/docker-k8s-terraform/pack.json +46 -0
  61. package/src/gdskills/bundled/stacks/docker-k8s-terraform/rules/coding-style.mdc +74 -0
  62. package/src/gdskills/bundled/stacks/docker-k8s-terraform/rules/patterns.mdc +81 -0
  63. package/src/gdskills/bundled/stacks/docker-k8s-terraform/rules/security.mdc +146 -0
  64. package/src/gdskills/bundled/stacks/docker-k8s-terraform/rules/testing.mdc +61 -0
  65. package/src/gdskills/bundled/stacks/docker-k8s-terraform/skills/docker-k8s-terraform-build-fix/SKILL.md +151 -0
  66. package/src/gdskills/bundled/stacks/docker-k8s-terraform/skills/docker-k8s-terraform-build-fix/evals.json +74 -0
  67. package/src/gdskills/bundled/stacks/docker-k8s-terraform/skills/docker-k8s-terraform-review/SKILL.md +135 -0
  68. package/src/gdskills/bundled/stacks/docker-k8s-terraform/skills/docker-k8s-terraform-review/evals.json +76 -0
  69. package/src/gdskills/bundled/stacks/flutter-dart/agent-refs.json +4 -0
  70. package/src/gdskills/bundled/stacks/flutter-dart/governance/eval.json +1849 -0
  71. package/src/gdskills/bundled/stacks/flutter-dart/governance/scout.json +33 -0
  72. package/src/gdskills/bundled/stacks/flutter-dart/pack.json +41 -0
  73. package/src/gdskills/bundled/stacks/flutter-dart/rules/coding-style.mdc +98 -0
  74. package/src/gdskills/bundled/stacks/flutter-dart/rules/patterns.mdc +88 -0
  75. package/src/gdskills/bundled/stacks/flutter-dart/rules/security.mdc +91 -0
  76. package/src/gdskills/bundled/stacks/flutter-dart/rules/testing.mdc +101 -0
  77. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-build-fix/SKILL.md +134 -0
  78. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-build-fix/evals.json +79 -0
  79. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-code-review/SKILL.md +124 -0
  80. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-code-review/evals.json +74 -0
  81. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-implementation/SKILL.md +139 -0
  82. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-implementation/evals.json +77 -0
  83. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-testing/SKILL.md +134 -0
  84. package/src/gdskills/bundled/stacks/flutter-dart/skills/flutter-testing/evals.json +74 -0
  85. package/src/gdskills/bundled/stacks/kotlin-android/agent-refs.json +4 -0
  86. package/src/gdskills/bundled/stacks/kotlin-android/governance/eval.json +1889 -0
  87. package/src/gdskills/bundled/stacks/kotlin-android/governance/scout.json +34 -0
  88. package/src/gdskills/bundled/stacks/kotlin-android/pack.json +38 -0
  89. package/src/gdskills/bundled/stacks/kotlin-android/rules/coding-style.mdc +89 -0
  90. package/src/gdskills/bundled/stacks/kotlin-android/rules/patterns.mdc +96 -0
  91. package/src/gdskills/bundled/stacks/kotlin-android/rules/security.mdc +90 -0
  92. package/src/gdskills/bundled/stacks/kotlin-android/rules/testing.mdc +89 -0
  93. package/src/gdskills/bundled/stacks/kotlin-android/skills/compose-implementation/SKILL.md +150 -0
  94. package/src/gdskills/bundled/stacks/kotlin-android/skills/compose-implementation/evals.json +77 -0
  95. package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-build-fix/SKILL.md +151 -0
  96. package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-build-fix/evals.json +76 -0
  97. package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-code-review/SKILL.md +139 -0
  98. package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-code-review/evals.json +78 -0
  99. package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-testing/SKILL.md +131 -0
  100. package/src/gdskills/bundled/stacks/kotlin-android/skills/kotlin-android-testing/evals.json +77 -0
  101. package/src/gdskills/bundled/stacks/php-laravel/agent-refs.json +4 -0
  102. package/src/gdskills/bundled/stacks/php-laravel/governance/eval.json +1829 -0
  103. package/src/gdskills/bundled/stacks/php-laravel/governance/scout.json +33 -0
  104. package/src/gdskills/bundled/stacks/php-laravel/pack.json +41 -0
  105. package/src/gdskills/bundled/stacks/php-laravel/rules/coding-style.mdc +82 -0
  106. package/src/gdskills/bundled/stacks/php-laravel/rules/patterns.mdc +80 -0
  107. package/src/gdskills/bundled/stacks/php-laravel/rules/security.mdc +80 -0
  108. package/src/gdskills/bundled/stacks/php-laravel/rules/testing.mdc +82 -0
  109. package/src/gdskills/bundled/stacks/php-laravel/skills/php-laravel-build-fix/SKILL.md +143 -0
  110. package/src/gdskills/bundled/stacks/php-laravel/skills/php-laravel-build-fix/evals.json +74 -0
  111. package/src/gdskills/bundled/stacks/php-laravel/skills/php-laravel-code-review/SKILL.md +126 -0
  112. package/src/gdskills/bundled/stacks/php-laravel/skills/php-laravel-code-review/evals.json +76 -0
  113. package/src/gdskills/bundled/stacks/php-laravel/skills/php-laravel-implementation/SKILL.md +140 -0
  114. package/src/gdskills/bundled/stacks/php-laravel/skills/php-laravel-implementation/evals.json +75 -0
  115. package/src/gdskills/bundled/stacks/php-laravel/skills/php-laravel-testing/SKILL.md +124 -0
  116. package/src/gdskills/bundled/stacks/php-laravel/skills/php-laravel-testing/evals.json +74 -0
  117. package/src/gdskills/bundled/stacks/ruby-rails/agent-refs.json +4 -0
  118. package/src/gdskills/bundled/stacks/ruby-rails/governance/eval.json +1673 -0
  119. package/src/gdskills/bundled/stacks/ruby-rails/governance/scout.json +33 -0
  120. package/src/gdskills/bundled/stacks/ruby-rails/pack.json +42 -0
  121. package/src/gdskills/bundled/stacks/ruby-rails/rules/coding-style.mdc +69 -0
  122. package/src/gdskills/bundled/stacks/ruby-rails/rules/patterns.mdc +93 -0
  123. package/src/gdskills/bundled/stacks/ruby-rails/rules/security.mdc +90 -0
  124. package/src/gdskills/bundled/stacks/ruby-rails/rules/testing.mdc +89 -0
  125. package/src/gdskills/bundled/stacks/ruby-rails/skills/ruby-rails-build-fix/SKILL.md +143 -0
  126. package/src/gdskills/bundled/stacks/ruby-rails/skills/ruby-rails-build-fix/evals.json +73 -0
  127. package/src/gdskills/bundled/stacks/ruby-rails/skills/ruby-rails-code-review/SKILL.md +134 -0
  128. package/src/gdskills/bundled/stacks/ruby-rails/skills/ruby-rails-code-review/evals.json +71 -0
  129. package/src/gdskills/bundled/stacks/ruby-rails/skills/ruby-rails-implementation/SKILL.md +141 -0
  130. package/src/gdskills/bundled/stacks/ruby-rails/skills/ruby-rails-implementation/evals.json +72 -0
  131. package/src/gdskills/bundled/stacks/ruby-rails/skills/ruby-rails-testing/SKILL.md +125 -0
  132. package/src/gdskills/bundled/stacks/ruby-rails/skills/ruby-rails-testing/evals.json +72 -0
  133. package/src/gdskills/bundled/stacks/sql-db/agent-refs.json +4 -0
  134. package/src/gdskills/bundled/stacks/sql-db/governance/eval.json +1829 -0
  135. package/src/gdskills/bundled/stacks/sql-db/governance/scout.json +30 -0
  136. package/src/gdskills/bundled/stacks/sql-db/pack.json +40 -0
  137. package/src/gdskills/bundled/stacks/sql-db/rules/coding-style.mdc +69 -0
  138. package/src/gdskills/bundled/stacks/sql-db/rules/patterns.mdc +134 -0
  139. package/src/gdskills/bundled/stacks/sql-db/rules/security.mdc +74 -0
  140. package/src/gdskills/bundled/stacks/sql-db/rules/testing.mdc +83 -0
  141. package/src/gdskills/bundled/stacks/sql-db/skills/sql-db-build-fix/SKILL.md +147 -0
  142. package/src/gdskills/bundled/stacks/sql-db/skills/sql-db-build-fix/evals.json +72 -0
  143. package/src/gdskills/bundled/stacks/sql-db/skills/sql-db-code-review/SKILL.md +132 -0
  144. package/src/gdskills/bundled/stacks/sql-db/skills/sql-db-code-review/evals.json +73 -0
  145. package/src/gdskills/bundled/stacks/sql-db/skills/sql-db-implementation/SKILL.md +153 -0
  146. package/src/gdskills/bundled/stacks/sql-db/skills/sql-db-implementation/evals.json +77 -0
  147. package/src/gdskills/bundled/stacks/sql-db/skills/sql-db-testing/SKILL.md +129 -0
  148. package/src/gdskills/bundled/stacks/sql-db/skills/sql-db-testing/evals.json +73 -0
  149. package/src/gdskills/bundled/stacks/swift-ios/agent-refs.json +4 -0
  150. package/src/gdskills/bundled/stacks/swift-ios/governance/eval.json +1803 -0
  151. package/src/gdskills/bundled/stacks/swift-ios/governance/scout.json +32 -0
  152. package/src/gdskills/bundled/stacks/swift-ios/pack.json +38 -0
  153. package/src/gdskills/bundled/stacks/swift-ios/rules/coding-style.mdc +92 -0
  154. package/src/gdskills/bundled/stacks/swift-ios/rules/patterns.mdc +112 -0
  155. package/src/gdskills/bundled/stacks/swift-ios/rules/security.mdc +78 -0
  156. package/src/gdskills/bundled/stacks/swift-ios/rules/testing.mdc +90 -0
  157. package/src/gdskills/bundled/stacks/swift-ios/skills/swift-build-fix/SKILL.md +144 -0
  158. package/src/gdskills/bundled/stacks/swift-ios/skills/swift-build-fix/evals.json +75 -0
  159. package/src/gdskills/bundled/stacks/swift-ios/skills/swift-code-review/SKILL.md +122 -0
  160. package/src/gdskills/bundled/stacks/swift-ios/skills/swift-code-review/evals.json +75 -0
  161. package/src/gdskills/bundled/stacks/swift-ios/skills/swift-testing/SKILL.md +131 -0
  162. package/src/gdskills/bundled/stacks/swift-ios/skills/swift-testing/evals.json +75 -0
  163. package/src/gdskills/bundled/stacks/swift-ios/skills/swiftui-implementation/SKILL.md +149 -0
  164. package/src/gdskills/bundled/stacks/swift-ios/skills/swiftui-implementation/evals.json +76 -0
@@ -0,0 +1,33 @@
1
+ [
2
+ {
3
+ "query": "Use when implementing or extending a feature in a Flutter app -- widget composition, state-management-agnostic lifecycle correctness, guarding BuildContext/setState across an async gap, and sound-null-safety idiom.",
4
+ "decision": "fork",
5
+ "topMatch": "flutter-dart/flutter-code-review",
6
+ "recordedAt": "2026-09-25T15:35:12.436Z",
7
+ "skillName": "flutter-implementation",
8
+ "justification": "Top match flutter-dart/flutter-code-review is this same pack's read-only review skill (different intent, action verb, workflow), not a real implementation duplicate; no existing implement skill covers Flutter widget composition, BuildContext-across-async-gap guarding, or Dart null safety."
9
+ },
10
+ {
11
+ "query": "Use when a Flutter app's test suite needs writing, extending, or fixing -- widget tests with testWidgets/WidgetTester, mocking the network/repository boundary with mocktail/mockito, and pump vs pumpAndSettle for animation- and async-aware assertions.",
12
+ "decision": "fork",
13
+ "topMatch": "ts-js-node/nodejs-testing",
14
+ "recordedAt": "2026-09-25T15:35:12.736Z",
15
+ "skillName": "flutter-testing",
16
+ "justification": "Nearest match ts-js-node/nodejs-testing tests TypeScript/Node code with Vitest/Jest, a different runtime and tooling entirely; no existing test skill covers Flutter widget tests, testWidgets/WidgetTester, or pump/pumpAndSettle semantics."
17
+ },
18
+ {
19
+ "query": "Use when reviewing a Flutter/Dart change for lifecycle and null-safety risks -- unguarded BuildContext/setState after an await, an undisposed controller/subscription, bang-operator misuse, and business logic inside build(). Read-only, no edits.",
20
+ "decision": "create",
21
+ "topMatch": "flutter-dart/flutter-implementation",
22
+ "recordedAt": "2026-09-25T15:33:56.877Z",
23
+ "skillName": "flutter-code-review"
24
+ },
25
+ {
26
+ "query": "Use when flutter analyze/flutter build fails, or pubspec.yaml/pubspec.lock are out of sync -- resolves dependency version conflicts, analyzer/lint failures, null-safety compile errors, and a failing flutter test, with the smallest root-cause fix.",
27
+ "decision": "fork",
28
+ "topMatch": "kotlin-android/kotlin-android-build-fix",
29
+ "recordedAt": "2026-09-25T15:35:13.311Z",
30
+ "skillName": "flutter-build-fix",
31
+ "justification": "Nearest match kotlin-android/kotlin-android-build-fix fixes Gradle/AGP/Kotlin/detekt errors, not flutter analyze/pubspec/Dart null-safety compile errors; each build-fix skill is scoped to its own toolchain's specific failure surface."
32
+ }
33
+ ]
@@ -0,0 +1,41 @@
1
+ {
2
+ "id": "flutter-dart",
3
+ "family": "framework",
4
+ "modules": ["flutter-dart-rules", "flutter-dart-skills"],
5
+ "detectionMarkers": ["flutter"],
6
+ "provenance": {
7
+ "origin": "authored",
8
+ "sourceRef": "flow 336, Wave 4 batch 4"
9
+ },
10
+ "stability": "experimental",
11
+ "skills": {
12
+ "implement": ["flutter-implementation"],
13
+ "test": ["flutter-testing"],
14
+ "review": ["flutter-code-review"],
15
+ "build-fix": ["flutter-build-fix"],
16
+ "migrate": []
17
+ },
18
+ "agentProfile": {
19
+ "displayName": "Flutter/Dart",
20
+ "auditFocus": [
21
+ "a BuildContext used after an await with no context.mounted (or State.mounted) check first",
22
+ "a StatefulWidget with a TextEditingController/AnimationController/StreamSubscription/FocusNode created in initState but never released in dispose",
23
+ "setState called after an async gap with no mounted guard, risking 'setState() called after dispose()'",
24
+ "a widget tree many levels deep in one build method instead of extracted into smaller const-friendly widgets",
25
+ "a secret, token, or API key read from or written to SharedPreferences instead of flutter_secure_storage",
26
+ "a bang operator (!) on a nullable value with no preceding null check or non-null guarantee in scope"
27
+ ],
28
+ "buildCommands": [
29
+ "flutter analyze",
30
+ "dart format --set-exit-if-changed .",
31
+ "flutter test",
32
+ "flutter build apk --debug (or the project's actual target platform build)"
33
+ ],
34
+ "fixGuardrails": [
35
+ "never add // ignore: or a blanket // ignore_for_file: comment to silence an analyzer finding instead of fixing the root cause",
36
+ "never add the bang operator (!) to a nullable value just to satisfy the analyzer without first establishing the value is actually non-null there",
37
+ "never delete or weaken a failing widget test's expectation (find.text/find.byType assertion) to make it pass",
38
+ "never pin or downgrade a pub dependency to route around a real incompatibility without saying so in the report"
39
+ ]
40
+ }
41
+ }
@@ -0,0 +1,98 @@
1
+ ---
2
+ extends: common
3
+ paths: ["**/*.dart"]
4
+ metadata:
5
+ origin: authored
6
+ ---
7
+
8
+ # Flutter/Dart coding style
9
+
10
+ Narrows `core-common-rules`' stack-agnostic style rules to modern Dart
11
+ (3.x, sound null safety — mandatory since Dart 3, it cannot be disabled)
12
+ and Flutter widget idiom. Applies only to `*.dart` files — everything not
13
+ Dart/Flutter-specific still comes from the common rules this file
14
+ `extends`.
15
+
16
+ ## Naming and structure
17
+
18
+ - `UpperCamelCase` for classes, enums, extensions, typedefs, and widgets;
19
+ `lowerCamelCase` for variables, parameters, and methods;
20
+ `lowercase_with_underscores` for file names and package/directory names —
21
+ never `snake_case` identifiers or `PascalCase` file names.
22
+ - A widget file is named after the widget it defines
23
+ (`order_summary_card.dart` for `OrderSummaryCard`), one primary public
24
+ widget per file, matching how the project already splits `lib/`.
25
+ - Keep a `build()` method reading top-to-bottom as layout, not a mix of
26
+ layout and business logic — push data fetching, formatting, and
27
+ validation into a controller/view-model/state object the widget reads
28
+ from, not inline inside `build()`.
29
+ - An identifier's name shrinks with its scope: a short-lived loop index is
30
+ `i`, a public widget or service class gets a full descriptive name.
31
+
32
+ ## Const constructors and rebuild cost
33
+
34
+ - Mark every widget constructor `const` when all of its fields can be
35
+ `final` and const-constructible — a `const` widget is skipped entirely
36
+ by `build()` on a parent rebuild instead of being rebuilt and diffed,
37
+ which is a real, measurable performance difference in a widget tree
38
+ that rebuilds often (a list item, an animated ancestor).
39
+ - Prefer `const` at the call site too (`const SizedBox(height: 8)`, `const
40
+ Divider()`), not just on the constructor declaration — the analyzer's
41
+ `prefer_const_constructors` lint exists to catch the call sites that
42
+ could be const but are not; do not disable that lint to avoid fixing
43
+ them.
44
+ - A widget with a non-const field (a callback closure built fresh each
45
+ `build()`, for instance) cannot be const — when that field does not
46
+ actually need to vary per-build, hoist it out (a `static` handler, a
47
+ field on the enclosing `State`) so the widget itself can go back to
48
+ being const.
49
+
50
+ ## Sound null safety idiom
51
+
52
+ - Prefer `?.`/`??`/`??=` over the bang operator (`!`) — reach for `!` only
53
+ when the value's non-nullability is guaranteed by code the analyzer
54
+ cannot see (already checked a few lines above with no intervening
55
+ `await`, or a documented invariant), and say why in a comment when it is
56
+ not obvious.
57
+ - Never use `!` on a value that crossed an `await` since it was last
58
+ checked, or on a field read from a widget/state that could have been
59
+ disposed in between — re-check (`if (value == null) return;` or
60
+ `context.mounted`) after the async gap instead of re-asserting non-null.
61
+ - Declare a field `late` only when it is genuinely always initialized
62
+ before first read (e.g. in `initState`) — a `late` field that can
63
+ legitimately be unset just trades a compile-time nullability warning for
64
+ a runtime `LateInitializationError`, which is strictly worse.
65
+ - Give a nullable parameter a sensible default via `??` at the point of
66
+ use rather than threading a null check through every downstream
67
+ consumer of that parameter.
68
+
69
+ ## Composition over deep nesting
70
+
71
+ - Extract a widget into its own class (or a private `_SectionWidget`
72
+ below the file's main widget) once a single `build()` method's nesting
73
+ becomes hard to scan — composition of small, focused widgets is the
74
+ idiomatic Flutter equivalent of extracting a function, and each
75
+ extracted piece can independently be `const` and independently testable
76
+ with `testWidgets`.
77
+ - Prefer a `Column`/`Row`/`Wrap` plus a handful of small child widgets
78
+ over one large widget expression with many positional/named-argument
79
+ levels of `Padding(child: Container(child: Column(children: [...])))` —
80
+ flatten with `SizedBox`/`Padding` siblings and extracted widgets instead
81
+ of nesting purely to achieve a visual effect a flatter tree would give
82
+ just as well.
83
+ - A `build()` method that branches on more than two or three conditions to
84
+ decide what to render is a sign the widget is doing too much — extract
85
+ each branch into its own small widget so each one is readable and
86
+ testable in isolation.
87
+
88
+ ## Formatting and imports
89
+
90
+ - Format with `dart format` before finishing a change — do not hand-format
91
+ around a formatter that is already configured; CI enforces `dart format
92
+ --set-exit-if-changed .` in most Flutter repos.
93
+ - Order imports `dart:` / `package:flutter` / other `package:` / relative,
94
+ with a blank line between groups, matching whatever the project's
95
+ `analysis_options.yaml` (e.g. `directives_ordering`) already enforces.
96
+ - Prefer relative imports within the same package's `lib/` tree and
97
+ `package:` imports for anything outside it, matching the project's
98
+ existing convention rather than switching styles mid-file.
@@ -0,0 +1,88 @@
1
+ ---
2
+ extends: common
3
+ paths: ["**/*.dart"]
4
+ metadata:
5
+ origin: authored
6
+ ---
7
+
8
+ # Flutter/Dart patterns
9
+
10
+ Narrows `core-common-rules`' stack-agnostic design guidance to Flutter's
11
+ widget lifecycle, state handling, and async patterns. Applies only to
12
+ `*.dart` files. Flutter has no single mandated state-management story —
13
+ `Provider`, `Riverpod`, `Bloc`, and plain `StatefulWidget` all appear
14
+ across real projects — so this rule gives lifecycle-correct guidance that
15
+ applies regardless of which the project has chosen; match whichever one is
16
+ already in use rather than introducing a second approach.
17
+
18
+ ## Widget lifecycle correctness
19
+
20
+ - `initState()` is for one-time setup that needs `this` (subscribing to a
21
+ controller, starting a timer, reading an inherited widget via
22
+ `context.dependOnInheritedWidgetOfExactType` is not yet safe here — use
23
+ `didChangeDependencies()` for that); it must call `super.initState()`
24
+ first.
25
+ - `dispose()` releases everything `initState()` (or a later lifecycle
26
+ method) acquired: cancel every `StreamSubscription`, call `.dispose()`
27
+ on every `TextEditingController`/`AnimationController`/`FocusNode`/
28
+ `ScrollController` the `State` created, and call `super.dispose()` last,
29
+ not first. A controller created in `initState` and never disposed leaks
30
+ its underlying resources for the life of the app.
31
+ - `didUpdateWidget(oldWidget)` is where a `StatefulWidget` reacts to a
32
+ changed constructor parameter from its parent (e.g. re-subscribing to a
33
+ different id) — comparing `oldWidget.someId != widget.someId` there,
34
+ not inside `build()`, keeps that reaction from re-running on every
35
+ rebuild.
36
+
37
+ ## setState and BuildContext after an async gap
38
+
39
+ - After any `await` inside a `State` method, check `mounted` (the
40
+ `State`'s own property) before calling `setState()` — a `State` can be
41
+ disposed while the `Future` was pending, and calling `setState()` on a
42
+ disposed `State` throws.
43
+ - After any `await` inside a callback that holds a `BuildContext` (a
44
+ button's `onPressed`, a `Future` continuation), check `context.mounted`
45
+ before using that `context` again — for showing a dialog/SnackBar,
46
+ reading `Theme.of(context)`/`Navigator.of(context)`, or anything else —
47
+ never assume the widget that owns it is still in the tree just because
48
+ the `Future` completed. This applies whether the context came from a
49
+ `StatefulWidget`'s own `State` or from a `StatelessWidget`'s `build`
50
+ parameter.
51
+ - An early-return `if` check on `context.mounted` (or `mounted` inside
52
+ `State`) immediately after the `await`, before the first subsequent use
53
+ of `context`/`setState`, is the fix — not a `try`/`catch` around the
54
+ eventual error, and not skipping the check because the async call
55
+ "usually" resolves quickly.
56
+
57
+ ## Async patterns
58
+
59
+ - Prefer `async`/`await` over chained `.then()` for anything beyond a
60
+ single continuation — sequential `await` reads top-to-bottom and
61
+ composes with `try`/`catch` the same way synchronous code does.
62
+ - For a value that arrives over time rather than once, use a `Stream` and
63
+ a `StreamBuilder` (or the state-management approach's own stream/async
64
+ listener), not a `Future` polled on a timer.
65
+ - Cancel a `StreamSubscription` created outside `StreamBuilder` (i.e. one
66
+ the `State` subscribes to manually) in `dispose()` — `StreamBuilder`
67
+ itself manages its subscription's lifecycle and needs no manual cancel.
68
+ - Guard a `FutureBuilder`/`StreamBuilder`'s `snapshot.connectionState`
69
+ before reading `snapshot.data` — a `ConnectionState.waiting` or
70
+ `.none` snapshot with a stale or null `data` rendered as if it were
71
+ ready is a common source of a flashed empty/error state on first frame.
72
+
73
+ ## Anti-patterns to flag
74
+
75
+ - A `TextEditingController`/`AnimationController`/`StreamSubscription`/
76
+ `FocusNode` created in `initState` with no matching release in
77
+ `dispose()`.
78
+ - `BuildContext` or `setState()` used after an `await` with no
79
+ `context.mounted`/`mounted` check immediately before that use.
80
+ - Business logic (network calls, parsing, validation) written directly
81
+ inside a `build()` method instead of a controller/view-model/state
82
+ object the widget merely reads from — `build()` can be called many
83
+ times for reasons unrelated to data changing, so anything with a side
84
+ effect or real cost does not belong there.
85
+ - Mixing state-management approaches in the same feature (e.g. a
86
+ `Riverpod` provider read via `ref` next to an ad hoc
87
+ `InheritedWidget`/`setState` for the same piece of state) instead of
88
+ following whichever one the project has already standardized on.
@@ -0,0 +1,91 @@
1
+ ---
2
+ extends: common
3
+ paths: ["**/*.dart"]
4
+ metadata:
5
+ origin: authored
6
+ ---
7
+
8
+ # Flutter/Dart security
9
+
10
+ Narrows `core-common-rules`' stack-agnostic security rules to Flutter/Dart-
11
+ specific risks and the safe APIs to use instead. Applies only to `*.dart`
12
+ files.
13
+
14
+ ## Secret and credential storage
15
+
16
+ - Store a token, session cookie, refresh token, or any other credential in
17
+ `flutter_secure_storage` (backed by Keychain on iOS, the Android
18
+ Keystore on Android — check the plugin's current backing implementation
19
+ rather than assuming `EncryptedSharedPreferences`, which has known
20
+ reliability issues and is no longer recommended by Google for new
21
+ Android code), never in `shared_preferences` — `SharedPreferences`
22
+ persists as an unencrypted plist/XML file on disk that any process with
23
+ filesystem access (a rooted device, a backup extraction) can read
24
+ directly.
25
+ - `shared_preferences` remains fine for genuinely non-sensitive
26
+ preferences (a theme choice, a "seen onboarding" flag) — the rule is
27
+ about what the value *is*, not a blanket ban on the package.
28
+ - Never hard-code an API key, client secret, or signing credential as a
29
+ Dart string literal compiled into the app — every string in a release
30
+ build is recoverable from the compiled binary with straightforward
31
+ reverse-engineering tools. `--dart-define`/a build-time `.env` file is
32
+ NOT a way to keep a secret server-side — both are compiled into the
33
+ binary at build time exactly like a string literal and are just as
34
+ recoverable from the shipped artifact; they only avoid committing the
35
+ secret to source control, which is a different property. For a value
36
+ that must actually stay off the device, fetch it at runtime from a
37
+ backend-issued short-lived token or a secrets manager reached over an
38
+ authenticated network call — never bake it into the build at all.
39
+
40
+ ## Network calls and certificate pinning
41
+
42
+ - Use `https://` for every network call that carries user data,
43
+ credentials, or tokens; a plaintext `http://` endpoint is trivially
44
+ interceptable on a shared or compromised network.
45
+ - For a call carrying especially sensitive data (payment, health,
46
+ authentication) where the project has decided the risk of a
47
+ compromised/misissued CA in the platform trust store is worth guarding
48
+ against, use certificate pinning (`HttpClient.badCertificateCallback`
49
+ validated against a known pin, or a package such as
50
+ `http_certificate_pinning`/platform-native pinning) — but treat this as
51
+ a deliberate, project-level decision with a rotation plan, not a default
52
+ to apply to every request, since a mishandled pin update can lock out
53
+ legitimate traffic when a certificate rotates.
54
+ - Never override `badCertificateCallback` (or an equivalent HTTP client
55
+ hook) to unconditionally return `true` — that disables certificate
56
+ validation entirely for that client, the same failure class as Go's
57
+ `InsecureSkipVerify: true`, and is never appropriate outside a
58
+ short-lived local test.
59
+
60
+ ## Platform channel and input validation
61
+
62
+ - Validate and sanitize any value crossing a `MethodChannel`/
63
+ `EventChannel` in either direction — a payload from native code is
64
+ external input from the Dart side's perspective, and a payload from
65
+ Dart is external input from the native side's perspective; do not trust
66
+ a channel argument's shape or range without checking it, especially
67
+ before using it to index a collection, build a file path, or construct
68
+ a query.
69
+ - Encode structured data crossing a platform channel with the codec the
70
+ channel already uses (the default standard codec, or an explicit
71
+ `MessageCodec`) rather than hand-rolling string concatenation/parsing
72
+ across the channel boundary, which reintroduces the same injection and
73
+ parsing-ambiguity risks as building a query string by hand.
74
+
75
+ ## Local storage and logging
76
+
77
+ - Never write a secret, token, or PII value to `debugPrint`/`print` or any
78
+ logging sink that a release build still ships with enabled — a log
79
+ statement written for local debugging has a way of surviving into a
80
+ shipped build and into crash-reporting payloads.
81
+ - A `WebView` rendering any content that includes user-controlled or
82
+ externally-fetched HTML must not run with JavaScript enabled on
83
+ untrusted content unless the content is sanitized first — the same XSS
84
+ risk class as an unescaped web template, just inside a native app.
85
+
86
+ ## Dependency hygiene
87
+
88
+ - Run `flutter pub outdated` and review a dependency's changelog/CVE
89
+ history before a major-version bump, and prefer `dart pub deps` to
90
+ understand what a new transitive dependency actually pulls in before
91
+ adding it.
@@ -0,0 +1,101 @@
1
+ ---
2
+ extends: common
3
+ paths: ["**/*.dart"]
4
+ metadata:
5
+ origin: authored
6
+ ---
7
+
8
+ # Flutter/Dart testing
9
+
10
+ Narrows `core-common-rules`' stack-agnostic testing rules to
11
+ `flutter_test`'s widget-test framework and `package:test`'s unit-test
12
+ conventions. Applies only to `*.dart` files.
13
+
14
+ ## Layout and naming
15
+
16
+ - Unit and widget tests live under `test/`, mirroring `lib/`'s structure
17
+ (`lib/order/order_service.dart` → `test/order/order_service_test.dart`)
18
+ — no separate ad hoc fixture tree.
19
+ - A widget test file's `testWidgets('<behavior it verifies>', (tester)
20
+ async { ... })` description names the observable behavior under test,
21
+ not the widget's implementation detail — `'shows an error banner when
22
+ submit fails'`, not `'calls setState'`.
23
+ - `group('OrderService', () { ... })` to cluster related cases for one
24
+ class/widget, matching whatever the project's existing suite already
25
+ does.
26
+
27
+ ## Widget tests
28
+
29
+ - Build the widget under test with `tester.pumpWidget(...)`, wrapped in
30
+ whatever ancestor widgets it actually needs to render (a `MaterialApp`/
31
+ `CupertinoApp`, a `Localizations` scope, a state-management provider) —
32
+ matching the app's real widget tree shape, not an arbitrary bare
33
+ wrapper.
34
+ - Locate widgets with `find.byType`, `find.text`, `find.byKey`, or
35
+ `find.byIcon` — prefer `find.byKey` for a widget identified by role
36
+ rather than by its current text/type when either could plausibly change
37
+ without the behavior changing.
38
+ - Use `tester.pump()` to advance exactly one frame (a single `setState`
39
+ or a fixed-duration animation step) and `tester.pumpAndSettle()` when
40
+ waiting for an animation, page transition, or async operation to fully
41
+ finish before asserting — but do not reach for `pumpAndSettle()` by
42
+ default for everything: a widget under a `Timer.periodic` or another
43
+ never-ending animation makes `pumpAndSettle()` time out waiting for a
44
+ frame that never stops changing, so a bounded `pump(Duration(...))` is
45
+ the correct tool there instead.
46
+ - Interact with `tester.tap(finder)`, `tester.enterText(finder, '...')`,
47
+ `tester.drag(finder, offset)`, each followed by a `pump()`/
48
+ `pumpAndSettle()` appropriate to what the interaction triggers, before
49
+ asserting on the result.
50
+
51
+ ## Mocking the boundary, not the internals
52
+
53
+ - Mock at the external boundary a widget/class depends on — a repository,
54
+ an HTTP client, a platform-channel wrapper — defined as an interface (an
55
+ abstract class) the real implementation and a test double both satisfy,
56
+ using `mocktail` (no code generation, works with sound null safety) or
57
+ `mockito` (code-generation based) to build that double.
58
+ - Never mock a class's own internal collaborator that exists purely to
59
+ implement its behavior (a private helper, a widget's own internal
60
+ state) — mocking one layer too deep tests that the implementation calls
61
+ itself in a particular way, not that the widget/class actually produces
62
+ the right externally-observable behavior, and it breaks on every
63
+ internal refactor even when the behavior is unchanged.
64
+ - Verify a mocked dependency's interaction (`verify(() =>
65
+ mockRepository.fetchOrders()).called(1)`) only for calls that matter to
66
+ the behavior under test — do not over-verify every incidental call,
67
+ which turns the test into a change-detector for implementation details.
68
+
69
+ ## Async state in widget tests
70
+
71
+ - When a widget's state depends on a `Future` (a repository call behind a
72
+ loading spinner), pump through the states explicitly: `pump()` once to
73
+ render the loading state, then `pump()`/`pumpAndSettle()` again after
74
+ the mocked `Future` resolves, asserting the loading indicator is gone
75
+ and the real content is present — asserting only on the state
76
+ immediately after `pumpWidget()` misses the loading-to-loaded
77
+ transition entirely.
78
+ - Never use `Future.delayed`/a real `Duration` wait inside a test to give
79
+ a mocked async call "enough time" to resolve — control the mock's
80
+ `Future` directly (a `Completer` the test completes explicitly, or a
81
+ mock configured to resolve immediately) and drive time forward with
82
+ `pump()`/`pumpAndSettle()`/`tester.pump(duration)` instead, so the test
83
+ is deterministic rather than timing-dependent.
84
+
85
+ ## Fixtures and golden tests
86
+
87
+ - `testWidgets` fixtures (sample model instances, mock repository
88
+ responses) live in a `test/fixtures/` or per-feature helper file,
89
+ matching whatever the project already uses — do not invent a second
90
+ fixture convention alongside an existing one.
91
+ - A golden-image test (`matchesGoldenFile`) is opt-in per project; only
92
+ add one where the project already has a golden-test setup and baseline
93
+ images checked in, and regenerate baselines deliberately (`flutter test
94
+ --update-goldens`), not as a side effect of an unrelated change.
95
+
96
+ ## Running and coverage
97
+
98
+ - Run `flutter test` (or `flutter test --coverage` when the project
99
+ tracks coverage) before reporting a testing task done; fix a failing
100
+ test by correcting the test or the fixture it depends on, not by
101
+ weakening its `expect`/`find` assertion to make it pass.
@@ -0,0 +1,134 @@
1
+ ---
2
+ name: flutter-build-fix
3
+ description: "Use when flutter analyze/flutter build fails, or pubspec.yaml/pubspec.lock are out of sync -- resolves dependency version conflicts, analyzer/lint failures, null-safety compile errors, and a failing flutter test, with the smallest root-cause fix."
4
+ triggers:
5
+ - "flutter analyze is failing"
6
+ - "flutter build is failing with a dependency error"
7
+ - "fix this pubspec.yaml version conflict"
8
+ - "resolve this Dart null-safety compile error"
9
+ - "this Flutter lint is failing in CI"
10
+ - "flutter test is failing after a pub upgrade"
11
+ metadata:
12
+ origin: authored
13
+ category: build-fix
14
+ version: "1.0.0"
15
+ compatible_harnesses: "claude,codex,cursor,zed,opencode"
16
+ license: "MIT"
17
+ ---
18
+
19
+ # Flutter/Dart build fix
20
+
21
+ Resolve a `flutter analyze`/`flutter build` failure, a `pubspec.yaml`/
22
+ `pubspec.lock` mismatch, a null-safety compile error, an analyzer/lint
23
+ failure, or a failing `flutter test` — with the smallest change that fixes
24
+ the actual root cause. `rules/coding-style.mdc` and `rules/security.mdc`
25
+ govern what a "correct" fix looks like; this skill never reaches for a
26
+ suppression instead of a fix.
27
+
28
+ ## Workflow
29
+
30
+ ### Step 1: Reproduce and classify
31
+
32
+ ```bash
33
+ flutter analyze
34
+ dart format --set-exit-if-changed .
35
+ ```
36
+
37
+ Read the exact error text and classify it:
38
+
39
+ - **Compile error** (undefined identifier, type mismatch, missing
40
+ override).
41
+ - **Null-safety error** (a nullable value used where non-null is
42
+ required, a missing `late`/`required`, an unhandled `null` case).
43
+ - **Dependency/version conflict** (`pubspec.yaml`/`pubspec.lock`
44
+ mismatch, `flutter pub get` reporting a version solving failure).
45
+ - **Analyzer/lint finding** (`flutter analyze`'s own rules, or a rule from
46
+ the project's `analysis_options.yaml`).
47
+ - **Failing test** (`flutter test` reports a failed `expect`/`find`
48
+ assertion, or a widget test exception).
49
+
50
+ ### Step 2: Fix by category
51
+
52
+ **Dependency/version conflict:** run `flutter pub get` (or `flutter pub
53
+ upgrade` when a newer compatible version is needed) and read the actual
54
+ version-solving error — it names which packages conflict and why. Check
55
+ `flutter pub deps` to see the dependency graph before pinning a version by
56
+ hand. Only add a `dependency_overrides` entry when it is a real,
57
+ intentional override (a known-good pre-release, a local path dependency
58
+ during development) — never to silently paper over a conflict without
59
+ understanding it, and say so in the report either way.
60
+
61
+ **Null-safety compile error:** fix the actual nullability gap — add a
62
+ null check, use `?.`/`??`, make a constructor parameter `required` or give
63
+ it a default, or correct a type that should not have been nullable in the
64
+ first place. Never add `!` purely to make the compiler stop complaining
65
+ without confirming the value is actually non-null at that point.
66
+
67
+ **Analyzer/lint finding:** fix the underlying issue the finding names
68
+ (the real missing override, the actual unused import, the genuine dead
69
+ code). Never add `// ignore: <rule>` or a blanket `// ignore_for_file:`
70
+ comment whose only purpose is to make the analyzer stop complaining
71
+ without addressing what it found.
72
+
73
+ **Failing test:** read the assertion failure and fix the actual cause —
74
+ either the implementation has a real bug the test correctly caught (fix
75
+ the implementation, say so), or the test/fixture is stale (fix the test).
76
+ Never delete or weaken a `find`/`expect` assertion just to reach green.
77
+
78
+ ### Step 3: Verify
79
+
80
+ ```bash
81
+ flutter analyze
82
+ dart format --set-exit-if-changed .
83
+ flutter test
84
+ ```
85
+
86
+ Re-run `flutter build <platform>` if the original failure was a build (not
87
+ just an analyze/test) failure. All must exit 0 before reporting done.
88
+
89
+ ### Step 4: Report
90
+
91
+ ```
92
+ Fixed: pubspec.yaml/pubspec.lock version conflict (ran `flutter pub get`
93
+ after loosening a pinned transitive constraint)
94
+ - Root cause: pubspec.lock predated a direct dependency bump in
95
+ pubspec.yaml
96
+ - flutter analyze / dart format / flutter test all pass
97
+ ```
98
+
99
+ State the root cause in one sentence, not just "fixed the error."
100
+
101
+ ## Rules
102
+
103
+ - Find and fix the smallest change that addresses the actual root cause —
104
+ never widen a fix beyond what the failure requires.
105
+ - NEVER add `// ignore:` or `// ignore_for_file:` to silence an analyzer
106
+ finding instead of fixing what it found.
107
+ - NEVER add the bang operator (`!`) to a nullable value just to make a
108
+ compile error disappear without confirming non-nullability.
109
+ - NEVER add a `dependency_overrides` entry to route around a real version
110
+ conflict without confirming it is an intentional, documented override.
111
+ - NEVER delete or weaken a failing test's assertion to reach a green
112
+ build.
113
+
114
+ ## Red Flags
115
+
116
+ | Rationalization | Why it is wrong |
117
+ |---|---|
118
+ | "I'll add `// ignore: prefer_const_constructors` here so analyze passes" | Silences the finding without fixing the actual missed `const`, which is exactly the performance signal the lint exists to catch |
119
+ | "I'll just add `!` here so the compiler stops complaining about this nullable value" | Papers over a real null-safety gap the compiler correctly found; add a null check or `?.`/`??` instead of asserting past it |
120
+ | "This dependency conflict is annoying, I'll add a dependency_override to force the version I want" | Routes around a real incompatibility the version solver found without understanding why it conflicts; check `flutter pub deps` and resolve the actual conflict first |
121
+ | "This widget test is flaky, I'll just remove the assertion that's failing" | Hides a real bug or a genuinely broken test instead of fixing either one; read the failure and fix the actual cause |
122
+
123
+ ## Verification
124
+
125
+ Do not report the fix done until all of the following hold:
126
+
127
+ - `flutter analyze`, `dart format --set-exit-if-changed .`, and `flutter
128
+ test` all exit 0.
129
+ - `flutter build <platform>` exits 0 if the original failure was a build
130
+ failure.
131
+ - The change is the smallest one that addresses the stated root cause —
132
+ no unrelated files touched.
133
+ - The report states the root cause in one sentence, not just "build now
134
+ passes."