4.2 KiB
4.2 KiB
Agent Guide
Preferences for AI agents working on this repository. Follow these strictly.
Architecture
State management: Riverpod only
- Use Riverpod for all state management and dependency injection.
- The app is wrapped in
ProviderScopeat the root (lib/main.dart). - Use the right provider type:
Provider<T>for services.FutureProvider<T>for async loads.StreamProvider<T>for reactive streams.StreamProvider.family<T, Param>for parameterized streams.StateNotifierProvider<N, T>for mutable, persisted state (seetrackerServiceProvider).
Services (business logic)
- All services are instance classes — never static.
- Accept dependencies via the constructor.
- Always expose via a
Provider.
final myServiceProvider = Provider<MyService>((ref) {
return MyService(ref.read(repositoryProvider));
});
class MyService {
final MyRepository _repository;
MyService(this._repository);
}
Repositories (data access)
Create a repository only when data access meets one of:
- Complex caching (in-memory + persistence).
- Stream management for reactive updates.
- Multiple specialized queries.
- Multiple consumers.
- Would otherwise be 100+ lines.
Otherwise, keep simple CRUD inline in the service. Never create thin repository wrappers that just delegate to a service.
Breaking circular dependencies
When two providers reference each other, add explicit types to break inference cycles:
final Provider<ServiceA> serviceAProvider = Provider<ServiceA>((ref) {
final ServiceB b = ref.read(serviceBProvider);
return ServiceA(b);
});
Code Quality (mandatory)
After every change, run in this order:
- Codegen (if
@freezedor@GenerateMockschanged):dart run build_runner build --delete-conflicting-outputs - Format (always, especially after codegen):
dart format . - Lints: use the ReadLints tool on modified files — must be clean.
- Analyzer:
flutter analyze— must show "No issues found!". - Tests:
flutter test— 0 failures. - Goldens (if UI changed and golden test exists):
flutter test <file> --update-goldensand commit PNGs alongside the UI change.
Never commit unformatted code, lints, analyzer warnings, or UI changes without corresponding golden updates. Never tell the user "it's clean" without running the checks.
Code Style
- Prefer
constconstructors everywhere possible. - Use
finalfor locals by default. - Avoid
dynamic— prefer explicit types. - Use Freezed for immutable data models; avoid hand-rolled
==/hashCode. - No narrative comments. Don't write
// increment the counter. Only comment non-obvious intent, trade-offs, or constraints. - Keep files focused; mirror
lib/structure intest/.
Testing
- Mock with
mockito+@GenerateMocks+build_runner. - Unit tests for services and models; golden tests for screens and widgets.
- Golden tests must run on macOS for consistent font rendering.
- Load bundled fonts in
test/flutter_test_config.dart. - Never skip failing tests to make CI pass — fix the root cause.
UI
- Define a single theme in
lib/widgets/theme.dartand reference design tokens (AppTokens) — no inline magic colors. - Keep
DESIGN_GUIDE.mddocumenting color palette, typography, spacing, and component patterns. Reference it before any UI work. - Build reusable widgets (
TrackerTile,BookTile,ProgressBar, etc.) instead of repeating styling. - Support both light and dark modes.
- Use
ListView.separatedfor lists with dividers.
Commits & PRs
- Commit messages focus on why, not what.
- Every commit on an open PR must be production-ready (format + analyze + test
- lints + goldens).
- Commit generated files (freezed, mocks, goldens) alongside the source changes that produced them.
- Don't open/push a PR until the full checklist passes.
General Agent Behavior
- Read
README.mdand this file before starting work. - Use todos for multi-step tasks; mark them complete promptly.
- Don't hide verification failures — report honestly and fix.
- Prefer editing existing files over creating new ones.
- Never create docs (
*.md) proactively unless asked. - Use specialized file tools (Read/Edit/Write) instead of
cat/sed/echo.