123 lines
4.2 KiB
Markdown
123 lines
4.2 KiB
Markdown
|
|
# 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 `ProviderScope` at 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 (see `trackerServiceProvider`).
|
||
|
|
|
||
|
|
### Services (business logic)
|
||
|
|
|
||
|
|
- All services are instance classes — never static.
|
||
|
|
- Accept dependencies via the constructor.
|
||
|
|
- Always expose via a `Provider`.
|
||
|
|
|
||
|
|
```dart
|
||
|
|
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:
|
||
|
|
|
||
|
|
```dart
|
||
|
|
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:
|
||
|
|
|
||
|
|
1. Codegen (if `@freezed` or `@GenerateMocks` changed):
|
||
|
|
`dart run build_runner build --delete-conflicting-outputs`
|
||
|
|
2. Format (always, especially after codegen): `dart format .`
|
||
|
|
3. Lints: use the ReadLints tool on modified files — must be clean.
|
||
|
|
4. Analyzer: `flutter analyze` — must show "No issues found!".
|
||
|
|
5. Tests: `flutter test` — 0 failures.
|
||
|
|
6. Goldens (if UI changed and golden test exists):
|
||
|
|
`flutter test <file> --update-goldens` and 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 `const` constructors everywhere possible.
|
||
|
|
- Use `final` for 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 in `test/`.
|
||
|
|
|
||
|
|
## 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.dart` and reference design tokens
|
||
|
|
(`AppTokens`) — no inline magic colors.
|
||
|
|
- Keep `DESIGN_GUIDE.md` documenting 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.separated` for 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.md` and 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`.
|