Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
bfcfb9e
docs(library): update best-ai-automation-tools-2026 (#8465)
icecrasher321 Sep 30, 2026
ee258b6
docs(library): update best-gumloop-alternatives-in-2026 (#8466)
icecrasher321 Sep 30, 2026
7e17356
feat(library): Best AI Agent Builders for Slack and CRM Automation in…
icecrasher321 Sep 30, 2026
e219a4b
feat(library): Marketing Automation Platform vs AI Agent Builder: Whi…
icecrasher321 Sep 30, 2026
e0c90b3
fix(tests): keep the preview turn-budget test inside its timeout unde…
waleedlatif1 Sep 30, 2026
c873ed2
fix(sim-cli): report an embedded SimApiError with its own exit code (…
waleedlatif1 Sep 30, 2026
e09970a
fix(sandbox): withhold workbench certification after an unprovenanced…
waleedlatif1 Sep 30, 2026
cebe8a3
fix(mothership): settle chat runs no controller owns (#8457)
waleedlatif1 Sep 30, 2026
294c505
fix(search): bound Search retirement pages so the migration finishes …
waleedlatif1 Sep 30, 2026
c30d58d
fix(logs): record a run's cost before it reads finished, and hold syn…
waleedlatif1 Sep 30, 2026
e816f01
fix(mothership): keep Chat stream legs alive without a wall clock (#8…
waleedlatif1 Sep 30, 2026
9703b07
fix(mothership): explain withheld code and workflow results and bound…
waleedlatif1 Sep 30, 2026
b8a0044
fix(auth): use neutral links for email verification (#8476)
waleedlatif1 Sep 30, 2026
df47953
feat(search): add Lucidchart and Lucidspark live search (#8475)
waleedlatif1 Sep 30, 2026
9ed10e1
fix(mothership): re-sync Chat reconnects from the worker log and trim…
waleedlatif1 Sep 30, 2026
0f218b6
fix(billing): enforce the plan usage limit mid-run and bill runs that…
waleedlatif1 Sep 30, 2026
594894c
fix(chat): keep empty search activity collapsed (#8477)
waleedlatif1 Sep 30, 2026
be50bc6
feat(dashboards): Sim-built workspace dashboard behind a rollout flag…
TheodoreSpeaks Sep 30, 2026
e72626d
fix(desktop): return source connections to the app (#8486)
waleedlatif1 Sep 30, 2026
8c55350
fix(desktop): preserve browser sign-in recovery guidance (#8487)
waleedlatif1 Sep 30, 2026
41adb36
feat(search): add Zoom and Google Meet providers (#8483)
waleedlatif1 Sep 30, 2026
9ae8ba8
fix(sandbox): preserve workbench output provenance (#8485)
icecrasher321 Sep 30, 2026
a1ee856
feat(search): add Devin to Sim Search MCP clients (#8489)
waleedlatif1 Sep 30, 2026
b84828d
fix(async-jobs): retain accepted run IDs for immediate lookup (#8490)
icecrasher321 Oct 1, 2026
f89b168
fix(billing): keep billing a request whose period start moved forward…
waleedlatif1 Oct 1, 2026
fb33da1
fix(mothership): close abandoned tool meters once instead of alarming…
waleedlatif1 Oct 1, 2026
dd54d31
fix(search): gate Zoom rollout and correct Lucid tiles (#8491)
waleedlatif1 Oct 1, 2026
088955f
fix(mothership): answer a retried task wake whose turn already ran (#…
waleedlatif1 Oct 1, 2026
2178d6e
fix(mothership): explain a Chat turn the worker ends without a reason…
waleedlatif1 Oct 1, 2026
21b2972
fix(mothership): report a browser-claimed workflow tool from its sett…
waleedlatif1 Oct 1, 2026
f363541
feat(analytics): add Freebuff Ads conversion tracking (#8492)
waleedlatif1 Oct 1, 2026
517a5f3
fix(integrations): complete account connections in place (#8493)
waleedlatif1 Oct 1, 2026
55d877b
fix(mothership): never sweep a Chat run while one of its Sim tools is…
waleedlatif1 Oct 1, 2026
51f793b
fix(integrations): close connection recovery edge cases (#8497)
waleedlatif1 Oct 1, 2026
7e8d3ff
fix(dashboards): carry dashboard chat context ids, label the chart re…
waleedlatif1 Oct 1, 2026
2091953
fix(billing): build the mid-run usage card from the admitted payer an…
waleedlatif1 Oct 1, 2026
96fd30d
fix(mothership): number recovered turns past an unreadable ring and f…
waleedlatif1 Oct 1, 2026
e1e8689
fix(search): recheck Zoom approval and bound MCP serialization (#8496)
waleedlatif1 Oct 1, 2026
bd46dfb
fix(dashboards): menu order, org-chat entitlement, mention ids, contr…
TheodoreSpeaks Oct 1, 2026
fa32bc1
fix(desktop): install browser before release smoke tests (#8504)
waleedlatif1 Oct 1, 2026
a0b859b
fix(sandbox): redact temporary session credentials in model output (#…
icecrasher321 Oct 1, 2026
c57c905
fix(billing): refuse charges into a period the terminal settlement al…
waleedlatif1 Oct 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
13 changes: 7 additions & 6 deletions .claude/rules/sim-list-ordering.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
description: List and menu ordering that mirrors the sidebar or toolbar, with one separator before the destructive action
description: List and menu ordering that mirrors the toolbar or settings nav, encoded once, with one separator before the destructive action
paths:
- "apps/sim/app/**/*.tsx"
- "apps/sim/ee/**/*.tsx"
Expand All @@ -8,7 +8,7 @@ paths:

# List & Menu Ordering

**A list orders itself the way the user already reads the same things somewhere else.** Dropdowns, context menus, tab strips, command palettes, and settings navs are all *second* presentations of a set the user has already seen — in the sidebar, in a toolbar, in a column-header row. When the second presentation reorders that set, the user re-reads it from scratch every time.
**A list orders itself the way the user already reads the same things somewhere else.** Dropdowns, context menus, tab strips, command palettes, and settings navs are all *second* presentations of a set the user has already seen — in a toolbar, in the settings nav, in a column-header row. When the second presentation reorders that set, the user re-reads it from scratch every time.

This is not a style preference. Order is the cheapest affordance a list has, and the only one that costs nothing to get right.

Expand All @@ -18,13 +18,14 @@ Before writing a list of items, find where the user sees those same items *first

| The list | Mirrors |
| --- | --- |
| Resource menus (`+` attach, `@` mention, resource-tab `+`) | the workspace **sidebar**, top-down |
| A row / root **context menu** | that surface's **toolbar**, left-to-right → top-to-bottom |
| Settings tab strip, recently-deleted tabs | the **settings nav**, top-down |
| A "New …" menu | the order those things appear once created |

Left-to-right becomes top-to-bottom. A toolbar reading `Filter · Sort · Export · Delete` becomes a menu reading Filter, Sort, Export, Delete — never alphabetized, never grouped by implementation, never "destructive last" unless the toolbar already puts it last.

Resource menus (`+` attach, `@` mention, resource-tab `+`) do not mirror the sidebar. Their order is a product decision encoded in `RESOURCE_MENU_ORDER` (see below), and every resource menu shares it.

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

## Grouping: a rule marks a change in what the action acts on
Expand Down Expand Up @@ -107,10 +108,10 @@ grouping wants the standard grouping.
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.

```ts
/** Top-down order for every menu listing resource families, mirroring the sidebar. */
/** Top-down order for every menu listing resource families. */
export const RESOURCE_MENU_ORDER: readonly MothershipResourceType[] = [
'integration', 'task', 'table', 'file', 'filefolder',
'knowledgebase', 'log', 'workflow', 'folder', 'browser', 'terminal', 'generic',
'integration', 'task', 'dashboard', 'table', 'file', 'filefolder',
'knowledgebase', 'workflow', 'log', 'folder', 'browser', 'terminal', 'generic',
]

export function byResourceMenuOrder<T extends { type: MothershipResourceType }>(a: T, b: T) {
Expand Down
13 changes: 7 additions & 6 deletions .cursor/rules/sim-list-ordering.mdc
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
---
description: "List and menu ordering that mirrors the sidebar or toolbar, with one separator before the destructive action"
description: "List and menu ordering that mirrors the toolbar or settings nav, encoded once, with one separator before the destructive action"
globs: ["apps/sim/app/**/*.tsx","apps/sim/ee/**/*.tsx","apps/sim/components/**/*.tsx"]
---

<!-- Generated from .claude/rules/sim-list-ordering.md by `bun run skills:sync`. Edit the source, not this file. -->

# List & Menu Ordering

**A list orders itself the way the user already reads the same things somewhere else.** Dropdowns, context menus, tab strips, command palettes, and settings navs are all *second* presentations of a set the user has already seen — in the sidebar, in a toolbar, in a column-header row. When the second presentation reorders that set, the user re-reads it from scratch every time.
**A list orders itself the way the user already reads the same things somewhere else.** Dropdowns, context menus, tab strips, command palettes, and settings navs are all *second* presentations of a set the user has already seen — in a toolbar, in the settings nav, in a column-header row. When the second presentation reorders that set, the user re-reads it from scratch every time.

This is not a style preference. Order is the cheapest affordance a list has, and the only one that costs nothing to get right.

Expand All @@ -17,13 +17,14 @@ Before writing a list of items, find where the user sees those same items *first

| The list | Mirrors |
| --- | --- |
| Resource menus (`+` attach, `@` mention, resource-tab `+`) | the workspace **sidebar**, top-down |
| A row / root **context menu** | that surface's **toolbar**, left-to-right → top-to-bottom |
| Settings tab strip, recently-deleted tabs | the **settings nav**, top-down |
| A "New …" menu | the order those things appear once created |

Left-to-right becomes top-to-bottom. A toolbar reading `Filter · Sort · Export · Delete` becomes a menu reading Filter, Sort, Export, Delete — never alphabetized, never grouped by implementation, never "destructive last" unless the toolbar already puts it last.

Resource menus (`+` attach, `@` mention, resource-tab `+`) do not mirror the sidebar. Their order is a product decision encoded in `RESOURCE_MENU_ORDER` (see below), and every resource menu shares it.

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

## Grouping: a rule marks a change in what the action acts on
Expand Down Expand Up @@ -106,10 +107,10 @@ grouping wants the standard grouping.
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.

```ts
/** Top-down order for every menu listing resource families, mirroring the sidebar. */
/** Top-down order for every menu listing resource families. */
export const RESOURCE_MENU_ORDER: readonly MothershipResourceType[] = [
'integration', 'task', 'table', 'file', 'filefolder',
'knowledgebase', 'log', 'workflow', 'folder', 'browser', 'terminal', 'generic',
'integration', 'task', 'dashboard', 'table', 'file', 'filefolder',
'knowledgebase', 'workflow', 'log', 'folder', 'browser', 'terminal', 'generic',
]

export function byResourceMenuOrder<T extends { type: MothershipResourceType }>(a: T, b: T) {
Expand Down
17 changes: 17 additions & 0 deletions .github/workflows/desktop-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ on:
- 'apps/sim/app/layout.tsx'
- 'apps/sim/hooks/use-desktop-update-state.ts'
- 'apps/sim/lib/desktop/**'
- 'apps/sim/app/desktop/connect/**'
- 'apps/sim/app/credential-groups/**'
- 'apps/sim/hooks/queries/slack-search.ts'
- 'apps/sim/hooks/queries/personal-search-integrations.ts'
- 'apps/sim/hooks/use-search-integration-connection.ts'
- 'apps/sim/hooks/use-github-installation-setup.ts'
- 'apps/sim/app/o/**/integrations/indexed/use-member-enrollment.ts'
- 'apps/sim/lib/api/contracts/desktop-source-connect.ts'
- 'apps/sim/scripts/fixtures/desktop-source-connect.tsx'
- 'apps/sim/app/workspace/**/browser-session/**'
- 'apps/sim/app/_styles/**'
- 'apps/sim/lib/postcss/**'
Expand Down Expand Up @@ -61,6 +70,10 @@ jobs:
working-directory: apps/desktop
run: bun run build

- name: Install system-browser fixture
working-directory: apps/desktop
run: bunx playwright install chromium

- name: Run Playwright _electron smoke suite
working-directory: apps/desktop
run: bunx playwright test
Expand Down Expand Up @@ -98,6 +111,10 @@ jobs:
working-directory: apps/desktop
run: bun run build

- name: Install system-browser fixture
working-directory: apps/desktop
run: bunx playwright install chromium

- name: Run Playwright _electron smoke suite
working-directory: apps/desktop
run: bunx playwright test
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/desktop-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ jobs:
SIM_DESKTOP_DEFAULT_ORIGIN: ${{ steps.channel.outputs.origin }}
run: bun run build

- name: Install system-browser fixture
working-directory: apps/desktop
run: bunx playwright install chromium

- name: Run Electron smoke tests
working-directory: apps/desktop
env:
Expand Down
54 changes: 54 additions & 0 deletions .github/workflows/test-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,60 @@ jobs:
if-no-files-found: ignore
retention-days: 7

- name: Verify Lucid MCP search and complete diagram reads over real HTTP
if: matrix.provision == 'push'
working-directory: apps/sim
env:
NEXT_PUBLIC_APP_URL: http://127.0.0.1:3040
NEXT_PUBLIC_FORCE_HOSTED: 'false'
SEARCH_LUCID_REPORT_PATH: ${{ runner.temp }}/search-lucid.json
run: bun scripts/test-search-lucid-e2e.ts

- name: Upload Lucid acceptance report
if: failure() && matrix.provision == 'push'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: search-lucid
path: ${{ runner.temp }}/search-lucid.json
if-no-files-found: ignore
retention-days: 7

- name: Verify Zoom search over real HTTP
if: matrix.provision == 'push'
working-directory: apps/sim
env:
NEXT_PUBLIC_APP_URL: http://127.0.0.1:3040
NEXT_PUBLIC_FORCE_HOSTED: 'false'
SEARCH_ZOOM_REPORT_PATH: ${{ runner.temp }}/search-zoom.json
run: bun scripts/test-search-zoom-e2e.ts

- name: Upload Zoom acceptance report
if: failure() && matrix.provision == 'push'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: search-zoom
path: ${{ runner.temp }}/search-zoom.json
if-no-files-found: ignore
retention-days: 7

- name: Verify Google Meet search over real HTTP
if: matrix.provision == 'push'
working-directory: apps/sim
env:
NEXT_PUBLIC_APP_URL: http://127.0.0.1:3040
NEXT_PUBLIC_FORCE_HOSTED: 'false'
SEARCH_GOOGLE_MEET_REPORT_PATH: ${{ runner.temp }}/search-google-meet.json
run: bun scripts/test-search-google-meet-e2e.ts

- name: Upload Google Meet acceptance report
if: failure() && matrix.provision == 'push'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: search-google-meet
path: ${{ runner.temp }}/search-google-meet.json
if-no-files-found: ignore
retention-days: 7

- name: Verify SCIM and administration over real HTTP
working-directory: apps/sim
env:
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ The `'use client'` server boundary, the app/worker runtime env split, and featur
- **Components**: `'use client'` only for hooks or browser APIs. Structure order, extraction thresholds, and list-render rules: `.claude/rules/sim-components.md`. Render-performance idioms (lazy-init refs, hoisting, `Map` pre-indexing, `[...arr].sort()` never `toSorted()` on client paths): `.claude/rules/sim-react-performance.md`. For effect/state/memo/callback anti-patterns use the `/you-might-not-need-*` skills and verify against the running UI.
- **State ownership**: React Query owns server data — never `useState` + `fetch`; shareable client view-state (tabs, filters, search, pagination, selected id) lives in the URL via `nuqs`; Zustand owns global client state; `useState` owns UI-only state. Hooks: `.claude/rules/sim-hooks.md`. Stores (`devtools`, `persist` only with an explicit `partialize` whitelist, workflow value invariants): `.claude/rules/sim-stores.md`. URL state: `.claude/rules/sim-url-state.md`.
- **Utils**: inline a helper with one consumer; create `utils.ts` when 2+ files share it — in `lib/` (app-wide) or `feature/utils/` (feature-scoped). Check `lib/` before writing a new one.
- **Lists and menus** mirror the order the user already reads elsewhere (sidebar, toolbar), encoded in one exported order constant; a separator marks only a change in what the action acts on (typically one, before the destructive action): `.claude/rules/sim-list-ordering.md`.
- **Lists and menus** mirror the order the user already reads elsewhere (toolbar, settings nav), encoded in one exported order constant (resource menus share `RESOURCE_MENU_ORDER`, a product order that does not mirror the sidebar); a separator marks only a change in what the action acts on (typically one, before the destructive action): `.claude/rules/sim-list-ordering.md`.
- **Caching**: `lru-cache` with a `max` ceiling, never a hand-rolled TTL `Map`; a lifecycle map is not a cache; cache the gate, never the credential: `.claude/rules/sim-caching.md`.

## API Contracts and Routes
Expand Down
2 changes: 2 additions & 0 deletions apps/desktop/e2e/fixtures/browser-buffer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/** Matches Next's browser Buffer polyfill when bundling application code with esbuild. */
export { Buffer } from 'buffer'
Loading
Loading