docs(agents): split the release ritual into a repo-local playbook
The full release procedure was loading in every Frosty session. Same split as the dotfiles resync playbook: always-on file stays gotchas, the ritual lives in docs/release.md. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
0937a1c5ad
commit
dc444810b1
2 changed files with 84 additions and 32 deletions
61
AGENTS.md
61
AGENTS.md
|
|
@ -1,49 +1,46 @@
|
|||
# AGENTS.md
|
||||
|
||||
Flutter mobile app for browsing Twitch on iOS and Android. Uses MobX for state management with code generation.
|
||||
Flutter Twitch client for iOS and Android. MobX with `build_runner`. The landing page is `web/` (own `AGENTS.md`). Flutter is pinned in `pubspec.yaml` `environment.flutter` — bump that one field; CI reads it via `flutter-version-file`.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
flutter pub get # Install dependencies
|
||||
flutter run --dart-define=CLIENT_ID=ID --dart-define=SECRET=SECRET # Run with Twitch credentials
|
||||
flutter analyze # Static analysis
|
||||
flutter test # Run tests
|
||||
dart run build_runner build # Regenerate .g.dart files (MobX/JSON models)
|
||||
flutter pub get
|
||||
flutter run --dart-define-from-file=.env # local; .env is gitignored
|
||||
flutter run --dart-define=CLIENT_ID=ID --dart-define=SECRET=SECRET
|
||||
flutter analyze
|
||||
flutter test
|
||||
flutter test test/path/to/file.dart
|
||||
dart run build_runner build # after MobX / @JsonSerializable changes
|
||||
```
|
||||
|
||||
`--delete-conflicting-outputs` was removed in build_runner 2.15 and is now ignored — conflicting outputs are handled automatically.
|
||||
`--delete-conflicting-outputs` is ignored as of build_runner 2.15. Don't add it.
|
||||
|
||||
## Source Structure
|
||||
## Layout
|
||||
|
||||
- `lib/apis/` — API services (all extend `BaseApiClient`)
|
||||
- `lib/models/` — Data models (`@JsonSerializable` with `.g.dart` codegen)
|
||||
- `lib/screens/{feature}/` — Feature screens with co-located `stores/` subdirectories
|
||||
- `lib/stores/` — Global stores only (e.g., `global_assets_store.dart`)
|
||||
- `lib/services/` — App-level services
|
||||
- `lib/widgets/` — Shared widgets
|
||||
- `lib/utils/` — Utility functions
|
||||
- `lib/apis/` — API clients extend `BaseApiClient`
|
||||
- `lib/models/` — data models; `@JsonSerializable` ones commit `.g.dart`
|
||||
- `lib/screens/{feature}/` — screens; feature stores in co-located `stores/`
|
||||
- `lib/stores/` — global stores only (`global_assets_store.dart`)
|
||||
- `test/` mirrors `lib/`; shared fixtures in `test/fixtures/`
|
||||
|
||||
## Architecture
|
||||
Don't add top-level store files or standalone API classes. Canonical MobX store: `lib/screens/settings/stores/auth_store.dart`. Extract state, reactions, and actions into stores when it keeps widgets on rendering.
|
||||
|
||||
- Feature stores live in `lib/screens/{feature}/stores/` — don't create new top-level store files (only `lib/stores/` holds global stores)
|
||||
- All API services extend `BaseApiClient` (`lib/apis/base_api_client.dart`) — don't create standalone API classes
|
||||
- MobX stores use a generated mixin pattern — see `lib/screens/settings/stores/auth_store.dart` for the canonical example
|
||||
|
||||
## Code Opinions
|
||||
|
||||
- Extract related/grouped logic (state, reactions, actions) into dedicated stores when it improves readability — keep widgets focused on rendering
|
||||
- Default to writing tests: new or changed logic (stores, API clients, parsing, utils) ships with tests; when touching existing tested code, update or extend its tests. Pure UI/rendering or config changes may skip.
|
||||
New or changed logic (stores, API clients, parsing, utils) ships with tests; extend existing tests when touching tested code. Pure UI or config may skip. HTTP: `http_mock_adapter` (`DioAdapter`) with full URLs. Otherwise `mocktail`.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- After changing MobX stores or `@JsonSerializable` models, regenerate with `dart run build_runner build`. Never edit `.g.dart` files directly. Commit `.g.dart` files to source control.
|
||||
- The secure storage cleanup in `main.dart` looks unnecessary but handles an Android/iOS edge case where secure storage persists after uninstall. Don't remove it.
|
||||
- Several deps in `pubspec.yaml` are git-pinned forks carrying compatibility patches (`extended_text_field`, `better_native_video_player`, `simple_pip_mode`). When upgrading dependencies, don't swap them back to pub.dev releases.
|
||||
- Commit regenerated `.g.dart` files. Never edit them. CI fails the PR if they're stale.
|
||||
- `main.dart` secure-storage `deleteAll()` looks redundant; it handles Android/iOS storage surviving uninstall. Don't remove it.
|
||||
- `flutter_secure_storage` stays on v9 (v10 shipped in 5.0.0 and was reverted in 5.0.1 over an Android 14 startup freeze). That also holds `package_info_plus` v9 and `device_info_plus` v12 (win32). Don't jump them in a drive-by upgrade.
|
||||
- Git-pinned forks in `pubspec.yaml` (`extended_text_field`, `better_native_video_player`, `simple_pip_mode`) carry patches. Don't swap them back to pub.dev.
|
||||
- `android/gradle.properties`: keep `android.builtInKotlin=false` and `android.newDsl=false` so plugins that still apply KGP build on AGP 9.
|
||||
- `ios/Runner/AppDelegate.swift` is customized (`CookieExtractorPlugin` + `FlutterImplicitEngineDelegate`). Flutter will not auto-migrate UIScene; don't replace the delegate with the template.
|
||||
- `android/.../MainActivity.kt` extends `PipCallbackHelperActivityWrapper` and registers `CookieExtractorPlugin` by hand. Don't revert it to `FlutterActivity`.
|
||||
- Helix OAuth (`Bearer`) and the Twitch web GQL cookie are different tokens. Native playback uses the cookie; don't send the Helix token to GQL/Usher.
|
||||
- `syncedChatDelay` is runtime-only (`includeFromJson/toJson: false`). Don't persist it with the other settings.
|
||||
- Don't remove the `ALLOW_DEBUG_SIGNED_RELEASE` branch in `android/app/build.gradle.kts`. Real releases must still fail if `key.properties` is missing.
|
||||
|
||||
## Testing
|
||||
## Releases
|
||||
|
||||
- `flutter test` runs all tests; `flutter test test/path/to/file.dart` for a single file
|
||||
- HTTP mocking: `http_mock_adapter` (`DioAdapter`) — use full URLs in `onGet`/`onPost`
|
||||
- General mocking: `mocktail` (no codegen required)
|
||||
- Test layout mirrors `lib/` (`test/apis/`, `test/models/`, `test/screens/`); shared fixtures live in `test/fixtures/` (e.g., `irc_messages.dart`, `api_responses.dart`)
|
||||
When cutting a store or GitHub release, read `docs/release.md` and follow it. That playbook is repo-local, not a global skill.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue