@cubis/foundry 0.3.71 → 0.3.73
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/CHANGELOG.md +23 -2
- package/dist/cli/core.js +9 -22
- package/dist/cli/core.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/core.ts +13 -22
- package/workflows/powers/accessibility/POWER.md +83 -94
- package/workflows/powers/accessibility/SKILL.md +82 -94
- package/workflows/powers/agent-design/POWER.md +201 -0
- package/workflows/powers/agent-design/SKILL.md +198 -0
- package/workflows/powers/agent-design/references/clarification-patterns.md +153 -0
- package/workflows/powers/agent-design/references/skill-testing.md +164 -0
- package/workflows/powers/agent-design/references/workflow-patterns.md +226 -0
- package/workflows/powers/agentic-eval/POWER.md +62 -0
- package/workflows/powers/agentic-eval/SKILL.md +59 -0
- package/workflows/powers/agentic-eval/references/rubric-and-regression-checklist.md +11 -0
- package/workflows/powers/api-designer/POWER.md +43 -71
- package/workflows/powers/api-designer/SKILL.md +43 -71
- package/workflows/powers/api-patterns/POWER.md +42 -56
- package/workflows/powers/api-patterns/SKILL.md +42 -57
- package/workflows/powers/architecture-designer/POWER.md +43 -60
- package/workflows/powers/architecture-designer/SKILL.md +43 -60
- package/workflows/powers/ask-questions-if-underspecified/POWER.md +51 -3
- package/workflows/powers/auth-architect/POWER.md +69 -0
- package/workflows/powers/auth-architect/SKILL.md +66 -0
- package/workflows/powers/auth-architect/references/session-token-policy-checklist.md +45 -0
- package/workflows/powers/behavioral-modes/POWER.md +100 -9
- package/workflows/powers/c-pro/POWER.md +105 -0
- package/workflows/powers/c-pro/SKILL.md +102 -0
- package/workflows/powers/c-pro/references/build-systems-and-toolchains.md +148 -0
- package/workflows/powers/c-pro/references/common-ub-and-portability.md +166 -0
- package/workflows/powers/c-pro/references/debugging-with-sanitizers.md +205 -0
- package/workflows/powers/c-pro/references/memory-safety-and-build-checklist.md +60 -0
- package/workflows/powers/c-pro/references/posix-and-platform-apis.md +244 -0
- package/workflows/powers/changelog-generator/POWER.md +127 -63
- package/workflows/powers/changelog-generator/SKILL.md +126 -63
- package/workflows/powers/ci-cd-pipelines/POWER.md +156 -0
- package/workflows/powers/ci-cd-pipelines/SKILL.md +153 -0
- package/workflows/powers/ci-cd-pipelines/references/github-actions-patterns.md +160 -0
- package/workflows/powers/ci-cd-pipelines/references/pipeline-security-checklist.md +57 -0
- package/workflows/powers/cli-developer/POWER.md +152 -95
- package/workflows/powers/cli-developer/SKILL.md +152 -95
- package/workflows/powers/cpp-pro/POWER.md +111 -0
- package/workflows/powers/cpp-pro/SKILL.md +108 -0
- package/workflows/powers/cpp-pro/references/concurrency-primitives.md +266 -0
- package/workflows/powers/cpp-pro/references/move-semantics-and-value-types.md +149 -0
- package/workflows/powers/cpp-pro/references/performance-and-profiling.md +191 -0
- package/workflows/powers/cpp-pro/references/raii-and-modern-cpp-checklist.md +87 -0
- package/workflows/powers/cpp-pro/references/template-and-concepts-patterns.md +205 -0
- package/workflows/powers/csharp-pro/POWER.md +47 -22
- package/workflows/powers/csharp-pro/SKILL.md +47 -22
- package/workflows/powers/dart-pro/POWER.md +68 -0
- package/workflows/powers/dart-pro/SKILL.md +65 -0
- package/workflows/powers/dart-pro/references/isolate-and-concurrency.md +180 -0
- package/workflows/powers/dart-pro/references/null-safety-and-async-patterns.md +133 -0
- package/workflows/powers/dart-pro/references/package-structure-and-linting.md +193 -0
- package/workflows/powers/dart-pro/references/sealed-records-patterns.md +173 -0
- package/workflows/powers/dart-pro/references/testing-and-mocking.md +235 -0
- package/workflows/powers/database-design/POWER.md +47 -33
- package/workflows/powers/database-design/SKILL.md +47 -33
- package/workflows/powers/database-optimizer/POWER.md +43 -64
- package/workflows/powers/database-optimizer/SKILL.md +43 -64
- package/workflows/powers/database-skills/POWER.md +59 -93
- package/workflows/powers/database-skills/SKILL.md +59 -93
- package/workflows/powers/debugging-strategies/POWER.md +69 -0
- package/workflows/powers/debugging-strategies/SKILL.md +66 -0
- package/workflows/powers/debugging-strategies/references/reproduce-isolate-verify-checklist.md +42 -0
- package/workflows/powers/deep-research/POWER.md +67 -0
- package/workflows/powers/deep-research/SKILL.md +64 -0
- package/workflows/powers/deep-research/references/multi-round-research-loop.md +80 -0
- package/workflows/powers/design-system-builder/POWER.md +130 -116
- package/workflows/powers/design-system-builder/SKILL.md +130 -116
- package/workflows/powers/devops-engineer/POWER.md +120 -57
- package/workflows/powers/devops-engineer/SKILL.md +120 -57
- package/workflows/powers/docker-kubernetes/POWER.md +94 -0
- package/workflows/powers/docker-kubernetes/SKILL.md +91 -0
- package/workflows/powers/docker-kubernetes/references/dockerfile-optimization-checklist.md +35 -0
- package/workflows/powers/docker-kubernetes/references/kubernetes-deployment-patterns.md +59 -0
- package/workflows/powers/documentation-templates/POWER.md +158 -127
- package/workflows/powers/documentation-templates/SKILL.md +158 -127
- package/workflows/powers/drizzle-expert/POWER.md +66 -0
- package/workflows/powers/drizzle-expert/SKILL.md +63 -0
- package/workflows/powers/drizzle-expert/references/runtime-pairing-matrix.md +16 -0
- package/workflows/powers/drizzle-expert/references/schema-and-migration-playbook.md +18 -0
- package/workflows/powers/error-ux-observability/POWER.md +144 -131
- package/workflows/powers/error-ux-observability/SKILL.md +143 -131
- package/workflows/powers/fastapi-expert/POWER.md +46 -60
- package/workflows/powers/fastapi-expert/SKILL.md +46 -60
- package/workflows/powers/firebase/POWER.md +65 -0
- package/workflows/powers/firebase/SKILL.md +62 -0
- package/workflows/powers/firebase/references/platform-routing.md +16 -0
- package/workflows/powers/firebase/references/rules-and-indexes-checklist.md +11 -0
- package/workflows/powers/flutter-design-system/POWER.md +63 -0
- package/workflows/powers/flutter-design-system/SKILL.md +60 -0
- package/workflows/powers/flutter-design-system/references/shared-widgets.md +29 -0
- package/workflows/powers/flutter-design-system/references/tokens-and-theme.md +34 -0
- package/workflows/powers/flutter-drift/POWER.md +65 -0
- package/workflows/powers/flutter-drift/SKILL.md +62 -0
- package/workflows/powers/flutter-drift/references/migrations.md +22 -0
- package/workflows/powers/flutter-drift/references/query-patterns.md +26 -0
- package/workflows/powers/flutter-feature/POWER.md +65 -0
- package/workflows/powers/flutter-feature/SKILL.md +62 -0
- package/workflows/powers/flutter-feature/references/architecture-rules.md +85 -0
- package/workflows/powers/flutter-feature/references/composite-provider.md +58 -0
- package/workflows/powers/flutter-feature/references/outbox-pattern.md +87 -0
- package/workflows/powers/flutter-feature/references/testing-patterns.md +218 -0
- package/workflows/powers/flutter-go-router/POWER.md +64 -0
- package/workflows/powers/flutter-go-router/SKILL.md +61 -0
- package/workflows/powers/flutter-go-router/references/guards-and-deeplinks.md +20 -0
- package/workflows/powers/flutter-go-router/references/typed-routes.md +27 -0
- package/workflows/powers/flutter-offline-sync/POWER.md +62 -0
- package/workflows/powers/flutter-offline-sync/SKILL.md +59 -0
- package/workflows/powers/flutter-offline-sync/references/outbox-full.md +44 -0
- package/workflows/powers/flutter-repository/POWER.md +64 -0
- package/workflows/powers/flutter-repository/SKILL.md +61 -0
- package/workflows/powers/flutter-repository/references/drift-patterns.md +21 -0
- package/workflows/powers/flutter-repository/references/retrofit-patterns.md +20 -0
- package/workflows/powers/flutter-riverpod/POWER.md +70 -0
- package/workflows/powers/flutter-riverpod/SKILL.md +67 -0
- package/workflows/powers/flutter-riverpod/references/async-and-mutations.md +19 -0
- package/workflows/powers/flutter-riverpod/references/async-lifecycle.md +19 -0
- package/workflows/powers/flutter-riverpod/references/provider-selection.md +20 -0
- package/workflows/powers/flutter-riverpod/references/testing.md +21 -0
- package/workflows/powers/flutter-riverpod/references/version-matrix.md +24 -0
- package/workflows/powers/flutter-state-machine/POWER.md +62 -0
- package/workflows/powers/flutter-state-machine/SKILL.md +59 -0
- package/workflows/powers/flutter-state-machine/references/app-state-contract.md +23 -0
- package/workflows/powers/flutter-state-machine/references/ui-rendering.md +14 -0
- package/workflows/powers/flutter-testing/POWER.md +64 -0
- package/workflows/powers/flutter-testing/SKILL.md +61 -0
- package/workflows/powers/flutter-testing/references/offline-sync-tests.md +16 -0
- package/workflows/powers/flutter-testing/references/test-layers.md +33 -0
- package/workflows/powers/frontend-code-review/POWER.md +137 -0
- package/workflows/powers/frontend-code-review/SKILL.md +134 -0
- package/workflows/powers/frontend-code-review/references/common-antipatterns.md +86 -0
- package/workflows/powers/frontend-code-review/references/performance-budgets.md +56 -0
- package/workflows/powers/frontend-code-review/references/review-checklists.md +47 -0
- package/workflows/powers/frontend-design/POWER.md +163 -362
- package/workflows/powers/frontend-design/SKILL.md +163 -362
- package/workflows/powers/game-development/POWER.md +57 -140
- package/workflows/powers/game-development/SKILL.md +57 -140
- package/workflows/powers/geo-fundamentals/POWER.md +64 -126
- package/workflows/powers/geo-fundamentals/SKILL.md +64 -127
- package/workflows/powers/git-workflow/POWER.md +135 -0
- package/workflows/powers/git-workflow/SKILL.md +132 -0
- package/workflows/powers/git-workflow/references/pr-review-checklist.md +63 -0
- package/workflows/powers/golang-pro/POWER.md +46 -35
- package/workflows/powers/golang-pro/SKILL.md +46 -35
- package/workflows/powers/graphql-architect/POWER.md +44 -62
- package/workflows/powers/graphql-architect/SKILL.md +44 -62
- package/workflows/powers/i18n-localization/POWER.md +118 -103
- package/workflows/powers/i18n-localization/SKILL.md +118 -103
- package/workflows/powers/java-pro/POWER.md +47 -22
- package/workflows/powers/java-pro/SKILL.md +47 -22
- package/workflows/powers/javascript-pro/POWER.md +47 -34
- package/workflows/powers/javascript-pro/SKILL.md +47 -34
- package/workflows/powers/kotlin-pro/POWER.md +46 -23
- package/workflows/powers/kotlin-pro/SKILL.md +46 -23
- package/workflows/powers/legacy-modernizer/POWER.md +43 -60
- package/workflows/powers/legacy-modernizer/SKILL.md +43 -60
- package/workflows/powers/mcp-builder/POWER.md +65 -0
- package/workflows/powers/mcp-builder/SKILL.md +62 -0
- package/workflows/powers/mcp-builder/references/testing-and-evals.md +17 -0
- package/workflows/powers/mcp-builder/references/transport-and-tool-design.md +17 -0
- package/workflows/powers/microservices-architect/POWER.md +43 -70
- package/workflows/powers/microservices-architect/SKILL.md +43 -70
- package/workflows/powers/mobile-design/POWER.md +110 -345
- package/workflows/powers/mobile-design/SKILL.md +110 -345
- package/workflows/powers/mongodb/POWER.md +67 -0
- package/workflows/powers/mongodb/SKILL.md +64 -0
- package/workflows/powers/mongodb/references/mongodb-checklist.md +20 -0
- package/workflows/powers/mysql/POWER.md +67 -0
- package/workflows/powers/mysql/SKILL.md +64 -0
- package/workflows/powers/mysql/references/mysql-checklist.md +20 -0
- package/workflows/powers/neki/POWER.md +67 -0
- package/workflows/powers/neki/SKILL.md +64 -0
- package/workflows/powers/neki/references/neki-checklist.md +18 -0
- package/workflows/powers/nestjs-expert/POWER.md +45 -91
- package/workflows/powers/nestjs-expert/SKILL.md +45 -91
- package/workflows/powers/nextjs-developer/POWER.md +51 -44
- package/workflows/powers/nextjs-developer/SKILL.md +51 -44
- package/workflows/powers/nodejs-best-practices/POWER.md +48 -29
- package/workflows/powers/nodejs-best-practices/SKILL.md +48 -29
- package/workflows/powers/observability/POWER.md +109 -0
- package/workflows/powers/observability/SKILL.md +106 -0
- package/workflows/powers/observability/references/alerting-and-slo-checklist.md +87 -0
- package/workflows/powers/observability/references/opentelemetry-setup-guide.md +121 -0
- package/workflows/powers/openai-docs/POWER.md +61 -0
- package/workflows/powers/openai-docs/SKILL.md +58 -0
- package/workflows/powers/openai-docs/references/official-source-playbook.md +10 -0
- package/workflows/powers/performance-profiling/POWER.md +61 -114
- package/workflows/powers/performance-profiling/SKILL.md +61 -114
- package/workflows/powers/php-pro/POWER.md +116 -0
- package/workflows/powers/php-pro/SKILL.md +113 -0
- package/workflows/powers/php-pro/references/architecture-and-di.md +239 -0
- package/workflows/powers/php-pro/references/modern-php-features.md +189 -0
- package/workflows/powers/php-pro/references/performance-and-deployment.md +197 -0
- package/workflows/powers/php-pro/references/php84-strict-typing-checklist.md +161 -0
- package/workflows/powers/php-pro/references/testing-and-static-analysis.md +235 -0
- package/workflows/powers/playwright-e2e/POWER.md +85 -0
- package/workflows/powers/playwright-e2e/SKILL.md +82 -0
- package/workflows/powers/playwright-e2e/references/locator-trace-flake-checklist.md +80 -0
- package/workflows/powers/postgres/POWER.md +67 -0
- package/workflows/powers/postgres/SKILL.md +64 -0
- package/workflows/powers/postgres/references/postgres-checklist.md +20 -0
- package/workflows/powers/prompt-engineer/POWER.md +47 -30
- package/workflows/powers/prompt-engineer/SKILL.md +47 -30
- package/workflows/powers/python-pro/POWER.md +47 -36
- package/workflows/powers/python-pro/SKILL.md +47 -36
- package/workflows/powers/react-best-practices/POWER.md +56 -33
- package/workflows/powers/react-best-practices/SKILL.md +56 -33
- package/workflows/powers/react-expert/POWER.md +47 -37
- package/workflows/powers/react-expert/SKILL.md +47 -37
- package/workflows/powers/redis/POWER.md +67 -0
- package/workflows/powers/redis/SKILL.md +64 -0
- package/workflows/powers/redis/references/redis-checklist.md +19 -0
- package/workflows/powers/ruby-pro/POWER.md +118 -0
- package/workflows/powers/ruby-pro/SKILL.md +115 -0
- package/workflows/powers/ruby-pro/references/modern-ruby-features.md +189 -0
- package/workflows/powers/ruby-pro/references/object-design-patterns.md +220 -0
- package/workflows/powers/ruby-pro/references/performance-and-profiling.md +224 -0
- package/workflows/powers/ruby-pro/references/ruby-concurrency-and-testing.md +190 -0
- package/workflows/powers/ruby-pro/references/testing-and-rspec.md +236 -0
- package/workflows/powers/rust-pro/POWER.md +45 -31
- package/workflows/powers/rust-pro/SKILL.md +45 -31
- package/workflows/powers/security-engineer/POWER.md +129 -0
- package/workflows/powers/security-engineer/SKILL.md +126 -0
- package/workflows/powers/seo-fundamentals/POWER.md +59 -102
- package/workflows/powers/seo-fundamentals/SKILL.md +59 -102
- package/workflows/powers/serverless-patterns/POWER.md +171 -0
- package/workflows/powers/serverless-patterns/SKILL.md +168 -0
- package/workflows/powers/skill-creator/POWER.md +90 -0
- package/workflows/powers/skill-creator/SKILL.md +87 -0
- package/workflows/powers/skill-creator/references/platform-formats.md +181 -0
- package/workflows/powers/skill-creator/references/schemas.md +430 -0
- package/workflows/powers/spec-miner/POWER.md +49 -57
- package/workflows/powers/spec-miner/SKILL.md +49 -57
- package/workflows/powers/sqlite/POWER.md +67 -0
- package/workflows/powers/sqlite/SKILL.md +64 -0
- package/workflows/powers/sqlite/references/sqlite-checklist.md +19 -0
- package/workflows/powers/sre-engineer/POWER.md +123 -64
- package/workflows/powers/sre-engineer/SKILL.md +123 -64
- package/workflows/powers/static-analysis/POWER.md +121 -77
- package/workflows/powers/static-analysis/SKILL.md +121 -77
- package/workflows/powers/stripe-best-practices/POWER.md +140 -17
- package/workflows/powers/stripe-best-practices/SKILL.md +139 -17
- package/workflows/powers/supabase/POWER.md +67 -0
- package/workflows/powers/supabase/SKILL.md +64 -0
- package/workflows/powers/supabase/references/supabase-checklist.md +19 -0
- package/workflows/powers/swift-pro/POWER.md +118 -0
- package/workflows/powers/swift-pro/SKILL.md +115 -0
- package/workflows/powers/swift-pro/references/concurrency-patterns.md +165 -0
- package/workflows/powers/swift-pro/references/protocol-and-generics.md +172 -0
- package/workflows/powers/swift-pro/references/sendable-and-isolation.md +116 -0
- package/workflows/powers/swift-pro/references/swift-concurrency-and-protocols.md +260 -0
- package/workflows/powers/swift-pro/references/testing-and-packages.md +192 -0
- package/workflows/powers/tailwind-patterns/POWER.md +71 -240
- package/workflows/powers/tailwind-patterns/SKILL.md +71 -240
- package/workflows/powers/testing-patterns/POWER.md +155 -10
- package/workflows/powers/testing-patterns/SKILL.md +155 -10
- package/workflows/powers/typescript-pro/POWER.md +47 -38
- package/workflows/powers/typescript-pro/SKILL.md +47 -38
- package/workflows/powers/vitess/POWER.md +67 -0
- package/workflows/powers/vitess/SKILL.md +64 -0
- package/workflows/powers/vitess/references/vitess-checklist.md +19 -0
- package/workflows/powers/vulnerability-scanner/POWER.md +146 -10
- package/workflows/powers/vulnerability-scanner/SKILL.md +146 -10
- package/workflows/powers/web-perf/POWER.md +43 -170
- package/workflows/powers/web-perf/SKILL.md +43 -170
- package/workflows/powers/webapp-testing/POWER.md +43 -164
- package/workflows/powers/webapp-testing/SKILL.md +43 -164
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/rules/GEMINI.md +65 -42
- package/workflows/workflows/agent-environment-setup/platforms/claude/rules/CLAUDE.md +8 -6
- package/workflows/workflows/agent-environment-setup/platforms/codex/rules/AGENTS.md +65 -41
- package/workflows/workflows/agent-environment-setup/platforms/copilot/rules/copilot-instructions.md +8 -6
- package/workflows/workflows/agent-environment-setup/shared/rules/STEERING.md +9 -8
- package/workflows/workflows/agent-environment-setup/shared/rules/overrides/codex.md +1 -1
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Testing Patterns Reference
|
|
2
|
+
|
|
3
|
+
## Layer 1: Repository Test (in-memory Drift + mocktail)
|
|
4
|
+
```dart
|
|
5
|
+
void main() {
|
|
6
|
+
late AppDatabase db;
|
|
7
|
+
late Mock<N>Api mockApi;
|
|
8
|
+
late MockOutboxService mockOutbox;
|
|
9
|
+
late MockConnectivityService mockConnectivity;
|
|
10
|
+
late <N>Repository sut;
|
|
11
|
+
|
|
12
|
+
setUp(() {
|
|
13
|
+
db = AppDatabase(NativeDatabase.memory());
|
|
14
|
+
mockApi = Mock<N>Api();
|
|
15
|
+
mockOutbox = MockOutboxService();
|
|
16
|
+
mockConnectivity = MockConnectivityService();
|
|
17
|
+
when(() => mockConnectivity.isOnline).thenAnswer((_) async => false);
|
|
18
|
+
sut = <N>Repository(
|
|
19
|
+
dao: <N>Dao(db),
|
|
20
|
+
api: mockApi,
|
|
21
|
+
outbox: mockOutbox,
|
|
22
|
+
connectivity: mockConnectivity,
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
tearDown(() => db.close());
|
|
27
|
+
|
|
28
|
+
group('create', () {
|
|
29
|
+
test('writes to local DB immediately', () async {
|
|
30
|
+
await sut.create(fake<N>Input());
|
|
31
|
+
final items = await db.<n>Dao.getAll();
|
|
32
|
+
expect(items.length, 1);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('enqueues in outbox with operationId', () async {
|
|
36
|
+
await sut.create(fake<N>Input());
|
|
37
|
+
verify(() => mockOutbox.enqueue(
|
|
38
|
+
operationId: any(named: 'operationId'),
|
|
39
|
+
feature: '<n>',
|
|
40
|
+
operation: 'create',
|
|
41
|
+
payload: any(named: 'payload'),
|
|
42
|
+
)).called(1);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test('does NOT call API directly', () async {
|
|
46
|
+
await sut.create(fake<N>Input());
|
|
47
|
+
verifyNever(() => mockApi.create(any()));
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
group('syncFromRemote', () {
|
|
52
|
+
test('upserts all remote records into local DB', () async {
|
|
53
|
+
when(() => mockApi.getAll()).thenAnswer((_) async => [fake<N>Dto()]);
|
|
54
|
+
await sut.syncFromRemote();
|
|
55
|
+
final items = await db.<n>Dao.getAll();
|
|
56
|
+
expect(items.length, 1);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Layer 2: Service Test (pure Dart — no Flutter, no Riverpod)
|
|
63
|
+
```dart
|
|
64
|
+
void main() {
|
|
65
|
+
late <N>Service sut;
|
|
66
|
+
late Mock<N>Repository mockRepo;
|
|
67
|
+
|
|
68
|
+
setUp(() {
|
|
69
|
+
mockRepo = Mock<N>Repository();
|
|
70
|
+
sut = <N>Service(repository: mockRepo, /* other deps */);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
group('<operation>', () {
|
|
74
|
+
test('returns Left when <failure condition>', () async {
|
|
75
|
+
// Arrange: set up conditions that trigger failure
|
|
76
|
+
final result = await sut.<operation>(/* bad input */);
|
|
77
|
+
expect(result.isLeft(), true);
|
|
78
|
+
result.fold(
|
|
79
|
+
(err) => expect(err, isA<ClientError>()),
|
|
80
|
+
(_) => fail('should have been Left'),
|
|
81
|
+
);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('returns Right on success', () async {
|
|
85
|
+
when(() => mockRepo.<action>(any())).thenAnswer((_) async => fake<N>());
|
|
86
|
+
final result = await sut.<operation>(/* valid input */);
|
|
87
|
+
expect(result.isRight(), true);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Layer 3: Notifier Test (ProviderContainer)
|
|
94
|
+
```dart
|
|
95
|
+
void main() {
|
|
96
|
+
late ProviderContainer container;
|
|
97
|
+
|
|
98
|
+
ProviderContainer makeContainer({List<Override> overrides = const []}) =>
|
|
99
|
+
ProviderContainer(overrides: [
|
|
100
|
+
<n>RepositoryProvider.overrideWith((_) => Fake<N>Repository()),
|
|
101
|
+
...overrides,
|
|
102
|
+
]);
|
|
103
|
+
|
|
104
|
+
tearDown(() => container.dispose());
|
|
105
|
+
|
|
106
|
+
test('initial state is AppState.loading()', () {
|
|
107
|
+
container = makeContainer();
|
|
108
|
+
expect(container.read(<n>NotifierProvider), const AppState.loading());
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test('transitions to AppState.data when items exist', () async {
|
|
112
|
+
container = makeContainer();
|
|
113
|
+
await container.pump(); // allow stream to emit
|
|
114
|
+
expect(container.read(<n>NotifierProvider), isA<_Data>());
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test('transitions to AppState.empty when no items', () async {
|
|
118
|
+
container = makeContainer(overrides: [
|
|
119
|
+
<n>RepositoryProvider.overrideWith((_) => Empty<N>Repository()),
|
|
120
|
+
]);
|
|
121
|
+
await container.pump();
|
|
122
|
+
expect(container.read(<n>NotifierProvider), const AppState.empty());
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('error state contains non-empty requestId', () async {
|
|
126
|
+
container = makeContainer(overrides: [
|
|
127
|
+
<n>RepositoryProvider.overrideWith((_) => Failing<N>Repository()),
|
|
128
|
+
]);
|
|
129
|
+
await container.pump();
|
|
130
|
+
final state = container.read(<n>NotifierProvider);
|
|
131
|
+
expect(state, isA<_Error>());
|
|
132
|
+
expect((state as _Error).error.requestId, isNotEmpty);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Layer 4: Widget Test (all 5 AppState variants)
|
|
138
|
+
```dart
|
|
139
|
+
void main() {
|
|
140
|
+
Widget buildSubject(AppState<List<<N>>> state) =>
|
|
141
|
+
ProviderScope(
|
|
142
|
+
overrides: [
|
|
143
|
+
<n>NotifierProvider.overrideWith((_) => FixedState<N>Notifier(state)),
|
|
144
|
+
],
|
|
145
|
+
child: const MaterialApp(home: <N>ListPage()),
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
testWidgets('shows LoadingView in loading state', (tester) async {
|
|
149
|
+
await tester.pumpWidget(buildSubject(const AppState.loading()));
|
|
150
|
+
expect(find.byType(LoadingView), findsOneWidget);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
testWidgets('shows EmptyView in empty state', (tester) async {
|
|
154
|
+
await tester.pumpWidget(buildSubject(const AppState.empty()));
|
|
155
|
+
expect(find.byType(EmptyView), findsOneWidget);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
testWidgets('shows data in data state', (tester) async {
|
|
159
|
+
await tester.pumpWidget(buildSubject(AppState.data([fake<N>()])));
|
|
160
|
+
expect(find.byType(<N>Card), findsOneWidget);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
testWidgets('shows ErrorView with selectable requestId', (tester) async {
|
|
164
|
+
final err = AppError.network(requestId: 'test-req-id', userMessage: 'Oops');
|
|
165
|
+
await tester.pumpWidget(buildSubject(AppState.error(err)));
|
|
166
|
+
expect(find.byType(ErrorView), findsOneWidget);
|
|
167
|
+
expect(find.textContaining('test-req-id'), findsOneWidget);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
testWidgets('shows DeadLetterView with retry button', (tester) async {
|
|
171
|
+
final err = AppError.syncDead(requestId: 'dlq-id', feature: '<n>',
|
|
172
|
+
operation: 'create', userMessage: 'Failed', errorLog: []);
|
|
173
|
+
await tester.pumpWidget(buildSubject(
|
|
174
|
+
AppState.deadLetter(error: err, requestId: 'dlq-id'),
|
|
175
|
+
));
|
|
176
|
+
expect(find.byType(DeadLetterView), findsOneWidget);
|
|
177
|
+
expect(find.text('Retry'), findsOneWidget);
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Layer 5: Golden Test (shared widgets)
|
|
183
|
+
```dart
|
|
184
|
+
void main() {
|
|
185
|
+
testGoldens('ErrorView renders correctly', (tester) async {
|
|
186
|
+
await loadAppFonts();
|
|
187
|
+
await tester.pumpWidgetBuilder(
|
|
188
|
+
ErrorView(
|
|
189
|
+
error: AppError.network(requestId: 'abc-123', userMessage: 'No connection'),
|
|
190
|
+
onRetry: () {},
|
|
191
|
+
),
|
|
192
|
+
surfaceSize: const Size(400, 300),
|
|
193
|
+
);
|
|
194
|
+
await screenMatchesGolden(tester, 'error_view');
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Fake Repository Helpers
|
|
200
|
+
```dart
|
|
201
|
+
// Always create typed fakes — never use mocks for repositories in widget tests
|
|
202
|
+
class Fake<N>Repository implements <N>Repository {
|
|
203
|
+
final List<<N>> items;
|
|
204
|
+
Fake<N>Repository({this.items = const []});
|
|
205
|
+
|
|
206
|
+
@override Stream<List<<N>>> watchAll() => Stream.value(items);
|
|
207
|
+
@override Future<bool> isEmpty() async => items.isEmpty;
|
|
208
|
+
@override Future<<N>> create(Create<N>Input input) async => fake<N>();
|
|
209
|
+
@override Future<void> syncFromRemote() async {}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
class Failing<N>Repository implements <N>Repository {
|
|
213
|
+
@override Stream<List<<N>>> watchAll() => Stream.error(
|
|
214
|
+
Exception('DB error'), StackTrace.empty,
|
|
215
|
+
);
|
|
216
|
+
// ... other methods throw
|
|
217
|
+
}
|
|
218
|
+
```
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
````markdown
|
|
2
|
+
---
|
|
3
|
+
inclusion: manual
|
|
4
|
+
name: flutter-go-router
|
|
5
|
+
description: "Use when adding or refactoring typed GoRouter navigation, guards, shell routes, deep links, or notification-driven routing in Flutter. Do not use for state management or feature business logic."
|
|
6
|
+
license: MIT
|
|
7
|
+
metadata:
|
|
8
|
+
author: cubis-foundry
|
|
9
|
+
version: "1.0"
|
|
10
|
+
compatibility: Claude Code, Codex, GitHub Copilot
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Flutter GoRouter
|
|
14
|
+
|
|
15
|
+
## Purpose
|
|
16
|
+
|
|
17
|
+
Guide typed Flutter navigation architecture with safe redirects, deep-link
|
|
18
|
+
handling, and predictable shell-route behavior.
|
|
19
|
+
|
|
20
|
+
## When to Use
|
|
21
|
+
|
|
22
|
+
- Adding a route or nested route
|
|
23
|
+
- Introducing auth or init guards
|
|
24
|
+
- Adding a bottom-nav shell
|
|
25
|
+
- Handling deep links or FCM notification taps
|
|
26
|
+
- Fixing redirect loops or back-stack issues
|
|
27
|
+
|
|
28
|
+
## Instructions
|
|
29
|
+
|
|
30
|
+
1. Define the route map and parameter shape first.
|
|
31
|
+
2. Choose the right route type for the navigation behavior.
|
|
32
|
+
3. Use typed route classes instead of raw string paths in widgets.
|
|
33
|
+
4. Keep `redirect` and `onEnter` pure, fast, and loop-safe.
|
|
34
|
+
5. Validate deep-link inputs before building pages.
|
|
35
|
+
6. Preserve branch stacks intentionally when using shell navigation.
|
|
36
|
+
7. Add tests for guards, deep links, and shell-route behavior where the flow is non-trivial.
|
|
37
|
+
|
|
38
|
+
## Output Format
|
|
39
|
+
|
|
40
|
+
Produce navigation guidance or code that:
|
|
41
|
+
|
|
42
|
+
- uses typed routes intentionally,
|
|
43
|
+
- explains guard and deep-link decisions,
|
|
44
|
+
- identifies shell-route versus standard-route boundaries,
|
|
45
|
+
- includes edge cases for invalid params or redirect loops.
|
|
46
|
+
|
|
47
|
+
## References
|
|
48
|
+
|
|
49
|
+
Load only what the current step needs.
|
|
50
|
+
|
|
51
|
+
| File | Load when |
|
|
52
|
+
| --- | --- |
|
|
53
|
+
| `references/typed-routes.md` | Defining route files, params, query handling, or typed route usage patterns. |
|
|
54
|
+
| `references/guards-and-deeplinks.md` | Adding auth guards, splash/init gates, notification routing, or shell-route preservation. |
|
|
55
|
+
|
|
56
|
+
## Scripts
|
|
57
|
+
|
|
58
|
+
No helper scripts are required for this skill right now.
|
|
59
|
+
|
|
60
|
+
## Examples
|
|
61
|
+
|
|
62
|
+
- "Add a typed detail route and deep-link handling for products."
|
|
63
|
+
- "Set up a stateful shell route for Flutter bottom navigation."
|
|
64
|
+
````
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: flutter-go-router
|
|
3
|
+
description: "Use when adding or refactoring typed GoRouter navigation, guards, shell routes, deep links, or notification-driven routing in Flutter. Do not use for state management or feature business logic."
|
|
4
|
+
license: MIT
|
|
5
|
+
metadata:
|
|
6
|
+
author: cubis-foundry
|
|
7
|
+
version: "1.0"
|
|
8
|
+
compatibility: Claude Code, Codex, GitHub Copilot
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Flutter GoRouter
|
|
12
|
+
|
|
13
|
+
## Purpose
|
|
14
|
+
|
|
15
|
+
Guide typed Flutter navigation architecture with safe redirects, deep-link
|
|
16
|
+
handling, and predictable shell-route behavior.
|
|
17
|
+
|
|
18
|
+
## When to Use
|
|
19
|
+
|
|
20
|
+
- Adding a route or nested route
|
|
21
|
+
- Introducing auth or init guards
|
|
22
|
+
- Adding a bottom-nav shell
|
|
23
|
+
- Handling deep links or FCM notification taps
|
|
24
|
+
- Fixing redirect loops or back-stack issues
|
|
25
|
+
|
|
26
|
+
## Instructions
|
|
27
|
+
|
|
28
|
+
1. Define the route map and parameter shape first.
|
|
29
|
+
2. Choose the right route type for the navigation behavior.
|
|
30
|
+
3. Use typed route classes instead of raw string paths in widgets.
|
|
31
|
+
4. Keep `redirect` and `onEnter` pure, fast, and loop-safe.
|
|
32
|
+
5. Validate deep-link inputs before building pages.
|
|
33
|
+
6. Preserve branch stacks intentionally when using shell navigation.
|
|
34
|
+
7. Add tests for guards, deep links, and shell-route behavior where the flow is non-trivial.
|
|
35
|
+
|
|
36
|
+
## Output Format
|
|
37
|
+
|
|
38
|
+
Produce navigation guidance or code that:
|
|
39
|
+
|
|
40
|
+
- uses typed routes intentionally,
|
|
41
|
+
- explains guard and deep-link decisions,
|
|
42
|
+
- identifies shell-route versus standard-route boundaries,
|
|
43
|
+
- includes edge cases for invalid params or redirect loops.
|
|
44
|
+
|
|
45
|
+
## References
|
|
46
|
+
|
|
47
|
+
Load only what the current step needs.
|
|
48
|
+
|
|
49
|
+
| File | Load when |
|
|
50
|
+
| --- | --- |
|
|
51
|
+
| `references/typed-routes.md` | Defining route files, params, query handling, or typed route usage patterns. |
|
|
52
|
+
| `references/guards-and-deeplinks.md` | Adding auth guards, splash/init gates, notification routing, or shell-route preservation. |
|
|
53
|
+
|
|
54
|
+
## Scripts
|
|
55
|
+
|
|
56
|
+
No helper scripts are required for this skill right now.
|
|
57
|
+
|
|
58
|
+
## Examples
|
|
59
|
+
|
|
60
|
+
- "Add a typed detail route and deep-link handling for products."
|
|
61
|
+
- "Set up a stateful shell route for Flutter bottom navigation."
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Guards and Deep Links
|
|
2
|
+
|
|
3
|
+
## Guard Rules
|
|
4
|
+
|
|
5
|
+
- Redirect functions stay pure and deterministic.
|
|
6
|
+
- Check the current matched location before redirecting to avoid loops.
|
|
7
|
+
- Preserve user intent with a `from` query when redirecting to auth.
|
|
8
|
+
- Keep init/auth guards separate when they represent different state machines.
|
|
9
|
+
|
|
10
|
+
## Deep-Link Rules
|
|
11
|
+
|
|
12
|
+
- Validate required IDs and query params before building the page.
|
|
13
|
+
- Route invalid or incomplete links to a safe fallback or error screen.
|
|
14
|
+
- Keep notification payload parsing outside widgets when possible.
|
|
15
|
+
|
|
16
|
+
## Shell Navigation
|
|
17
|
+
|
|
18
|
+
- Use stateful shell navigation when each tab needs its own stack.
|
|
19
|
+
- Give each branch its own navigator key.
|
|
20
|
+
- Test back navigation and tab switching explicitly.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Typed Routes
|
|
2
|
+
|
|
3
|
+
## Route File Layout
|
|
4
|
+
|
|
5
|
+
Prefer a dedicated routing area such as:
|
|
6
|
+
|
|
7
|
+
- `lib/core/routing/app_router.dart`
|
|
8
|
+
- `lib/core/routing/routes/<feature>_route.dart`
|
|
9
|
+
|
|
10
|
+
## Route Type Choice
|
|
11
|
+
|
|
12
|
+
- `GoRouteData` for normal screen routes
|
|
13
|
+
- `ShellRouteData` for shared wrappers with one navigator
|
|
14
|
+
- stateful shell route for persistent tabs with independent stacks
|
|
15
|
+
|
|
16
|
+
## Parameter Rules
|
|
17
|
+
|
|
18
|
+
- Required path params for canonical resource identity
|
|
19
|
+
- Optional query params for filters, search, and non-identity state
|
|
20
|
+
- Use `extra` sparingly and avoid relying on it for deep-linkable flows
|
|
21
|
+
|
|
22
|
+
## Widget Usage
|
|
23
|
+
|
|
24
|
+
- `ProductListRoute().go(context)`
|
|
25
|
+
- `ProductDetailRoute(id: id).push(context)`
|
|
26
|
+
|
|
27
|
+
Do not call `context.go('/products')` from widgets when typed routes exist.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
````markdown
|
|
2
|
+
---
|
|
3
|
+
inclusion: manual
|
|
4
|
+
name: flutter-offline-sync
|
|
5
|
+
description: "Use when implementing or auditing offline-first sync in Flutter with a local database, outbox queue, retry policy, conflict handling, and dead-letter behavior. Do not use for simple online-only CRUD."
|
|
6
|
+
license: MIT
|
|
7
|
+
metadata:
|
|
8
|
+
author: cubis-foundry
|
|
9
|
+
version: "1.0"
|
|
10
|
+
compatibility: Claude Code, Codex, GitHub Copilot
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Flutter Offline Sync
|
|
14
|
+
|
|
15
|
+
## Purpose
|
|
16
|
+
|
|
17
|
+
Guide local-first write flows that reconcile with the server later through an
|
|
18
|
+
outbox queue, retry policy, and explicit conflict handling.
|
|
19
|
+
|
|
20
|
+
## When to Use
|
|
21
|
+
|
|
22
|
+
- Adding offline-first writes to a feature
|
|
23
|
+
- Designing or auditing outbox behavior
|
|
24
|
+
- Handling retry, dead-letter, or conflict states
|
|
25
|
+
- Wiring connectivity-driven background draining
|
|
26
|
+
|
|
27
|
+
## Instructions
|
|
28
|
+
|
|
29
|
+
1. Identify the feature and write operations that need offline behavior.
|
|
30
|
+
2. Choose a conflict strategy per feature.
|
|
31
|
+
3. Ensure the outbox infrastructure exists once per project.
|
|
32
|
+
4. Persist locally first, then enqueue sync work.
|
|
33
|
+
5. Never block UI completion on network success.
|
|
34
|
+
6. Surface sync status and dead-letter behavior clearly in the UI.
|
|
35
|
+
7. Keep retry policy bounded and explicit.
|
|
36
|
+
|
|
37
|
+
## Output Format
|
|
38
|
+
|
|
39
|
+
Produce offline-sync guidance or code that:
|
|
40
|
+
|
|
41
|
+
- shows the local-write then outbox-enqueue contract,
|
|
42
|
+
- names the retry, dead-letter, and conflict decisions,
|
|
43
|
+
- separates one-time infrastructure from per-feature integration,
|
|
44
|
+
- includes sync-status UI expectations when relevant.
|
|
45
|
+
|
|
46
|
+
## References
|
|
47
|
+
|
|
48
|
+
Load only what the current step needs.
|
|
49
|
+
|
|
50
|
+
| File | Load when |
|
|
51
|
+
| --- | --- |
|
|
52
|
+
| `references/outbox-full.md` | Setting up the outbox table or service, connectivity listeners, feature handlers, retry logic, or dead-letter UI. |
|
|
53
|
+
|
|
54
|
+
## Scripts
|
|
55
|
+
|
|
56
|
+
No helper scripts are required for this skill right now.
|
|
57
|
+
|
|
58
|
+
## Examples
|
|
59
|
+
|
|
60
|
+
- "Add offline-first create and update support to this Flutter repository."
|
|
61
|
+
- "Review this outbox flow for retry and dead-letter mistakes."
|
|
62
|
+
````
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: flutter-offline-sync
|
|
3
|
+
description: "Use when implementing or auditing offline-first sync in Flutter with a local database, outbox queue, retry policy, conflict handling, and dead-letter behavior. Do not use for simple online-only CRUD."
|
|
4
|
+
license: MIT
|
|
5
|
+
metadata:
|
|
6
|
+
author: cubis-foundry
|
|
7
|
+
version: "1.0"
|
|
8
|
+
compatibility: Claude Code, Codex, GitHub Copilot
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Flutter Offline Sync
|
|
12
|
+
|
|
13
|
+
## Purpose
|
|
14
|
+
|
|
15
|
+
Guide local-first write flows that reconcile with the server later through an
|
|
16
|
+
outbox queue, retry policy, and explicit conflict handling.
|
|
17
|
+
|
|
18
|
+
## When to Use
|
|
19
|
+
|
|
20
|
+
- Adding offline-first writes to a feature
|
|
21
|
+
- Designing or auditing outbox behavior
|
|
22
|
+
- Handling retry, dead-letter, or conflict states
|
|
23
|
+
- Wiring connectivity-driven background draining
|
|
24
|
+
|
|
25
|
+
## Instructions
|
|
26
|
+
|
|
27
|
+
1. Identify the feature and write operations that need offline behavior.
|
|
28
|
+
2. Choose a conflict strategy per feature.
|
|
29
|
+
3. Ensure the outbox infrastructure exists once per project.
|
|
30
|
+
4. Persist locally first, then enqueue sync work.
|
|
31
|
+
5. Never block UI completion on network success.
|
|
32
|
+
6. Surface sync status and dead-letter behavior clearly in the UI.
|
|
33
|
+
7. Keep retry policy bounded and explicit.
|
|
34
|
+
|
|
35
|
+
## Output Format
|
|
36
|
+
|
|
37
|
+
Produce offline-sync guidance or code that:
|
|
38
|
+
|
|
39
|
+
- shows the local-write then outbox-enqueue contract,
|
|
40
|
+
- names the retry, dead-letter, and conflict decisions,
|
|
41
|
+
- separates one-time infrastructure from per-feature integration,
|
|
42
|
+
- includes sync-status UI expectations when relevant.
|
|
43
|
+
|
|
44
|
+
## References
|
|
45
|
+
|
|
46
|
+
Load only what the current step needs.
|
|
47
|
+
|
|
48
|
+
| File | Load when |
|
|
49
|
+
| --- | --- |
|
|
50
|
+
| `references/outbox-full.md` | Setting up the outbox table or service, connectivity listeners, feature handlers, retry logic, or dead-letter UI. |
|
|
51
|
+
|
|
52
|
+
## Scripts
|
|
53
|
+
|
|
54
|
+
No helper scripts are required for this skill right now.
|
|
55
|
+
|
|
56
|
+
## Examples
|
|
57
|
+
|
|
58
|
+
- "Add offline-first create and update support to this Flutter repository."
|
|
59
|
+
- "Review this outbox flow for retry and dead-letter mistakes."
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Outbox Full
|
|
2
|
+
|
|
3
|
+
## One-Time Infrastructure
|
|
4
|
+
|
|
5
|
+
- Outbox table persisted in Drift
|
|
6
|
+
- Outbox service responsible for dequeue, dispatch, retry, and dead-letter transitions
|
|
7
|
+
- Connectivity service that triggers draining when the device comes back online
|
|
8
|
+
- Optional app-init seeding for empty local stores
|
|
9
|
+
|
|
10
|
+
## Repository Write Contract
|
|
11
|
+
|
|
12
|
+
1. Generate an operation ID.
|
|
13
|
+
2. Persist the local change.
|
|
14
|
+
3. Enqueue the serialized operation.
|
|
15
|
+
4. Trigger a non-blocking drain when online.
|
|
16
|
+
5. Return the local result immediately.
|
|
17
|
+
|
|
18
|
+
## Feature Handler Contract
|
|
19
|
+
|
|
20
|
+
Each queued feature operation needs a handler that:
|
|
21
|
+
|
|
22
|
+
- decodes the payload,
|
|
23
|
+
- calls the correct API operation,
|
|
24
|
+
- marks success or updates retry/dead-letter state,
|
|
25
|
+
- applies conflict policy when the server rejects the write semantically.
|
|
26
|
+
|
|
27
|
+
## Sync Status Contract
|
|
28
|
+
|
|
29
|
+
Offline-capable records should expose a sync field such as:
|
|
30
|
+
|
|
31
|
+
- `pendingSync`
|
|
32
|
+
- `synced`
|
|
33
|
+
- `failed`
|
|
34
|
+
- `dead`
|
|
35
|
+
- `conflict`
|
|
36
|
+
|
|
37
|
+
## Conflict Strategies
|
|
38
|
+
|
|
39
|
+
- `clientWins`
|
|
40
|
+
- `serverWins`
|
|
41
|
+
- `lastWriteWins`
|
|
42
|
+
- `manualResolve`
|
|
43
|
+
|
|
44
|
+
Pick one per feature. Safety-critical data should not default to silent overwrite.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
````markdown
|
|
2
|
+
---
|
|
3
|
+
inclusion: manual
|
|
4
|
+
name: flutter-repository
|
|
5
|
+
description: "Use when building or refactoring a Flutter feature data layer: Drift tables and DAOs, DTOs, mappers, Retrofit APIs, and repository orchestration. Do not use when the task needs a full feature scaffold across presentation and routing."
|
|
6
|
+
license: MIT
|
|
7
|
+
metadata:
|
|
8
|
+
author: cubis-foundry
|
|
9
|
+
version: "1.0"
|
|
10
|
+
compatibility: Claude Code, Codex, GitHub Copilot
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Flutter Repository
|
|
14
|
+
|
|
15
|
+
## Purpose
|
|
16
|
+
|
|
17
|
+
Generate or review one Flutter feature's data layer while keeping persistence,
|
|
18
|
+
transport, mapping, and orchestration properly separated.
|
|
19
|
+
|
|
20
|
+
## When to Use
|
|
21
|
+
|
|
22
|
+
- Adding a new repository
|
|
23
|
+
- Adding local tables or DAOs
|
|
24
|
+
- Adding DTOs and network API interfaces
|
|
25
|
+
- Wiring local-first read/write behavior
|
|
26
|
+
- Updating sync logic in an existing repository
|
|
27
|
+
|
|
28
|
+
## Instructions
|
|
29
|
+
|
|
30
|
+
1. Define the local table and DAO contract first.
|
|
31
|
+
2. Define DTOs and the remote API interface separately.
|
|
32
|
+
3. Keep mapping logic outside large repository methods where possible.
|
|
33
|
+
4. Let repositories own local and remote coordination.
|
|
34
|
+
5. Keep DAOs persistence-focused and DTOs transport-focused.
|
|
35
|
+
6. If offline sync exists, persist locally and enqueue sync work instead of blocking on the network.
|
|
36
|
+
7. Add tests for local-first reads, writes, and sync behavior.
|
|
37
|
+
|
|
38
|
+
## Output Format
|
|
39
|
+
|
|
40
|
+
Produce repository-layer guidance or code that:
|
|
41
|
+
|
|
42
|
+
- separates table, DAO, DTO, mapper, API, and repository responsibilities,
|
|
43
|
+
- explains any offline-sync behavior,
|
|
44
|
+
- identifies test points for read, write, and sync flows,
|
|
45
|
+
- avoids collapsing the whole data layer into a single file.
|
|
46
|
+
|
|
47
|
+
## References
|
|
48
|
+
|
|
49
|
+
Load only what the current step needs.
|
|
50
|
+
|
|
51
|
+
| File | Load when |
|
|
52
|
+
| --- | --- |
|
|
53
|
+
| `references/drift-patterns.md` | Designing local tables, DAO helpers, sync-status fields, or Drift-side read and write helpers. |
|
|
54
|
+
| `references/retrofit-patterns.md` | Designing DTOs, Retrofit interfaces, mapper boundaries, or repository orchestration. |
|
|
55
|
+
|
|
56
|
+
## Scripts
|
|
57
|
+
|
|
58
|
+
No helper scripts are required for this skill right now.
|
|
59
|
+
|
|
60
|
+
## Examples
|
|
61
|
+
|
|
62
|
+
- "Create the Flutter repository layer for a new offline-capable entity."
|
|
63
|
+
- "Refactor this feature repository so DAO, DTO, and mapping logic are separated."
|
|
64
|
+
````
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: flutter-repository
|
|
3
|
+
description: "Use when building or refactoring a Flutter feature data layer: Drift tables and DAOs, DTOs, mappers, Retrofit APIs, and repository orchestration. Do not use when the task needs a full feature scaffold across presentation and routing."
|
|
4
|
+
license: MIT
|
|
5
|
+
metadata:
|
|
6
|
+
author: cubis-foundry
|
|
7
|
+
version: "1.0"
|
|
8
|
+
compatibility: Claude Code, Codex, GitHub Copilot
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Flutter Repository
|
|
12
|
+
|
|
13
|
+
## Purpose
|
|
14
|
+
|
|
15
|
+
Generate or review one Flutter feature's data layer while keeping persistence,
|
|
16
|
+
transport, mapping, and orchestration properly separated.
|
|
17
|
+
|
|
18
|
+
## When to Use
|
|
19
|
+
|
|
20
|
+
- Adding a new repository
|
|
21
|
+
- Adding local tables or DAOs
|
|
22
|
+
- Adding DTOs and network API interfaces
|
|
23
|
+
- Wiring local-first read/write behavior
|
|
24
|
+
- Updating sync logic in an existing repository
|
|
25
|
+
|
|
26
|
+
## Instructions
|
|
27
|
+
|
|
28
|
+
1. Define the local table and DAO contract first.
|
|
29
|
+
2. Define DTOs and the remote API interface separately.
|
|
30
|
+
3. Keep mapping logic outside large repository methods where possible.
|
|
31
|
+
4. Let repositories own local and remote coordination.
|
|
32
|
+
5. Keep DAOs persistence-focused and DTOs transport-focused.
|
|
33
|
+
6. If offline sync exists, persist locally and enqueue sync work instead of blocking on the network.
|
|
34
|
+
7. Add tests for local-first reads, writes, and sync behavior.
|
|
35
|
+
|
|
36
|
+
## Output Format
|
|
37
|
+
|
|
38
|
+
Produce repository-layer guidance or code that:
|
|
39
|
+
|
|
40
|
+
- separates table, DAO, DTO, mapper, API, and repository responsibilities,
|
|
41
|
+
- explains any offline-sync behavior,
|
|
42
|
+
- identifies test points for read, write, and sync flows,
|
|
43
|
+
- avoids collapsing the whole data layer into a single file.
|
|
44
|
+
|
|
45
|
+
## References
|
|
46
|
+
|
|
47
|
+
Load only what the current step needs.
|
|
48
|
+
|
|
49
|
+
| File | Load when |
|
|
50
|
+
| --- | --- |
|
|
51
|
+
| `references/drift-patterns.md` | Designing local tables, DAO helpers, sync-status fields, or Drift-side read and write helpers. |
|
|
52
|
+
| `references/retrofit-patterns.md` | Designing DTOs, Retrofit interfaces, mapper boundaries, or repository orchestration. |
|
|
53
|
+
|
|
54
|
+
## Scripts
|
|
55
|
+
|
|
56
|
+
No helper scripts are required for this skill right now.
|
|
57
|
+
|
|
58
|
+
## Examples
|
|
59
|
+
|
|
60
|
+
- "Create the Flutter repository layer for a new offline-capable entity."
|
|
61
|
+
- "Refactor this feature repository so DAO, DTO, and mapping logic are separated."
|