timetracker/AGENT.md
2026-08-03 21:51:48 +02:00

123 lines
5.5 KiB
Markdown

# AGENT.md — Timetrack
## Project Overview
Flutter time-tracking app for capturing and analysing working hours.
Targets: Android, iOS, Web. Data is stored locally (offline-first, no backend).
## Stack
| Concern | Choice |
|----------------|-------------------------------|
| Framework | Flutter 3.41 / Dart 3.11 |
| State | Riverpod (riverpod_annotation)|
| Database | Drift + SQLite |
| Navigation | go_router (StatefulShellRoute)|
| Charts | fl_chart |
| Models | freezed + json_serializable |
| Export | pdf + csv + share_plus |
| i18n | flutter_localizations (ARB) |
| Tests | flutter_test + mocktail |
## Architecture — Feature-first
```
lib/
main.dart # ProviderScope → App
app.dart # MaterialApp.router, theme, locales
core/
database/ # Drift AppDatabase, DAOs
router/ # GoRouter provider (app_router.dart)
theme/ # AppTheme.light / AppTheme.dark
l10n/ # ARB files + AppLocalizations
features/
timer/ # Active timer — start/stop, project select
entries/ # TimeEntry CRUD + manual input
projects/ # Project CRUD (name, color, description)
reports/ # Day/week/month views + fl_chart
settings/ # Theme toggle, language, export
```
Each feature follows: `data/``domain/``presentation/`
## Data Models
### Project
```dart
int id, String name, int colorValue, String? description,
DateTime? archivedAt
```
### TimeEntry
```dart
int id, int projectId, DateTime startTime, DateTime? endTime,
Duration? duration, String? note, List<String> tags
```
### Tag
```dart
int id, String name
```
Junction table `time_entry_tags` links entries ↔ tags.
Full schema: see `.ai/database.md`
## Riverpod Conventions
- Use `@riverpod` annotation (code-gen); run `dart run build_runner watch`
- Providers live in the feature's `data/` or `domain/` layer
- Never put providers in `presentation/` widgets directly — import from domain/data
- AsyncNotifier for async state, Notifier for sync state
## Navigation
- `AppRoutes` constants in `lib/core/router/app_router.dart`
- Bottom nav: `/timer` | `/entries` | `/projects` | `/reports` | `/settings`
- Deep links use GoRouter sub-routes inside each branch
## Coding Conventions
- **Language in code**: English (variables, comments, docs)
- **UI strings**: ARB files only — never hardcode display text
- **Models**: always `freezed` + `copyWith`; no mutable model classes
- **Async**: always `await`; no fire-and-forget without `unawaited()` annotation
- **Imports**: always `package:` imports, no relative `../` imports
- **Formatting**: `dart format` enforced; trailing commas required
- **Single quotes** throughout
## Testing
See `.ai/testing.md` for full conventions.
- Unit tests for all repository methods and domain logic
- Widget tests for each screen (golden tests optional)
- Use `mocktail` for mocking repositories in widget tests
- Test files mirror `lib/` structure under `test/`
## .ai/ Context Files
| File | Content |
|--------------------------|------------------------------------------|
| `.ai/database.md` | Full Drift schema, migration strategy |
| `.ai/architecture.md` | ADRs, dependency decisions |
| `.ai/testing.md` | Test conventions, patterns, examples |
| `.ai/tickets.md` | Ticket workflow, template, agent rules |
| `.ai/features/timer.md` | Timer state-machine, background rules |
| `.ai/features/reports.md`| Report queries, chart data format |
| `.ai/features/export.md` | CSV/PDF/JSON export logic |
## Ticket Workflow
Every step in an implementation plan becomes a ticket under `.tasks/`.
Full rules, the ticket template, and the agent workflow are in `.ai/tickets.md`.
**Short version:**
1. Break implementation plan into tickets → create in `.tasks/todo/`
2. Move one ticket to `.tasks/processing/` before starting work
3. Move to `.tasks/done/` when complete, then pick the next ticket
4. Update the overview table in `.tasks/README.md` for every new ticket
## Interacting with the User
When any decision, clarification, or preference is needed — no matter how small —
**always use the `question` tool** rather than asking in plain text.
This applies to architecture choices, naming, scope, priority, and ambiguous requirements.
Only skip the question tool when the answer can be unambiguously derived from the codebase or existing documentation.
## Do / Don't
| Do | Don't |
|-------------------------------------------------|----------------------------------------------|
| Use `ConsumerWidget` / `ConsumerStatefulWidget` | Don't use `StatefulWidget` + manual setState |
| Keep screens thin — delegate to providers | Don't put business logic in widgets |
| Use `drift` DAOs for all DB access | Don't use raw SQL strings outside DAOs |
| Write tests alongside new features | Don't commit untested repository methods |
| Export via `share_plus` share sheet | Don't write files to arbitrary paths |
| Use `freezed` for all domain models | Don't use plain Dart classes for models |
| Single active timer — stop before starting new | Don't allow concurrent timer instances |