Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
cef594c
fix(mothership): leave desktop tool calls to the desktop app in other…
waleedlatif1 Oct 2, 2026
8a82103
feat(powerbi): add Power BI actions (#8538)
BillLeoutsakosvl346 Oct 2, 2026
dd24582
fix(powerbi): clear the explicit-any and unused-export ratchets on st…
waleedlatif1 Oct 2, 2026
f007bd6
feat(library): How to Use a Postgres MCP Server With AI Agents: Secur…
icecrasher321 Oct 2, 2026
b8f4d2e
docs(library): update ai-agent-examples-by-department-and-industry (#…
icecrasher321 Oct 2, 2026
24b4957
fix(audits): close guardrail detector gaps and correct guidance from …
waleedlatif1 Oct 2, 2026
b36757f
fix(knowledge): scope list counts to selected knowledge bases (#8575)
icecrasher321 Oct 2, 2026
c576e40
fix(integrations): list tools for integrations without an operation d…
waleedlatif1 Oct 2, 2026
ba0c8c7
fix(sdk): default both SDKs to the www.sim.ai host (#8581)
waleedlatif1 Oct 2, 2026
44016cd
feat(search): browse Lucid folders and Notion pages (#8579)
waleedlatif1 Oct 2, 2026
d05ae7a
fix(mothership): make chat fork complete, consistent and safe to retr…
waleedlatif1 Oct 2, 2026
78c371e
feat(youcom): add You.com integration (#8584)
waleedlatif1 Oct 2, 2026
c19db87
fix(landing): return 404 for unknown library, blog, integration, mode…
waleedlatif1 Oct 2, 2026
19abda3
fix(files): read offset 0 as the first line instead of rejecting it (…
waleedlatif1 Oct 2, 2026
405cc6a
feat(forks): compare last synced source deployments (#8586)
icecrasher321 Oct 2, 2026
d3bf864
fix(audits): apply browser-runtime rules to @sim/utils; align setting…
waleedlatif1 Oct 2, 2026
0c86cb6
fix(credentials): make Claude Platform API keys available in the prov…
TheodoreSpeaks Oct 2, 2026
d9a6769
chore(pi): upgrade agent to 1.0.0 (#8585)
BillLeoutsakosvl346 Oct 3, 2026
52878d1
fix(docs): document You.com tools and expand shared output spreads (#…
waleedlatif1 Oct 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .agents/skills/add-block-preview/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ To pull an already-GA block from discovery surfaces on hosted (incident, depreca
- **Clone-not-remove:** gated blocks stay in `getAllBlocks()` output as clones with `hideFromToolbar: true` — `.find`-by-type consumers rely on this. Never filter them out.
- **Keys are registry block types.** Never `custom_block_*` (parse drops them — custom blocks have their own enabled/disabled lifecycle).
- **The shared hidden-predicate is `isHiddenUnder`** (`apps/sim/blocks/visibility/context.ts`). Never restate the preview/disabled rule inline at a new consumer.
- **Process-global caches stay ungated.** Shared builders such as `getExposedIntegrationTools` (`lib/integrations/tool-catalog.ts`) build the ungated universe; per-viewer filtering happens at consumer time via `isHiddenUnder`. Never move gating into a shared builder.
- **Process-global caches stay ungated.** Shared builders such as `getExposedIntegrationTools` (`apps/sim/lib/integrations/tool-catalog.ts`) build the ungated universe; per-viewer filtering happens at consumer time via `isHiddenUnder`. Never move gating into a shared builder.
- Gating is **surface hiding, not secrecy** — the full config ships in the client JS bundle. Anything truly secret cannot be a registered block.

## Tests
Expand Down
7 changes: 6 additions & 1 deletion .agents/skills/add-block/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ When several fields are mutually exclusive alternatives, mark them all `required
other paths ever get a chance to supply the value.

**Constraints (block-wide):**
- `canonicalParamId` must not equal any subblock `id` in the block.
- `canonicalParamId` may equal only the `id` of a member of its own group, as `channel` does in the canonicalParamId Pattern below; it must never equal any other subblock's `id`. (`blocks.test.ts` enforces the case of a subblock with no `canonicalParamId`.)
- One canonical id links exactly one basic/advanced pair for one logical parameter. Groups are keyed by canonical id across every subblock and hold one `basicId`, so two operations that each need a pair need two canonical ids.
- All members of a group share the same `required` status.

Expand Down Expand Up @@ -562,6 +562,11 @@ Use `wandConfig` on fields that are hard to fill by hand — timestamps (`genera

## Tools Configuration

**Write operation ids and tool ids as string literals** in the `operation` dropdown `options` and
`tools.access`, never through constants (`id: SEARCH`, `access: [SEARCH]`). `scripts/generate-docs.ts`
reads them from source with regexes, so a constant parses as empty: the docs page loses its whole
Actions section and the integration catalog ships blank operation descriptions, with no check failing.

**Preferred:** Use tool names directly as dropdown option IDs to avoid switch cases:
```typescript
// Dropdown options use tool IDs directly
Expand Down
2 changes: 1 addition & 1 deletion .agents/skills/add-connector/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ The user sees a toggle button (ArrowLeftRight) to switch between the selector dr

1. **Every selector field MUST have a canonical pair** — a corresponding `short-input` (or `dropdown`) field with the same `canonicalParamId` and `mode: 'advanced'`.
2. **`required` must be set identically on both fields** in a pair. If the selector is required, the manual input must also be required.
3. **`canonicalParamId` must match the key the connector expects in `sourceConfig`** (e.g. `baseId`, `channel`, `teamId`). The advanced field's `id` should typically match `canonicalParamId` (connector config fields differ from block subBlocks here; the block rule that `canonicalParamId` must not equal a subblock id does not apply).
3. **`canonicalParamId` must match the key the connector expects in `sourceConfig`** (e.g. `baseId`, `channel`, `teamId`). The advanced field's `id` should typically match `canonicalParamId` (connector config fields differ from block subBlocks here; the block rule that `canonicalParamId` must not equal the id of a subblock without a `canonicalParamId` does not apply).
4. **`dependsOn` references the selector field's `id`**, not the `canonicalParamId`. The modal propagates dependency clearing across canonical siblings automatically — changing either field in a parent pair clears dependent children.

### Selector canonical pair example (Airtable base → table cascade)
Expand Down
11 changes: 6 additions & 5 deletions .agents/skills/add-settings-page/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,12 @@ Each grep lists candidates; review every match against the expected ones named b

1. Find hand-rolled shells that should be `SettingsPanel`:
`git grep -n "flex h-full flex-col bg-\[var(--bg)\]" -- 'apps/sim/**/settings/**' 'apps/sim/ee/'`
— expected matches: the workspace and organization `settings/layout.tsx` shells, the shared
header shell (`components/settings/settings-header.tsx`), `CredentialDetailLayout` (the
`settings/secrets/[credentialId]` exception), or an entitlement/loading gate. A detail
sub-view is never a match: it passes `back={{ text, icon: ArrowLeft, onSelect }}` to
`SettingsPanel`. Anything else is a violation: render it through `SettingsPanel`.
— expected matches: the workspace and organization `settings/layout.tsx` shells and the
shared header shell (`components/settings/settings-header.tsx`); an entitlement/loading gate
is also fine. `CredentialDetailLayout` (the `settings/secrets/[credentialId]` exception) is
an exempt hand-rolled shell outside these pathspecs. A detail sub-view is never a match: it
passes `back={{ text, icon: ArrowLeft, onSelect }}` to `SettingsPanel`. Anything else is a
violation: render it through `SettingsPanel`.
2. Find hand-rolled title blocks:
`git grep -n "text-\[var(--text-body)\] text-lg" -- 'apps/sim/**/settings/**' 'apps/sim/ee/'`
— the only title is the `<h1>` in `settings-header.tsx`; a non-heading value at that size
Expand Down
7 changes: 4 additions & 3 deletions .agents/skills/babysit/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,10 @@ conditions freshly after every push.
across all pages has `isResolved: true`, and every check has finished and passed, stop —
report the outcome (see "Reporting" below) and skip the rest of this list.

2. **If the PR has a merge conflict**, resolve it with step 6 (its rebase-based sync flow and
the `/ship` gates; a merge commit would be discarded by that rebase), then steps 7–8: push
with `--force-with-lease` and re-trigger review.
2. **If the PR has a merge conflict**, rebase rather than merge (step 6's rebase would discard a
merge commit): `git fetch origin staging && git rebase origin/staging`, resolve each conflict
and `git rebase --continue` until the rebase finishes. Then run step 6 (the sync check and the
`/ship` gates), then steps 7–8: push with `--force-with-lease` and re-trigger review.
Comment thread
waleedlatif1 marked this conversation as resolved.

3. **If no review has run yet** (fresh PR, no bot comments): both run automatically on PR open —
confirm via `gh pr checks <n>` (look for `Greptile Review` and `cubic · AI code reviewer`) and
Expand Down
5 changes: 3 additions & 2 deletions .agents/skills/ship/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ When the user runs `/ship`:
- Then run root `bun run test` from the repo root. It chains `test:scripts` (the `scripts/*.test.ts` suite CI runs) before every workspace suite; workspace-scoped runs skip it, which is how a `scripts/check-*.test.ts` failure has reached CI. A failing test aborts ship.
5. **Run migration safety** — only if the diff touches `packages/db/migrations/**` or `packages/db/schema.ts`:
- Run `/db-migrate` to review the migration for zero-downtime safety (expand/contract phasing, backward-compatibility with the deployed app version).
- `cd packages/db && bunx drizzle-kit generate && git status --porcelain ./migrations` must print nothing (CI's schema/migration sync step).
- `(cd packages/db && bunx drizzle-kit generate && git status --porcelain ./migrations)` must print nothing (CI's schema/migration sync step).
- `bun run check:migrations origin/staging` must pass (staging is the PR base). Do not silence a flagged statement with a `-- migration-safe:` annotation unless `/db-migrate` confirmed the old code no longer depends on it; otherwise split the destructive change into a later deploy.
6. **Run pre-ship checks** from the repo root before staging. This has two phases: first **regenerate** every committed artifact so generated files never drift into a CI failure (this is what catches things like `agent-stream-docs` going stale after a `models.ts` edit), then run the **full audit suite** CI's `Lint and Test` job enforces. Both phases parallelize — but only across commands that write **disjoint** outputs — and a bare `wait` swallows child exit codes, so both phases below explicitly collect each job's status and abort ship if any failed.

Expand Down Expand Up @@ -78,12 +78,13 @@ When the user runs `/ship`:
# Runs every audit CI runs, concurrently, and replays the output of any that fail.
# The audit list is derived in scripts/run-audits.ts — do not hand-list audits here.
bun run check:audits || { echo "❌ audit(s) failed — do not ship"; exit 1; }
bun run type-check || { echo "❌ type-check failed — do not ship"; exit 1; }
# CI's "Verify docs manifest is in sync" step is not a `check:*` script, so the runner above
# does not cover it. (CI's "Security audit" `bun audit` step is `continue-on-error` — advisory
# only, not a gate — so it is deliberately not run here.)
bun run docs-manifest:check || { echo "❌ docs manifest out of sync — do not ship"; exit 1; }
```
If Phase A regenerated a file, its matching `:check` in Phase B now passes trivially — that parity is the point. Do not ship with any generator or audit failing; fix the cause (never silence it) and re-run. `check:migrations` and `type-check` are covered by steps 5 and CI respectively and are not repeated here.
If Phase A regenerated a file, its matching `:check` in Phase B now passes trivially — that parity is the point. Do not ship with any generator or audit failing; fix the cause (never silence it) and re-run. `check:migrations` is covered by step 5 and is not repeated here.
7. **Stage and commit** the changes with the generated message — including any files Phase A regenerated in step 6
8. **Push to origin** using the current branch name — `--force-with-lease` if step 2's sync
check did any history rewrite (a clean rebase or a cherry-pick rebuild) on a branch that had
Expand Down
2 changes: 1 addition & 1 deletion .claude/rules/sim-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ When rendering or sorting a list of rows against a lookup collection (members, f
react-doctor diagnostics are hypotheses, not verdicts — confirm against the code before acting, and preserve behavior. Known repo-specific false positives to NOT "fix":

- `no-barrel-import` — barrel imports are the repo convention (see sim-imports.md, "Barrel Exports"). Keep them.
- `js-tosorted-immutable` — won't-fix anywhere; `check:utils` bans the ES2023 array methods repo-wide.
- `js-tosorted-immutable` — won't-fix anywhere; `tsc` rejects the ES2023 array methods, because no tsconfig raises `lib` past ES2022.
- `rerender-state-only-in-handlers` / "state set but never rendered" — a false positive when the `useState` is consumed by a `useEffect`/`useLayoutEffect` dependency (the effect must re-run on change). Only convert to a ref when nothing reads the value reactively.
- `no-render-in-render` — a helper *called inline* (`{renderRow()}`) is reconciled by position and does **not** remount, so extracting it to a component is usually pure churn and can regress behavior (prop-drilling many closures, focus/scroll loss on the inner `<input>`). Apply it only when the helper is genuinely a *component defined during render*, or when the move is mechanical (a stateless, ref-free helper whose closures become a small, explicit prop set).
- `async-await-in-loop` on an upload/progress loop where sequential execution is intentional (per-item progress, server backpressure) — leave it.
Expand Down
2 changes: 1 addition & 1 deletion .claude/rules/sim-integrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ The full authoring instructions — tool/block/icon/trigger scaffolding, SubBloc
- Tool IDs and the two registration/coercion rules are in the root `CLAUDE.md` → Integrations. `blocks/registry.ts` holds only the accessor functions; triggers register in `triggers/registry.ts`.
- Give every subblock a unique `id`: duplicates collide silently (the last definition wins). `blocks.test.ts` fails a duplicate within one condition unless the copies are a basic/advanced mode-swap pair, one basic plus trigger-mode copies, or all carry `canonicalParamId`. The only sanctioned cross-condition reuse is the hosted-key `apiKey` pair (`/add-hosted-key`), where both fields deliberately share one value.
- Keep block outputs aligned with what the referenced tools actually return, and block `tools.access` aligned with the registered tool IDs.
- `canonicalParamId` must NOT match the `id` of a subblock that has no `canonicalParamId` (a group member may share it, as the `add-block` skill's `channel` example does), must be unique **block-wide** (groups are keyed by canonical id across every subblock and hold exactly one `basicId`, so two operations that each need a pair need two different canonical ids), and all subblocks in a canonical group must share the same `required` status. The `inputs` section and the params function reference canonical IDs, not raw subblock IDs — the serializer deletes the subblock IDs and republishes the active member's value under the canonical ID.
- `canonicalParamId` may match only the `id` of a member of its own group (as the `add-block` skill's `channel` example does), never any other subblock's `id`, must be unique **block-wide** (groups are keyed by canonical id across every subblock and hold exactly one `basicId`, so two operations that each need a pair need two different canonical ids), and all subblocks in a canonical group must share the same `required` status. The `inputs` section and the params function reference canonical IDs, not raw subblock IDs — the serializer deletes the subblock IDs and republishes the active member's value under the canonical ID.
- A canonical pair carries ONE concept. For files that is upload (basic) + file reference (advanced), normalized with `normalizeFileInput`, as in Gmail attachments (`blocks/blocks/gmail.ts`). Never overload the advanced side with alternate identifiers (URL, provider asset ID) — give those their own subblocks, mark mutually exclusive sources `required: false`, and enforce "exactly one" at execution.
- A sub-block's option list is EITHER `selectorKey` (a registered selector — the only way to load a remote list, and the only one that works off the canvas) OR `options` (a static array, or a pure function of the block's own values). Never fetch from a block definition, and never read the workflow stores there. A credential sub-block needs `canonicalParamId: 'oauthCredential'` for its dependants' selectors to resolve. A secret must never appear in a selector's `getQueryKey`. `bun run check:fork-dependent-coverage` fails a `dependsOn` under a credential/KB/table anchor that the fork sync modal cannot offer.
- Integration blocks (`category: 'tools'`) must set `integrationType` (`integration-catalog:check` fails without it) and export a `{Service}BlockMeta` (with `tags`); set `authMode` and `docsLink` too, which otherwise fall back to a credential-subblock guess and the generated docs page — see the `/add-block` skill's BlockMeta section. `{Service}BlockMeta.skills` must be grounded in operations the block exposes via `tools.access` and sourced from real, popular use cases found online — never invented.
Expand Down
2 changes: 1 addition & 1 deletion .claude/rules/sim-react-performance.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ return items.sort(compare)
return [...items].sort(compare)
```

**Do NOT use `toSorted()` / `toReversed()` / `with()` / `toSpliced()`.** They are ES2023 *runtime* methods — and a tsconfig `"lib": ["ES2023"]` only makes them **type-check**, it does not make them **run**. Next/SWC compiles syntax but does **not** polyfill prototype methods, and the default browserslist still includes browsers without them (`toSorted` landed in Safari 16 / iOS 16, so any device capped at iOS 15 throws `TypeError: x.toSorted is not a function` and crashes the page). The perf difference vs `[...arr].sort()` is negligible (both allocate one array), so the copy-then-sort form is used everywhere: whether a module reaches the browser is not visible from its path. `check:utils` flags `toSorted`/`toReversed`/`toSpliced` repo-wide and `with` when called with a numeric index (an identifier index is indistinguishable from OpenTelemetry's `context.with`).
**Do NOT use `toSorted()` / `toReversed()` / `with()` / `toSpliced()`.** They are ES2023 *runtime* methods — and a tsconfig `"lib": ["ES2023"]` only makes them **type-check**, it does not make them **run**. Next/SWC compiles syntax but does **not** polyfill prototype methods, and the default browserslist still includes browsers without them (`toSorted` landed in Safari 16 / iOS 16, so any device capped at iOS 15 throws `TypeError: x.toSorted is not a function` and crashes the page). The perf difference vs `[...arr].sort()` is negligible (both allocate one array), so the copy-then-sort form is used everywhere: whether a module reaches the browser is not visible from its path. Every tsconfig keeps `"lib"` at or below ES2022 so `tsc` rejects these at each call site on a typed receiver (and still accepts OpenTelemetry's `context.with`, which it tells apart by type); `check:utils` fails if a tsconfig raises `lib` past ES2022, which is how they shipped in #5340, and also matches `toSorted`/`toReversed`/`toSpliced` in source, since tsc accepts any method on an `any` receiver. `.with` on an `any` receiver is caught by neither, so type a parsed array before copying from it. Never raise it to make one type-check.
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.

## Run independent awaits in parallel

Expand Down
7 changes: 5 additions & 2 deletions .claude/rules/sim-settings-pages.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,17 @@ return (
## Title + description live in navigation metadata

`apps/sim/components/settings/navigation.ts` is the single source of truth (the
`settings/navigation.ts` in the route tree is only a re-export shim). Every `SETTINGS_SECTION_REGISTRY` entry carries a one-line `description`; `SettingsPanel`
`settings/navigation.ts` in the route tree is only a re-export shim). Each `SETTINGS_SECTION_REGISTRY` entry's one-line description is
`unified.description` (a plane projection's `planes.<plane>.description` overrides it where that
plane's scope differs), or, for a section that exists only on a standalone plane, its
`planes.<plane>.description`; `SettingsPanel`
resolves both via `getSettingsSectionMeta(plane, section)` and the
`SettingsSectionProvider` the settings shell wraps around the active section.

Adding a new settings page:

1. Add the section id to the `UnifiedSettingsSection` union + a `SETTINGS_SECTION_REGISTRY`
entry (with `label` **and** `unified.description`) in `components/settings/navigation.ts`. Keep descriptions verb-first, one line,
entry (with `label` **and** its description, as described above) in `components/settings/navigation.ts`. Keep descriptions verb-first, one line,
~40–55 chars, in the product voice (see `.claude/rules/constitution.md`).
2. Register its module in `SECTION_MODULES` (`settings/section-warmers.ts`) and render it
inside the shell's `effectiveSection` switch in `settings/[section]/settings.tsx`.
Expand Down
2 changes: 1 addition & 1 deletion .claude/rules/sim-styling.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ Draw a line with a real `border-*` utility. Never hand-roll one as `shadow-[inse
- **Errors** → `error` prop. Never `className={cn(err && 'border-[var(--text-error)]')}`.
- **Leading icon** → `icon` prop (rendered 14px in `--text-icon`).
- **Trailing buttons** (reveal/copy/fetch) → `endAdornment`.
- **Inner-input styling** (e.g. `font-mono`, number-spinner reset) → `inputClassName` (ChipInput only). See `app/workspace/[workspaceId]/settings/components/billing/components/usage-limit-field/usage-limit-field.tsx`.
- **Inner-input styling** (e.g. `font-mono`, number-spinner reset) → `inputClassName` (ChipInput only). See `ee/whitelabeling/components/whitelabeling-settings.tsx`.
- **`ChipModalField` controls take NO className.** Pass `title`/`value`/`onChange`/`error`/`hint`/`required`/`flush`. The field owns label, control, and error/hint rendering. See `app/workspace/[workspaceId]/skills/components/skill-modal/skill-modal.tsx`.

### What className MAY carry
Expand Down
Loading
Loading