Skip to content

Commit f1a3456

Browse files
v0.8.10: security hardening, file sharing, Bitbucket triggers, UI performance improvements
v0.8.10: security hardening, file sharing, Bitbucket triggers, UI performance improvements
2 parents 0b232eb + d831c09 commit f1a3456

768 files changed

Lines changed: 115210 additions & 6672 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/skills/react-query-best-practices/SKILL.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ Read these before analyzing:
3535
- 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
3636
- `keepPreviousData` / `placeholderData` only on variable-key queries (where params change), never on static keys
3737
- 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.
3844

3945
### Mutations
4046
- Use `onSettled` (not `onSuccess`) for cache reconciliation — it fires on both success and error
@@ -46,7 +52,7 @@ Read these before analyzing:
4652
- Never copy query data into useState. Use query data directly in components.
4753
- Never copy query data into Zustand stores (exception: mutation callbacks that coordinate cross-store state like temp ID replacement)
4854
- 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.
5056

5157
## Steps
5258

.agents/skills/ship/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ gh pr create --base staging --title "COMMIT_MESSAGE" --body "PR_BODY"
150150

151151
## Important Notes
152152

153-
- Always confirm the commit message and PR description with the user before executing
153+
- Do not ask the user to confirm the commit message or PR description before executing
154154
- The PR should be created against `staging` branch
155155
- Keep descriptions concise and in active voice
156156
- Match the user's previous PR style: direct, no fluff, bullet points

.agents/skills/you-might-not-need-an-effect/SKILL.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,7 @@ Steps:
1616
1. Read https://react.dev/learn/you-might-not-need-an-effect to understand the guidelines
1717
2. Analyze the specified scope for useEffect anti-patterns
1818
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.

.claude/rules/sim-list-ordering.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,81 @@ Left-to-right becomes top-to-bottom. A toolbar reading `Filter · Sort · Export
2626

2727
Platform-only entries (desktop **Browser** and **Terminal**) trail the shared set rather than interleaving, so the common prefix is identical on every platform.
2828

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
60+
Open in new tab │─── Rename, Lock │─── Duplicate, Export │─── Delete
61+
62+
// ✓ Good — one rule, where the menu stops acting on the workflow
63+
Open in new tab, Rename, Lock, Duplicate, Export │─── Delete
64+
```
65+
66+
**Worked examples.** The logs row menu carries two: `Retry, Cancel Run │ Copy Run ID, Copy Link,
67+
Open Workflow, Open Snapshot │ Filter by Workflow, Clear Filters` — the run, then this log, then
68+
the page. The table row and column menus carry two: the rule before `Insert row above` /
69+
`Insert column left` is where the menu stops acting on the clicked cell and starts creating
70+
siblings. Every other row menu in the app has only the destructive transition, so it carries one.
71+
72+
**The one standing exception: menus that emulate a native menu.** The text-editor menu
73+
(`editor-context-menu.tsx`), the terminal menu (`terminal-context-menu.tsx`), and the browser
74+
page menu (`browser-session.tsx`) each mirror the OS menu the user already knows — clipboard
75+
banding (`Cut · Copy · Paste │ Select all`) is a convention every text field on their machine
76+
teaches them. These keep their native banding, and that is the *same* principle as the ordering
77+
rule above: mirror the surface the user already reads. The test is whether a real menu outside
78+
Sim taught them the grouping. Our own resource, row, and action menus have no such precedent —
79+
the toolbars they mirror are flat — so they take the single rule.
80+
81+
**Both sides of every rule must be guaranteed non-empty.** Write the separator's guard out of
82+
the *exact* render conditions of the items around it, never a looser approximation:
83+
84+
```tsx
85+
// ✗ Bad — `showLeave` alone, while the Leave item needs `showLeave && onLeave`.
86+
// A caller passing showLeave from a permission check with a conditional
87+
// onLeave renders a trailing rule under the last item.
88+
{hasActionsAbove && (showLeave || showDelete) && <DropdownMenuSeparator />}
89+
90+
// ✓ Good — each term is the item's own condition, verbatim
91+
const hasDestructiveSection = (showLeave && onLeave) || showDelete
92+
{hasActionsAboveDestructive && hasDestructiveSection && <DropdownMenuSeparator />}
93+
```
94+
95+
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+
29104
## Encode the order once
30105

31106
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.

