You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: .agents/skills/react-query-best-practices/SKILL.md
+7-1Lines changed: 7 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -35,6 +35,12 @@ Read these before analyzing:
35
35
- Every query must have an explicit `staleTime` (default 0 is almost never correct), assigned from a named exported constant — never an inline numeric literal. A server-side prefetch hydrating the same query key must import and reuse that constant instead of restating the number
36
36
-`keepPreviousData` / `placeholderData` only on variable-key queries (where params change), never on static keys
37
37
- Use `enabled` to prevent queries from running without required params
38
+
- Warm data for hover/focus intent with `queryClient.prefetchQuery` and shared `queryOptions`; never temporarily enable a mounted hidden observer, which can remain active after focus restoration and refetch data for closed UI
39
+
- When gating a query by view or modal state, move every consumer to the active query too: imperative refresh/pagination, loading and error feedback, and data-derived controls must never read a disabled query or placeholder data from a previous key
40
+
- Compose caller-controlled `enabled` options with required-param guards (`Boolean(id) && (options?.enabled ?? true)`). Never spread options after an internal guard, because `{ enabled: true }` can silently re-enable an invalid request.
41
+
- A disabled query can still report `isPending: true`. Aggregate loading state only for queries that are applicable/enabled, or an optional query can hold the whole surface in a permanent loading state.
42
+
- Deferred authorization or policy queries must fail closed. Do not give pending/error data the same fallback as a successfully loaded unrestricted policy; disable guarded actions until the policy query succeeds.
43
+
- Server prefetches must call the authorized use case, apply the route presenter/response schema, and reuse the client's exact key, mapper, and stale time. Keep all fallible auth/read/parse work inside `queryFn` so an optional warm cannot fail the page, and never bypass a route that redacts fields.
38
44
39
45
### Mutations
40
46
- Use `onSettled` (not `onSuccess`) for cache reconciliation — it fires on both success and error
@@ -46,7 +52,7 @@ Read these before analyzing:
46
52
- Never copy query data into useState. Use query data directly in components.
47
53
- Never copy query data into Zustand stores (exception: mutation callbacks that coordinate cross-store state like temp ID replacement)
48
54
- The query cache is not a local state manager — `setQueryData` is for optimistic updates only
49
-
- Forms are the one deliberate exception: copy server data into local form state with `staleTime: Infinity`
55
+
- Forms are the one deliberate exception: once query data exists, initialize a keyed form subtree from it with lazy state initializers. Do not synchronize query data into draft state with an Effect; key the form by resource identity so switching resources resets every draft/modal/upload field together. Keep independent queries in the outer wrapper so they still start in parallel.
Copy file name to clipboardExpand all lines: .agents/skills/you-might-not-need-an-effect/SKILL.md
+4Lines changed: 4 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -16,3 +16,7 @@ Steps:
16
16
1. Read https://react.dev/learn/you-might-not-need-an-effect to understand the guidelines
17
17
2. Analyze the specified scope for useEffect anti-patterns
18
18
3. If fix=true, apply the fixes. If fix=false, propose the fixes without applying.
19
+
20
+
## Query-backed forms
21
+
22
+
When query data supplies the initial values for an editable form, do not copy it into draft state in an Effect. Render loading chrome in an outer component, then mount a keyed form child once data exists and initialize its state lazily from props. Key by the resource identity so every related draft, dialog, and upload state resets together when the resource changes. Keep independent queries in the outer component to preserve parallel fetching.
Platform-only entries (desktop **Browser** and **Terminal**) trail the shared set rather than interleaving, so the common prefix is identical on every platform.
28
28
29
+
## Grouping: a rule marks a change in what the action acts on
30
+
31
+
Order is governed above. **Separators are governed here.**
32
+
33
+
A `DropdownMenuSeparator` earns its place when the next group stops acting on the thing the user
34
+
clicked. That is the whole test — one question, asked the same way in every menu:
35
+
36
+
| The group | Gets a rule before it |
37
+
| --- | --- |
38
+
| Acts on the clicked item (open, rename, duplicate, export, copy, edit, pin, run) | no — this is the body of the menu |
39
+
| Acts on **something else** — the page's filters or view, or a newly created sibling | yes |
40
+
|**Destroys or detaches** it (delete, leave, close, hide, remove) | yes |
41
+
42
+
Most row menus only ever have the one transition, so they carry one rule, immediately before
43
+
`Delete`. A menu that also filters the page or inserts siblings carries two. Nothing carries
44
+
more, because there is no third thing a menu acts on.
45
+
46
+
Do **not** band by verb. "Navigation", "status", "edit", "copy" are categories of *what the verb
47
+
is*, not of *what it touches*, and the user meets no such taxonomy anywhere else — every toolbar
48
+
in the app is a flat `gap-1` chip row with no dividers. Menus banded that way put the same action
49
+
in different groups depending on which siblings happened to be visible.
50
+
51
+
The consequential group trails in almost every menu. It leads in exactly one: the **logs row
52
+
menu**, where `Retry` and `Cancel Run` act on the run itself and are the primary actions on a
53
+
failure, so they sit on top with the rule beneath them. Ordering follows the surface (see "The
54
+
rule" above); the separator fences whichever end that group occupies.
55
+
56
+
A group whose items are merely *disabled* still gets no extra rule — `disabled` is not a group.
57
+
58
+
```tsx
59
+
// ✗ Bad — four semantic bands the user meets nowhere else
This is the failure that put a dangling rule at the bottom of the logs row menu, where two
96
+
unconditional separators sat above conditional items.
97
+
98
+
**Do not add a prop to move a rule.** The shared workflow context menu grew
99
+
`groupNonDestructiveActions` and `separateNavigationAction` for this; between them they moved one
100
+
separator for one caller, four of six branches were unreachable, and `separateNavigationAction`
101
+
had no observable effect anywhere in the repo. Both are gone. A menu that wants different
102
+
grouping wants the standard grouping.
103
+
29
104
## Encode the order once
30
105
31
106
An order duplicated across surfaces is an order that will drift. Export **one** constant and sort by it — do not hand-maintain a matching literal per menu.
Copy file name to clipboardExpand all lines: CLAUDE.md
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -386,7 +386,9 @@ Co-locate a `search-params.ts` per feature exporting the parser map (single sour
386
386
387
387
A list orders itself the way the user already reads the same things somewhere else. Resource menus (`+` attach, `@` mention, resource-tab `+`) mirror the **sidebar** top-down; a row or root **context menu** mirrors that surface's **toolbar**, left-to-right becoming top-to-bottom; tab strips mirror their nav. Platform-only entries (desktop Browser, Terminal) trail the shared set.
388
388
389
-
Encode the order in ONE exported constant and sort by it — never a hand-maintained literal per menu (`RESOURCE_MENU_ORDER` / `byResourceMenuOrder` in `home/components/mothership-view/components/resource-registry`). Render mixed item kinds in a single ordered pass; emitting all submenu-backed families and then all flat ones silently pins every submenu to the top no matter what the constant says. Divergence is allowed only for search ranking, user-controlled ordering, and recency. Full rule in `.claude/rules/sim-list-ordering.md`.
389
+
Encode the order in ONE exported constant and sort by it — never a hand-maintained literal per menu (`RESOURCE_MENU_ORDER` / `byResourceMenuOrder` in `home/components/mothership-view/components/resource-registry`). Render mixed item kinds in a single ordered pass; emitting all submenu-backed families and then all flat ones silently pins every submenu to the top no matter what the constant says. Divergence is allowed only for search ranking, user-controlled ordering, and recency.
390
+
391
+
**Grouping**: a `DropdownMenuSeparator` marks a change in WHAT the action acts on — the clicked item (no rule), something else like the page's filters or a new sibling (rule), or destroying it (rule). Most row menus have only the destructive transition and carry one rule before Delete/Leave/Close/Hide; menus that also filter the page or insert siblings carry two. Never band by verb (navigation/status/edit/copy) — the toolbars are flat, so that taxonomy exists nowhere else. No toolbar in the app renders a divider, so multi-band menus teach a taxonomy that exists on no other surface. Build each separator's guard from the EXACT render conditions of the items on both sides — a looser guard is what leaves a dangling rule when its group is conditional. Never add a prop to move a rule. Full rule in `.claude/rules/sim-list-ordering.md`.
|`--operation <value>`| Yes | Whether to restore or exclude the selected documents. Accepted values: `restore`, `exclude`. |
402
-
|`--document <value...>`| Yes | Connector document identifiers to update. (space-separated, or @path / @- with one value per line). |
428
+
|`--source-config <json\|@file>`| No | Replacement source selection and filtering configuration. Updating a runnable connector queues synchronization; paused connectors remain paused. (JSON, or @path / @- to read a file or stdin). |
429
+
|`--sync-interval-minutes <value>`| No | New scheduled synchronization interval in minutes. |
430
+
|`--status <value>`| No | New connector state. Accepted values: `active`, `paused`. |
0 commit comments