Hotfix Rule: Force Fresh Data After CRUD Mutation
Task-h not implements
This commit is contained in:
30
AGENTS.md
30
AGENTS.md
@@ -375,6 +375,31 @@ Preferred pattern for new pages:
|
||||
3. hydrate with `HydrationBoundary`
|
||||
4. read with `useSuspenseQuery()`
|
||||
|
||||
Required pattern for CRUD mutations:
|
||||
|
||||
1. every feature must define centralized query key factories in `queries.ts`
|
||||
2. use grouped keys such as `all`, `lists()`, `list(filters)`, `details()`, `detail(id)`, plus child-resource keys like `contacts(id)` or `followups(id)` when needed
|
||||
3. after create, explicitly invalidate the list-level key
|
||||
4. after update, explicitly invalidate both list and detail keys
|
||||
5. after delete, explicitly invalidate the list key and remove stale detail queries with `removeQueries`
|
||||
6. invalidate related queries affected by the mutation, such as counts, child tabs, document previews, approval panels, and cross-feature related lists
|
||||
7. do not rely on `staleTime` alone to refresh production CRUD data
|
||||
8. do not rely on `router.refresh()` alone for CRUD freshness; React Query invalidation is required first, and `router.refresh()` is optional only as a supplement
|
||||
|
||||
Mutation callback safety rule:
|
||||
|
||||
- if a shared mutation object from `api/mutations.ts` is spread into `useMutation({ ...sharedMutation, ... })`, do not override `onSuccess` or `onSettled` in a way that drops cache invalidation
|
||||
- prefer keeping cache invalidation inside the shared mutation definition
|
||||
- if component-level success behavior is needed, either:
|
||||
- put invalidation in shared `onSettled` and keep UI concerns like toast and closing dialogs in component `onSuccess`, or
|
||||
- call the shared invalidate helper explicitly from the component before closing the sheet/dialog
|
||||
|
||||
UI completion rule after successful mutation:
|
||||
|
||||
- close sheet/dialog only after the mutation promise resolves successfully
|
||||
- table/detail views must show fresh data immediately without a full browser refresh
|
||||
- related tabs and counts must refresh in the same interaction when their backing data changed
|
||||
|
||||
### URL State
|
||||
|
||||
Use `nuqs` for table search params and list filters.
|
||||
@@ -486,3 +511,8 @@ Ensure these are set:
|
||||
12. Treat legacy mock-backed modules as migration seams.
|
||||
13. Follow the migrated `products` and `users` feature patterns when building new CRUD modules.
|
||||
14. Do not re-enable self-service sign-up unless the product requirement changes explicitly.
|
||||
15. For every CRUD mutation, explicitly invalidate React Query caches for list/detail/related data; never rely on passive staleness recovery.
|
||||
16. Centralize query keys in each feature's `api/queries.ts`; do not scatter manual string query keys in components.
|
||||
17. When deleting entities, remove stale detail queries with `removeQueries` in addition to invalidating lists.
|
||||
18. If a component overrides `useMutation` callbacks on top of a shared mutation config, preserve or explicitly call the shared invalidation behavior before closing UI.
|
||||
19. After successful create/update/delete, sheets, dialogs, and destructive modals must close only after cache invalidation has been triggered and the UI can refresh from fresh data.
|
||||
|
||||
Reference in New Issue
Block a user