CLAUDE.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,9 @@ Co-locate a `search-params.ts` per feature exporting the parser map (single sour
386386

387387
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.
388388

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`.
390392

391393
## Styling
392394

apps/desktop/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"type": "module",
1010
"main": "dist/main.cjs",
1111
"engines": {
12-
"bun": ">=1.2.13",
12+
"bun": ">=1.3.14",
1313
"node": ">=20.0.0"
1414
},
1515
"scripts": {

apps/docs/content/docs/en/cli/commands.mdx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,29 @@ sim configure [options]
113113
| `--unset <key...>` | No | Remove settings (endpoint, workspace, output). |
114114

115115
</CommandTable>
116+
117+
## Ask Sim and print the reply
118+
119+
```bash
120+
sim chat <message> [options]
121+
```
122+
123+
**Arguments**
124+
125+
<CommandTable>
126+
127+
| Argument | Required | Description |
128+
| --- | --- | --- |
129+
| `message` | Yes | What to ask Sim |
130+
131+
</CommandTable>
132+
133+
**Options**
134+
135+
<CommandTable>
136+
137+
| Option | Required | Description |
138+
| --- | --- | --- |
139+
| `-c, --conversation <id>` | No | Continue the conversation with this ID. |
140+
141+
</CommandTable>

apps/docs/content/docs/en/cli/knowledge.mdx

Lines changed: 49 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ sim knowledge create [options]
216216
## Create knowledge connector
217217

218218
```bash
219-
sim knowledge connectors create <id> [options]
219+
sim knowledge connectors create <knowledgeBaseId> [options]
220220
```
221221

222222
**Arguments**
@@ -225,7 +225,7 @@ sim knowledge connectors create <id> [options]
225225

226226
| Argument | Required | Description |
227227
| --- | --- | --- |
228-
| `id` | Yes | Unique knowledge base identifier. |
228+
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
229229

230230
</CommandTable>
231231

@@ -246,7 +246,7 @@ sim knowledge connectors create <id> [options]
246246
## Delete knowledge connector
247247

248248
```bash
249-
sim knowledge connectors delete <id> <connectorId> [options]
249+
sim knowledge connectors delete <knowledgeBaseId> <connectorId> [options]
250250
```
251251

252252
**Arguments**
@@ -255,7 +255,7 @@ sim knowledge connectors delete <id> <connectorId> [options]
255255

256256
| Argument | Required | Description |
257257
| --- | --- | --- |
258-
| `id` | Yes | Knowledge base that owns the connector. |
258+
| `knowledgeBaseId` | Yes | Knowledge base that owns the connector. |
259259
| `connectorId` | Yes | Connector selected for the operation. |
260260

261261
</CommandTable>
@@ -275,7 +275,7 @@ sim knowledge connectors delete <id> <connectorId> [options]
275275
## Get knowledge connector
276276

277277
```bash
278-
sim knowledge connectors get <id> <connectorId>
278+
sim knowledge connectors get <knowledgeBaseId> <connectorId>
279279
```
280280

281281
**Arguments**
@@ -284,15 +284,15 @@ sim knowledge connectors get <id> <connectorId>
284284

285285
| Argument | Required | Description |
286286
| --- | --- | --- |
287-
| `id` | Yes | Knowledge base that owns the connector. |
287+
| `knowledgeBaseId` | Yes | Knowledge base that owns the connector. |
288288
| `connectorId` | Yes | Connector selected for the operation. |
289289

290290
</CommandTable>
291291

292292
## List knowledge connector documents
293293

294294
```bash
295-
sim knowledge connectors documents list <id> <connectorId> [options]
295+
sim knowledge connectors documents list <knowledgeBaseId> <connectorId> [options]
296296
```
297297

298298
**Arguments**
@@ -301,7 +301,7 @@ sim knowledge connectors documents list <id> <connectorId> [options]
301301

302302
| Argument | Required | Description |
303303
| --- | --- | --- |
304-
| `id` | Yes | Knowledge base that owns the connector. |
304+
| `knowledgeBaseId` | Yes | Knowledge base that owns the connector. |
305305
| `connectorId` | Yes | Connector selected for the operation. |
306306

307307
</CommandTable>
@@ -318,10 +318,38 @@ sim knowledge connectors documents list <id> <connectorId> [options]
318318

319319
</CommandTable>
320320

321+
## Update knowledge connector documents
322+
323+
```bash
324+
sim knowledge connectors documents update <knowledgeBaseId> <connectorId> [options]
325+
```
326+
327+
**Arguments**
328+
329+
<CommandTable>
330+
331+
| Argument | Required | Description |
332+
| --- | --- | --- |
333+
| `knowledgeBaseId` | Yes | Knowledge base that owns the connector. |
334+
| `connectorId` | Yes | Connector selected for the operation. |
335+
336+
</CommandTable>
337+
338+
**Options**
339+
340+
<CommandTable>
341+
342+
| Option | Required | Description |
343+
| --- | --- | --- |
344+
| `--operation <value>` | Yes | Whether to restore or exclude the selected documents. Accepted values: `restore`, `exclude`. |
345+
| `--document <value...>` | Yes | Connector document identifiers to update. (space-separated, or @path / @- with one value per line). |
346+
347+
</CommandTable>
348+
321349
## List knowledge connectors
322350

323351
```bash
324-
sim knowledge connectors list <id> [options]
352+
sim knowledge connectors list <knowledgeBaseId> [options]
325353
```
326354

327355
**Arguments**
@@ -330,7 +358,7 @@ sim knowledge connectors list <id> [options]
330358

331359
| Argument | Required | Description |
332360
| --- | --- | --- |
333-
| `id` | Yes | Unique knowledge base identifier. |
361+
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
334362

335363
</CommandTable>
336364

@@ -346,10 +374,10 @@ sim knowledge connectors list <id> [options]
346374

347375
</CommandTable>
348376

349-
## Update knowledge connector
377+
## Queue a knowledge connector synchronization
350378

351379
```bash
352-
sim knowledge connectors update <id> <connectorId> [options]
380+
sim knowledge connectors sync <knowledgeBaseId> <connectorId> [options]
353381
```
354382

355383
**Arguments**
@@ -358,7 +386,7 @@ sim knowledge connectors update <id> <connectorId> [options]
358386

359387
| Argument | Required | Description |
360388
| --- | --- | --- |
361-
| `id` | Yes | Knowledge base that owns the connector. |
389+
| `knowledgeBaseId` | Yes | Knowledge base that owns the connector. |
362390
| `connectorId` | Yes | Connector selected for the operation. |
363391

364392
</CommandTable>
@@ -369,16 +397,15 @@ sim knowledge connectors update <id> <connectorId> [options]
369397

370398
| Option | Required | Description |
371399
| --- | --- | --- |
372-
| `--source-config <json\|@file>` | No | Replacement source selection and filtering configuration. (JSON, or @path / @- to read a file or stdin). |
373-
| `--sync-interval-minutes <value>` | No | New scheduled synchronization interval in minutes. |
374-
| `--status <value>` | No | New connector state. Accepted values: `active`, `paused`. |
400+
| `--rehydrate` | No | Re-fetch and re-index every existing connector document. |
401+
| `--no-rehydrate` | No | Send --rehydrate as false. |
375402

376403
</CommandTable>
377404

378-
## Update knowledge connector documents
405+
## Update knowledge connector
379406

380407
```bash
381-
sim knowledge connectors documents update <id> <connectorId> [options]
408+
sim knowledge connectors update <knowledgeBaseId> <connectorId> [options]
382409
```
383410

384411
**Arguments**
@@ -387,7 +414,7 @@ sim knowledge connectors documents update <id> <connectorId> [options]
387414

388415
| Argument | Required | Description |
389416
| --- | --- | --- |
390-
| `id` | Yes | Knowledge base that owns the connector. |
417+
| `knowledgeBaseId` | Yes | Knowledge base that owns the connector. |
391418
| `connectorId` | Yes | Connector selected for the operation. |
392419

393420
</CommandTable>
@@ -398,8 +425,9 @@ sim knowledge connectors documents update <id> <connectorId> [options]
398425

399426
| Option | Required | Description |
400427
| --- | --- | --- |
401-
| `--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`. |
403431

404432
</CommandTable>
405433

@@ -588,34 +616,6 @@ sim knowledge search [options]
588616

589617
</CommandTable>
590618

591-
## Sync knowledge connector
592-
593-
```bash
594-
sim knowledge sync create <id> <connectorId> [options]
595-
```
596-
597-
**Arguments**
598-
599-
<CommandTable>
600-
601-
| Argument | Required | Description |
602-
| --- | --- | --- |
603-
| `id` | Yes | Knowledge base that owns the connector. |
604-
| `connectorId` | Yes | Connector selected for the operation. |
605-
606-
</CommandTable>
607-
608-
**Options**
609-
610-
<CommandTable>
611-
612-
| Option | Required | Description |
613-
| --- | --- | --- |
614-
| `--rehydrate` | No | Re-fetch and re-index every existing connector document. |
615-
| `--no-rehydrate` | No | Send --rehydrate as false. |
616-
617-
</CommandTable>
618-
619619
## Update knowledge base
620620

621621
```bash

0 commit comments

Comments
 (0)