Imported from CodeStorm-Hub/petfolio (
AGENTS.md). Install upstream withnpx skills add CodeStorm-Hub/petfolio. Copyright stays with the author.
Role & Architecture Rules
You are an expert Flutter and Supabase developer. For the PetFolio project, you must strictly adhere to the following rules:
- Feature-First Architecture: All code must live within
lib/features/<feature_name>/and be cleanly divided into presentation, domain, and data layers. - State Management: Use Riverpod (
flutter_riverpod,riverpod_annotation, generated notifiers) for all state management and dependency injection. Do not introduce theproviderpackage for new code. - Supabase Performance:
- Avoid client-side data joining (N+1 queries). Push complex relational logic and aggregations to Postgres Views or RPCs.
- When writing Row Level Security (RLS) policies, always wrap authentication checks in a subselect, such as
(select auth.uid()), to force the Postgres optimizer to cache the result and prevent severe performance degradation. - Never generate queries that could result in full table scans; always utilize appropriate indexing.
Learned User Preferences
- When applying Supabase schema to the hosted project, prefer the Supabase MCP migration path when available; if using the Supabase CLI, prefix commands with
npx(for examplenpx supabase db push). - After completing a distinct care, marketplace, backend, or PWA/web phase, keep
progress.mdupdated and use/rememberto persist high-signal context before starting the next phase. - Web/PWA work follows phased rollout in
PWA_WEB_AUDIT.md; do not change Android APK behavior—gate web-only paths withkIsWebandlib/core/platform/. - Avoid importing
router.dartfrom screens thatrouter.dartalready imports; use literal paths or query strings for deep links to prevent circular imports. - For optimistic UI and one-off actions (care task toggles, Stripe seller onboarding), surface failures with
AppSnackBar.showError; do not set long-lived providers (e.g.myShopProvider) toAsyncValue.errorfor transient failures. - When a subagent result is already visible in the UI, avoid re-summarizing it unless multi-task synthesis is needed; a short third-person completion note is enough, and avoid repeating the same confirmation every turn.
- When asked to save audits, reviews, or comparable findings, write them as Markdown under the repository root unless a different path is specified.
- For hosted FCM setup, use
tool/set_fcm_supabase_secrets.ps1andfirebase-instructions.md;FIREBASE_SERVICE_ACCOUNT_JSONin Supabase must be minified valid JSON andFCM_DISPATCH_SECRETmust matchprivate.fcm_internal_config.
Learned Workspace Facts
- Care routes: shell
/care, full-screen/care/nutritionand/care/medical-vault; successful onboarding navigates to/care?onboardingComplete=1, shows a one-shot success snackbar, then normalizes the URL to/care. careDashboardProviderandhealthVaultControllerProviderare non-family providers that watchactivePetIdProvider; a null active pet yields empty tasks or an empty medical list and skips remote loads.- Daily streak completion is driven by the
check_daily_completionRPC (target_pet_id, optionalcompletion_datematchingcare_logs.logged_date) againstcare_tasksandcare_logs, with streak state incare_streaksand badges inpet_badges; the dashboard also listens to Supabase realtime oncare_streaksviacareStreakRealtimeProviderfor immediate streak UI sync. - App-wide snackbars for notifier-triggered errors use
appSnackBarMessengerKeyonMaterialApp.routerandAppSnackBar.showErrorfromlib/core/widgets/app_snack_bar.dart. analysis_options.yamlexcludes only*.g.dartfrom the analyzer (not*.freezed.dart; Freezedpartfiles must be analyzed).- Canonical pet model:
lib/features/pet_profile/data/models/pet.dart—ActivityLevel,PetGender(gender),isPublic,isDiscoverable(is_discoverable, default false); sectionedEditProfileScreensaves viaeditPetProfile/EditProfileController; discoverable toggle uses optimisticPetListNotifier.setDiscoverable; match GPS sync viapetMatchLocationProvider. - Marionette runs only in debug builds via conditional imports
marionette_debug_gate_stub.dart/marionette_debug_gate_io.dartsomain.dartavoidsdart:ioon web targets. - Social screen header Messages navigates to
/matching. - PostGIS matching:
/matching/inbox,/matching/chat/:threadId;swipes/matchesandmatching_discovery_candidatesRPC (MatchingRepository);chat_threads.mutual_match_id+ensure_chat_thread_for_match(legacyparticipant_*/match_request_idpossible). RPC needsis_discoverable IS TRUEand non-nullpets.location;petHasLocationuses.not('location', 'is', null).mutualMatchInsertStreamProvider+MatchCelebrationOverlay;matchPreferenceControllerProvider+discoveryCandidatesControllerProvider(replenish when stack drops below 5, ~450ms debouncedinvalidateSelf()— do notref.watchprefs inbuild()on slider drags). Location:location_service.dart; denied/services-off empty state onMatchingScreen. Riverpod 3: generated notifiers omit type params (extends _$Foo); useAsyncValue.value, not.valueOrNull. - Multi-vendor marketplace (
docs/claude-handoff.md): cartitemsByShop+ per-shopstartCheckoutForShop; Discover Shops viashopListProvider→/shop/:id; seller routes/seller,/seller/setup,/seller/onboarding, products/orders.ShopRepository.startOnboardingcalls Edge Functionstripe-onboard-vendorwithfunctions.invoke(..., body: {'shopId'})(not.rpc()), readsaccountLinkUrl; platform Stripe account needs Connect enabled. - FCM push:
FcmService+user_fcm_devices; Edgesend-fcm-notification/_shared/fcm_send.ts; DB triggers onchat_messages,notifications,matches,marketplace_orders; outboxfcm_push_outbox+process-fcm-outbox; carecare_web_reminders+process-care-fcm-reminders. Tray UI:petfolio_pushchannel,fcm_push_display.dart, tap →FcmMessageRouter. Setup:firebase-instructions.md,tool/set_fcm_supabase_secrets.ps1. - PWA/web (
PWA_WEB_AUDIT.md, Vercel deploy): Phases 1–2 done—web/index.htmlshell fixes;lib/core/platform/(PlatformNotificationsIO local vs webcare_web_reminders,useStripeHostedCheckout+ hostedcreate-payment-intentsession on web,pickGalleryImage, web FCM viaFIREBASE_VAPID_KEY+FcmService.syncToken/firebase-messaging-sw.js). Matching on web uses pet profile location (petMatchLocationProvider), not device GPS.