123 lines
5.5 KiB
Markdown
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 |
|