Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
138 commits
Select commit Hold shift + click to select a range
cb05f50
docs(library): update agentic-ai-coding-tools-what-they-are-and-how-t…
icecrasher321 Oct 5, 2026
1056845
feat(library): How do you build an AI bot for Discord without code? (…
icecrasher321 Oct 5, 2026
733f4e9
perf(sandbox): grant the run_code session lease in the reconnect inst…
waleedlatif1 Oct 5, 2026
dc10d4c
fix(chat): label simple effort options with the effort they send (#8619)
waleedlatif1 Oct 5, 2026
807523e
feat(workflows): stop a manual v2 run after a block, and `workflows r…
waleedlatif1 Oct 5, 2026
b2c5b76
fix(executor): drop the full JSON clone of execution state at run com…
waleedlatif1 Oct 5, 2026
c723046
fix(logs): keep a block log's file size from changing after the block…
waleedlatif1 Oct 5, 2026
ea88578
feat(projects): add project identity and lifecycle foundation (#8580)
mzxchandra Oct 5, 2026
a865f47
fix(mcp): restrict MCP server destination changes to admins (#8629)
TheodoreSpeaks Oct 5, 2026
2c8eeaf
fix(code-placeholders): reject shell arithmetic placeholders (#8628)
icecrasher321 Oct 5, 2026
6b3cd82
fix(credentials): keep the field-less GitHub App installation out of …
TheodoreSpeaks Oct 5, 2026
844d181
fix(executor): fail a stop-after run whose routing skips the stop blo…
waleedlatif1 Oct 5, 2026
21c8a07
chore(terms): update terms of service (#8636)
waleedlatif1 Oct 5, 2026
7050250
fix(projects): restore workspace deletion and tighten Project lifecyc…
waleedlatif1 Oct 5, 2026
d32d4c9
feat(mothership): keep each chat's reasoning effort, default to mediu…
waleedlatif1 Oct 5, 2026
bd06886
feat(library): Best AI Coding Agents for Refactoring and Debugging: 5…
icecrasher321 Oct 5, 2026
6845fd9
feat(library): Best Conversational AI Platforms With CRM and Helpdesk…
icecrasher321 Oct 5, 2026
42c972c
docs(library): update langgraph-alternatives (#8640)
icecrasher321 Oct 5, 2026
8524cb9
docs(library): update dify-alternatives (#8641)
icecrasher321 Oct 5, 2026
2613543
docs(library): update best-ai-agents-for-customer-support-automation …
icecrasher321 Oct 5, 2026
2b007e1
docs(library): update ai-agent-observability (#8645)
icecrasher321 Oct 6, 2026
73bb265
docs(library): update aeo-vs-geo-what-answer-engine-and-generative-en…
icecrasher321 Oct 6, 2026
75cc375
docs(library): update mcp-security (#8649)
icecrasher321 Oct 6, 2026
2d043e9
docs(library): update ai-agents-in-procurement (#8648)
icecrasher321 Oct 6, 2026
e8e946c
docs(library): update sim-open-source-zapier-alternative (#8646)
icecrasher321 Oct 6, 2026
d4f26a7
fix(seo): make content pagination indexable (#8651)
waleedlatif1 Oct 6, 2026
46cd710
fix(mothership): refuse desktop claims for unapproved or stopped call…
waleedlatif1 Oct 6, 2026
269f9b8
fix(mothership): roll back a failed effort save by pick, not by value…
waleedlatif1 Oct 6, 2026
20a7350
fix(mcp): treat different URL credentials as a new destination (#8656)
TheodoreSpeaks Oct 6, 2026
3064219
fix(executor): unwrap boxed primitives by internal slot when checking…
waleedlatif1 Oct 6, 2026
777b3e9
fix(projects): revoke banned users' keys first and create imported wo…
waleedlatif1 Oct 6, 2026
648bf45
fix(mothership): default chat effort back to high (#8659)
waleedlatif1 Oct 6, 2026
239526a
improvement(tables): read row counts and versions through an append-o…
TheodoreSpeaks Oct 6, 2026
70e1980
docs(workflows): describe what still runs when a stop-after target is…
waleedlatif1 Oct 6, 2026
ef59524
test(mcp): exercise the real destination check in lifecycle tests (#8…
TheodoreSpeaks Oct 6, 2026
9af89fc
fix(mothership): fail unclaimed desktop calls fast and stop dropping …
waleedlatif1 Oct 6, 2026
c98e3c7
fix(sandbox): judge session lease coverage from the request's own clo…
waleedlatif1 Oct 6, 2026
a766a03
fix(mothership): keep a new chat's effort pick changed while its firs…
waleedlatif1 Oct 6, 2026
ba12945
feat(desktop): device registry, inbox and leased claims for a backgro…
waleedlatif1 Oct 6, 2026
65b247f
fix(mothership): keep local file tools running when the chat view cha…
waleedlatif1 Oct 6, 2026
63ba307
docs(library): update best-multi-agent-frameworks-2026 (#8678)
icecrasher321 Oct 6, 2026
b20ddc1
docs(library): update open-source-ai-agent-platforms (#8679)
icecrasher321 Oct 6, 2026
32a7f8e
fix(copilot): store tool file outputs from workspace chats under the …
waleedlatif1 Oct 6, 2026
7308e45
feat(library): 25 Multi-Step AI Agent Examples Beyond Chatbots (#8677)
icecrasher321 Oct 6, 2026
c9c2c4e
feat(plane): add core integration with self-hosted support (#8660)
waleedlatif1 Oct 6, 2026
d8ba4bf
feat(sso): allow self-hosted DNS verification bypass (#8681)
waleedlatif1 Oct 6, 2026
5156261
feat(desktop): bind turns to a desktop and enforce its deadlines from…
waleedlatif1 Oct 6, 2026
ab25c2a
docs(library): update ai-agent-examples-by-department-and-industry (#…
icecrasher321 Oct 6, 2026
94cba3b
fix(mothership): end desktop tools at sign-out and settle held report…
waleedlatif1 Oct 6, 2026
82591b5
docs(library): update top-ai-assistants-2026 (#8683)
icecrasher321 Oct 6, 2026
7307778
docs(library): update sim-vs-dedicated-chatbot-builders (#8684)
icecrasher321 Oct 6, 2026
5fccf71
docs(library): update best-ai-agents-for-lead-enrichment-2026 (#8687)
icecrasher321 Oct 6, 2026
c8ef18d
fix(desktop): inbox persistence order, desktop-only overdue sweep, an…
waleedlatif1 Oct 6, 2026
1f114dd
fix(mothership): re-read the transcript until the server has saved a …
waleedlatif1 Oct 6, 2026
662bd70
fix(mothership): re-attach at once when the user returns to a recover…
waleedlatif1 Oct 6, 2026
8714a8e
fix(mothership): keep a message the server never admitted instead of …
waleedlatif1 Oct 6, 2026
62287f6
test(desktop): keep the SQL and TypeScript desktop-call classifiers i…
waleedlatif1 Oct 6, 2026
5d86e42
docs(library): update 6-best-ai-observability-tools-for-production-ag…
icecrasher321 Oct 6, 2026
482f146
fix(plane): correct tile styling and capped connector syncs (#8690)
waleedlatif1 Oct 6, 2026
11f8190
fix(ci): stop each HTTP end-to-end app fully and start the next from …
waleedlatif1 Oct 6, 2026
3cc1ec1
fix(plane): validate webhook fields by registration mode (#8698)
waleedlatif1 Oct 6, 2026
d59e923
improvement(trigger): downsize connector sync and document processing…
waleedlatif1 Oct 6, 2026
551e05f
feat(mothership): let the worker choose models when the model picker …
waleedlatif1 Oct 6, 2026
5f1a29e
perf(cli): load a manual run's draft once and keep embedded CLI resul…
waleedlatif1 Oct 6, 2026
f4855cd
fix(mothership): prune composer contexts during render so fast typing…
waleedlatif1 Oct 6, 2026
632ba60
feat(desktop): run a chat's desktop tools in the background executor …
waleedlatif1 Oct 6, 2026
f98df1b
fix(e2e): compile every timed route first in the HTTP suites and stop…
waleedlatif1 Oct 7, 2026
6adf4c6
fix(mothership): close the remaining ways a chat send is lost, resent…
waleedlatif1 Oct 7, 2026
5ee756f
chore(table): remove unused table-update background task (#8708)
waleedlatif1 Oct 7, 2026
8fc4c1a
fix(analytics): protect production Google measurement (#8710)
waleedlatif1 Oct 7, 2026
db30e1a
improvement(triggers): move TRIGGER_TYPES to a dependency-free module…
waleedlatif1 Oct 7, 2026
ca11667
fix(chat): resolve a new chat's history entry to the chat route on Ba…
waleedlatif1 Oct 7, 2026
0d74834
feat(desktop): show background desktop chats and keep the chat view d…
waleedlatif1 Oct 7, 2026
d4d16a0
feat(desktop): keep the machine awake for background chats and yield …
waleedlatif1 Oct 7, 2026
6713fab
feat(desktop): import local files from the background executor (#8672)
waleedlatif1 Oct 7, 2026
da993c5
fix(events): start every SSE response once its subscriptions are live…
waleedlatif1 Oct 7, 2026
351b8b9
fix(mothership): keep a chatless surface's queue across remounts and …
waleedlatif1 Oct 7, 2026
e82689a
fix(ci): stop the detached telemetry flush too, re-signal stragglers …
waleedlatif1 Oct 7, 2026
ccce7f7
fix(webhooks): skip duplicate webhook deliveries already in progress …
waleedlatif1 Oct 7, 2026
ab6b400
chore(trigger): fix queues that never serialized and schedule missing…
waleedlatif1 Oct 7, 2026
b5a6d53
fix(mothership): run same-workflow workflow tools in order instead of…
waleedlatif1 Oct 7, 2026
18ad8b8
improvement(cron): only start outbox and file-search passes when work…
waleedlatif1 Oct 7, 2026
dfe8ecf
fix(desktop): read tmux format output with a separator no tmux versio…
waleedlatif1 Oct 7, 2026
ab588d4
fix(events): authorize the events queued before a stream opens once (…
waleedlatif1 Oct 7, 2026
988b079
fix(mothership): keep a withdrawn first message held at the queue hea…
waleedlatif1 Oct 7, 2026
29038b3
fix(ci): match E2E app tags literally, make them unique per run, and …
waleedlatif1 Oct 7, 2026
38942a7
fix(desktop): run an agent command on tmux that cannot tag its pane, …
waleedlatif1 Oct 7, 2026
2e7082f
fix(mothership): keep any queued send the server may already hold fro…
waleedlatif1 Oct 7, 2026
c5d07cc
fix(settings): prevent false unsaved prompts and preserve drafts (#8704)
waleedlatif1 Oct 7, 2026
48cbd4f
fix(ci): tidy stop-session.sh scans, listings and arguments (#8724)
waleedlatif1 Oct 7, 2026
00cedfa
fix(mothership): claim under the chat lock in the Stop-versus-recover…
waleedlatif1 Oct 7, 2026
edb2e6b
chore(nextjs): upgrade to 16.4.0 (#8729)
waleedlatif1 Oct 7, 2026
ae0a420
fix(mothership): retry a send that failed while the browser stayed on…
waleedlatif1 Oct 7, 2026
334b9f3
fix(desktop): stop the agent's tmux runs a previous process left goin…
waleedlatif1 Oct 7, 2026
566cea6
fix(desktop): frame each tmux format record so a newline in a field c…
waleedlatif1 Oct 7, 2026
1741ff9
test(mothership): stop the online case of the accepted-resend test pa…
waleedlatif1 Oct 7, 2026
055ff9c
improvement(outbox): load handler modules only for the event types a …
waleedlatif1 Oct 7, 2026
c3475fe
fix(mothership): decide once whether a queued send may already be on …
waleedlatif1 Oct 7, 2026
8f617da
refactor(desktop): one forward-only state per recorded tmux run, and …
waleedlatif1 Oct 7, 2026
102019b
test(desktop): stop the agent's terminal commands in the real app, wi…
waleedlatif1 Oct 7, 2026
96014bd
fix(mothership): keep a failed direct send ahead of follow-ups queued…
waleedlatif1 Oct 7, 2026
61ac093
fix(desktop): leave a stopped native file tool's outcome to Stop (#8732)
waleedlatif1 Oct 7, 2026
435d413
test(desktop): pin the journal snapshot before recovery, keep start g…
waleedlatif1 Oct 7, 2026
f83d977
refactor(mothership): one re-queue policy and one send payload, and k…
waleedlatif1 Oct 7, 2026
af5501b
improvement(desktop): Electron E2E for desktop tool lifetimes against…
waleedlatif1 Oct 7, 2026
f0e5700
fix(mothership): send a late queue write to the chat a new-chat queue…
waleedlatif1 Oct 7, 2026
3899fde
refactor(mothership): one hold field and one retry field on a queued …
waleedlatif1 Oct 7, 2026
00b6cee
fix(mothership): a pure resend verdict, and Send-now drops a message …
waleedlatif1 Oct 7, 2026
9e953d1
refactor(mothership): keep a queued send's reused id in one field (#8…
waleedlatif1 Oct 7, 2026
5d3806b
fix(desktop): keep a chat-view import alive while it works, by the le…
waleedlatif1 Oct 7, 2026
8760ca7
refactor(mothership): a saved Stop handoff's id wins on restore (#8747)
waleedlatif1 Oct 7, 2026
b74b9dd
fix(ci): count both sides of a rename in the desktop live gate, keep …
waleedlatif1 Oct 7, 2026
1a4a156
fix(desktop): linear path trim, prompt Stop between keystrokes, clear…
waleedlatif1 Oct 7, 2026
a7aaa2c
fix(outbox): log unloaded handler modules as a failure, not a complet…
waleedlatif1 Oct 7, 2026
9a1aca0
fix(desktop): stop a run the model never got the result of (#8749)
waleedlatif1 Oct 7, 2026
69d9ac6
fix(mothership): close a pre-aborted SSE stream, keep the new-chat ef…
waleedlatif1 Oct 7, 2026
6a92e05
fix(mothership): use a spinner while workflow resources load (#8756)
waleedlatif1 Oct 7, 2026
14e6c0a
improvement(mothership): relabel the Sol pick GPT-6.1 Sol and retire …
waleedlatif1 Oct 7, 2026
b4c38df
feat(providers): add Nebius Token Factory (#8759)
waleedlatif1 Oct 7, 2026
9ab24e9
ci: faster, cheaper, consistently named CI (#8750)
waleedlatif1 Oct 7, 2026
f775b29
fix(settings): protect generated keys and identity transitions (#8761)
waleedlatif1 Oct 7, 2026
bd7085e
fix(sandbox): keep reused E2B workbench leases within the runtime cap…
waleedlatif1 Oct 7, 2026
d8cb659
ci: duration-balanced integration shards, warm desktop-live, CI on ev…
waleedlatif1 Oct 7, 2026
b7fa794
fix(mothership): cancel desktop tools a signed-out turn starts late, …
waleedlatif1 Oct 7, 2026
96090ca
fix(tables): stop the fold sweep from starting a page query past its …
TheodoreSpeaks Oct 7, 2026
7b287b2
fix(docs): prerender complete LLM documentation (#8767)
waleedlatif1 Oct 7, 2026
350b016
improvement(ci): check out same-repo pull requests through a git mirr…
waleedlatif1 Oct 7, 2026
6df74d6
fix(docs): publish full LLM text as a static asset (#8769)
waleedlatif1 Oct 7, 2026
886cfa2
fix(billing): converge Stripe subscription syncs and stop webhook ech…
waleedlatif1 Oct 8, 2026
b7d5532
perf(pii): batch spaCy NER passes in redact_batch (#8772)
TheodoreSpeaks Oct 8, 2026
1f1e25d
improvement(files): add sharing to file resource view (#8775)
waleedlatif1 Oct 8, 2026
c53367c
feat(permission-groups): add agent default (#8771)
waleedlatif1 Oct 8, 2026
37f5cdf
feat(integrations): add Ramp and Microsoft Intune (#8780)
waleedlatif1 Oct 8, 2026
df34c67
feat(models): add current frontier models (#8777)
waleedlatif1 Oct 8, 2026
1f8c281
fix(executor): preserve stop-after across pause and resume (#8776)
waleedlatif1 Oct 8, 2026
59e749e
fix(audit): harden data drains and expand security event coverage (#8…
waleedlatif1 Oct 8, 2026
31a911d
improvement(desktop): ship the background executor without a flag, cl…
waleedlatif1 Oct 8, 2026
684b228
feat(api): expose credential sharing and SSO administration (#8770)
waleedlatif1 Oct 8, 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
  •  
  •  
  •  
4 changes: 2 additions & 2 deletions .agents/skills/add-settings-page/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ Each grep lists candidates; review every match against the expected ones named b
- Editable pages: confirm Save/Discard go through `saveDiscardActions()` and
dirty is wired via `useSettingsUnsavedGuard` (called before early-return
gates) — flag any hand-rolled Save button, `beforeunload`, or unsaved modal.
`git grep -n "beforeunload" -- 'apps/sim/**/settings/**' 'apps/sim/ee/'`
should only hit the centralized `use-settings-before-unload.ts`.
`git grep -n "beforeunload" -- 'apps/sim/**/settings/**' 'apps/sim/ee/' 'apps/sim/components/settings/' ':(exclude,glob)**/*.test.*'`
should only hit the centralized `use-settings-browser-navigation.ts`.
5. Fix each finding with the smallest structural change that satisfies the checklist;
do not touch handlers, state, queries, or gate returns. A pixel-size fix swaps
only the size class for its exact-pixel token (`text-[12px]` → `text-caption`).
Expand Down
7 changes: 5 additions & 2 deletions .agents/skills/ship/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ When the user runs `/ship`:
- 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).
- `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.
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` 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.

**Phase A — regenerate the always-in-repo committed artifacts (parallel), then let step 7 stage whatever changed.** Regenerate only the generators whose inputs live entirely in this repo and that any ordinary code change can drift — `agent-stream-docs:generate` (derives from the provider model registry), `docs-manifest:generate` (derives from docs page paths), and `skills:sync` (derives from `.agents/skills/**`). They write disjoint outputs (`apps/docs/…/agent.mdx`, `apps/sim/lib/mothership/generated/docs-manifest.ts`, and `.claude/skills` links), so they parallelize safely, and each is idempotent (a no-op when already in sync):
```bash
Expand All @@ -66,7 +66,7 @@ When the user runs `/ship`:

**Do NOT blanket-run the domain generators here.** `mship:generate` (`generate-mship-contracts.ts`) is an **umbrella** that drives all nine mothership contract generators (`mship-contracts`, `billing-protocol-contract`, `mship-tools`, the four `trace-*`, `metrics-contract`, `vfs-snapshot-contract`) and biome-formats `apps/sim/lib/mothership/generated/` — never run it *and* its constituents (they write the same files and corrupt each other in parallel), and never run it on an ordinary ship: it reads an **external** copilot-contract source that isn't checked out in most worktrees, so it hard-fails with `ENOENT` and would abort ship for an unrelated reason. `generate:pi-model-catalog` (under `apps/sim`) likewise regenerates from the installed Pi package, not repo source. `scripts/generate-docs.ts` rewrites the integration docs and client-safe catalog; run it when this PR changes their block/icon/landing-content inputs or when `integration-catalog:check` reports drift, then review its broad generated diff. Only when **this PR's diff actually touches** a domain generator's input do you regenerate it deliberately and run its matching `:check` (`bun run mship:check` / the individual `*:check`) — with the external source present.

**Phase B — run lint + every audit CI enforces, in parallel, and abort ship if any fails.** Before running the commands, compare this list with `.github/workflows/test-build.yml`; when CI adds an audit, run it and update this skill instead of trusting a stale snapshot. The env-flag audit is currently an inline workflow block rather than a package script: when `apps/sim/lib/core/config/env-flags.ts` changed, run that current workflow block verbatim instead of copying a second version into this skill. Run `bun run lint` first (it autofixes formatting and mutates files, so don't parallelize it with the read-only audits), then run the base-sensitive block-registry check, then fan the independent audits out and collect exit codes:
**Phase B — run lint + every audit CI enforces, in parallel, and abort ship if any fails.** Before running the commands, compare this list with `.github/workflows/checks.yml`; when CI adds an audit, run it and update this skill instead of trusting a stale snapshot. The env-flag audit is currently an inline workflow block rather than a package script: when `apps/sim/lib/core/config/env-flags.ts` changed, run that current workflow block verbatim instead of copying a second version into this skill. Run `bun run lint` first (it autofixes formatting and mutates files, so don't parallelize it with the read-only audits), then run the base-sensitive block-registry check, then fan the independent audits out and collect exit codes:
```bash
# autofix formatting first (mutating; not parallel-safe with the audits). Gate its exit too —
# a non-zero lint (unfixable errors) must abort before the audits run, not be ignored.
Expand All @@ -77,6 +77,9 @@ 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.
# Install CI's pinned actionlint version for the host OS/architecture and verify its
# artifact against the official release checksums in a local mktemp directory.
# Preserve CI's -shellcheck= -pyflakes= flags; lint all workflows and abort ship if it fails.
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
Expand Down
1 change: 1 addition & 0 deletions .claude/rules/landing-seo-geo.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ paths:
- All copy is server-rendered text: no text baked into images, no content that exists only after a client effect runs.
- Navbar is a Server Component (no `'use client'`) for immediate crawlability. Logo `<Image>` has `priority` (LCP element). The navbar `<nav>` carries `SiteNavigationElement` schema.org markup.
- Structured data: emit JSON-LD (`Organization`, `WebSite`, `WebApplication` with `featureList`, `FAQPage` if an FAQ exists) from a server component rendered before visible content. Keep `featureList` in sync with the features the page shows (`apps/sim/app/(landing)/components/home-structured-data/`).
- `/library` and `/blog` pagination stays server-rendered with real next/previous links. Each unfiltered page is indexable and uses its own canonical URL (`?page=2`, etc.); page 1 canonicalizes to the bare index. Tag-filtered variants remain `noindex,follow`. See [Google pagination guidance](https://developers.google.com/search/docs/specialty/ecommerce/pagination-and-incremental-page-loading).
- After adding routes or anchors, verify `app/sitemap.ts` and `app/robots.ts` still reflect reality.

## GEO (Generative Engine Optimisation)
Expand Down
55 changes: 27 additions & 28 deletions .claude/rules/sim-settings-pages.md
Original file line number Diff line number Diff line change
Expand Up @@ -339,34 +339,33 @@ rendered through `<SettingsActionChips actions={…} />` from
`@/components/settings/settings-header` — that is the shared chip path, and it
is what keeps tone/icon/variant/tooltip handling from drifting between the two
shells. Reach for it before hand-rolling a `Chip`.
- **`useSettingsUnsavedGuard({ isDirty })`** (`…/settings/hooks/use-settings-unsaved-guard`)
— syncs the page's local `isDirty` into the shared `useSettingsDirtyStore` (so
the sidebar's **section-switch** confirm + the centralized `beforeunload` both
apply for free) and returns `{ showUnsavedModal, setShowUnsavedModal, guardBack,
confirmDiscard }` for a detail view's **in-view back** chip.
- **Top-level pages** (whitelabeling, sso): call it **unassigned** —
`useSettingsUnsavedGuard({ isDirty: hasChanges })` — they only need the
store-sync; the sidebar/`beforeunload` do the rest.
- **Detail sub-views** (data-retention, access-control group-detail): route the
back chip through `onClick={() => guard.guardBack(closeFn)}` and render the
shared `<UnsavedChangesModal open={guard.showUnsavedModal}
onOpenChange={guard.setShowUnsavedModal} onDiscard={guard.confirmDiscard} />`
(from `@/app/workspace/[workspaceId]/components/credential-detail`). The
in-view header **Discard** chip (via `saveDiscardActions({ onDiscard })`) is a
*reset to original* — distinct from the back-confirm's discard, which leaves.
- **`useSettingsBeforeUnload`** is mounted by the settings shells
(`settings/layout.tsx` and `components/settings/standalone-settings-shell.tsx`) —
never add a per-page `beforeunload`.
- **Dirty *computation* stays local** (shapes differ: field-compare vs
normalize+stringify) — only how dirty is *consumed* is shared. Derive it (a
`const`/`useMemo`), never store it in `useState`.
- **CRITICAL — rules of hooks:** call `useSettingsUnsavedGuard(...)`
**unconditionally, before every early-return gate** (entitlement / loading /
not-entitled `return <SettingsEmptyState>`). A hook placed after a gate is
skipped on gated renders and crashes.
- The route-based credential detail keeps its own `useUnsavedChangesGuard` (it
guards real `router.push` navigation + browser Back via a history sentinel);
it already shares `UnsavedChangesModal`, so copy stays unified.
- **`useSettingsUnsavedGuard({ isDirty, navigationBlocked, onDiscard })`** from
`@/components/settings/use-settings-unsaved-guard` registers one editor with the
shared settings store. Register every full-page draft, including inline creation
forms. Dirty computation stays local and derived; fetched defaults stay clean.
- **`onDiscard` resets the registered draft.** The root `SettingsNavigationGuard`
owns the discard dialog, internal link interception, browser Back/Forward, and
refresh protection for registered editors. Do not add a per-page dialog or
history listener for an editor using this hook. Skill create/detail pages retain
their existing `useUnsavedChangesGuard` and local dialog until they migrate to
the shared registration.
- **Native history needs entry indexes.** The Navigation API supplies them for
legacy entries. Without it, native traversal to an unindexed entry cannot be
cancelled reliably; never guess a direction or rewrite the history stack.
- **History confirmation authorizes traversal before discarding.** Drafts are
discarded only when the browser reports the confirmed traversal, so a no-op
Back or Forward retains edits. Known cross-document traversal uses native unload
protection. An unknown cross-document target on a classic History browser can
require a second native confirmation after the shared dialog.
- **Detail back controls** call `guard.guardBack(closeFn)`. Other destructive view
transitions, such as switching an editor's direction or environment, also use
the shared `requestLeave` action before resetting their draft.
- **`navigationBlocked` covers pending saves and uploads.** The shared guard blocks
navigation while requests are pending. Attempts are not queued; retry after they
settle. Disable or preserve edits made during requests;
failed saves retain drafts, and successful saves only clear committed values.
- **Call the hook unconditionally, before every early-return gate** (entitlement,
loading, or empty-state return), so gated renders preserve hook order.

## Detail sub-views

Expand Down
6 changes: 3 additions & 3 deletions .claude/rules/sim-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ contracts, and demonstrated regressions.

| Suffix | Needs | Run with | In CI |
|--------|-------|----------|-------|
| `*.test.ts(x)` | nothing; global mocks from `vitest.setup.ts` | `vitest run` | Lint and Test job |
| `*.integration.ts` | real PostgreSQL (`TEST_DATABASE_URL`), optionally Redis (`TEST_REDIS_URL`) | `vitest run --mode integration` | `PostgreSQL integration` job, by glob |
| `*.test.ts(x)` | nothing; global mocks from `vitest.setup.ts` | `vitest run` | `test` jobs (sharded) |
| `*.integration.ts` | real PostgreSQL (`TEST_DATABASE_URL`), optionally Redis (`TEST_REDIS_URL`) | `vitest run --mode integration` | `integration` jobs, by glob (sharded per provisioning path) |
| `*.live.test.ts` | provider APIs, hosted sandboxes, local runtimes, or sibling checkouts | `vitest run --mode live <file>` (apps/sim) | never |
| `apps/desktop/e2e/*.spec.ts` | the packaged Electron app | Playwright | desktop E2E workflow |
| `apps/sim/scripts/test-*-e2e.ts` | a running app over HTTP | its `package.json` script when one exists (`bun run test:scim:e2e`; `test:workflow-version-compare:e2e` adds `--no-env-file`), else `bun scripts/test-<suite>-e2e.ts` from apps/sim | End-to-end over real HTTP job |
| `apps/sim/scripts/test-*-e2e.ts` | a running app over HTTP | its `package.json` script when one exists (`bun run test:scim:e2e`; `test:workflow-version-compare:e2e` adds `--no-env-file`), else `bun scripts/test-<suite>-e2e.ts` from apps/sim | `e2e` jobs (`.github/scripts/http-e2e.sh`) |

- A unit test lives next to its source: `feature.ts` → `feature.test.ts`. No network, no database,
no real timers.
Expand Down
1 change: 1 addition & 0 deletions .cursor/rules/landing-seo-geo.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ globs: ["apps/sim/app/(landing)/**/*.tsx","apps/sim/content/**/*.mdx"]
- All copy is server-rendered text: no text baked into images, no content that exists only after a client effect runs.
- Navbar is a Server Component (no `'use client'`) for immediate crawlability. Logo `<Image>` has `priority` (LCP element). The navbar `<nav>` carries `SiteNavigationElement` schema.org markup.
- Structured data: emit JSON-LD (`Organization`, `WebSite`, `WebApplication` with `featureList`, `FAQPage` if an FAQ exists) from a server component rendered before visible content. Keep `featureList` in sync with the features the page shows (`apps/sim/app/(landing)/components/home-structured-data/`).
- `/library` and `/blog` pagination stays server-rendered with real next/previous links. Each unfiltered page is indexable and uses its own canonical URL (`?page=2`, etc.); page 1 canonicalizes to the bare index. Tag-filtered variants remain `noindex,follow`. See [Google pagination guidance](https://developers.google.com/search/docs/specialty/ecommerce/pagination-and-incremental-page-loading).
- After adding routes or anchors, verify `app/sitemap.ts` and `app/robots.ts` still reflect reality.

## GEO (Generative Engine Optimisation)
Expand Down
55 changes: 27 additions & 28 deletions .cursor/rules/sim-settings-pages.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -336,34 +336,33 @@ rendered through `<SettingsActionChips actions={…} />` from
`@/components/settings/settings-header` — that is the shared chip path, and it
is what keeps tone/icon/variant/tooltip handling from drifting between the two
shells. Reach for it before hand-rolling a `Chip`.
- **`useSettingsUnsavedGuard({ isDirty })`** (`…/settings/hooks/use-settings-unsaved-guard`)
— syncs the page's local `isDirty` into the shared `useSettingsDirtyStore` (so
the sidebar's **section-switch** confirm + the centralized `beforeunload` both
apply for free) and returns `{ showUnsavedModal, setShowUnsavedModal, guardBack,
confirmDiscard }` for a detail view's **in-view back** chip.
- **Top-level pages** (whitelabeling, sso): call it **unassigned** —
`useSettingsUnsavedGuard({ isDirty: hasChanges })` — they only need the
store-sync; the sidebar/`beforeunload` do the rest.
- **Detail sub-views** (data-retention, access-control group-detail): route the
back chip through `onClick={() => guard.guardBack(closeFn)}` and render the
shared `<UnsavedChangesModal open={guard.showUnsavedModal}
onOpenChange={guard.setShowUnsavedModal} onDiscard={guard.confirmDiscard} />`
(from `@/app/workspace/[workspaceId]/components/credential-detail`). The
in-view header **Discard** chip (via `saveDiscardActions({ onDiscard })`) is a
*reset to original* — distinct from the back-confirm's discard, which leaves.
- **`useSettingsBeforeUnload`** is mounted by the settings shells
(`settings/layout.tsx` and `components/settings/standalone-settings-shell.tsx`) —
never add a per-page `beforeunload`.
- **Dirty *computation* stays local** (shapes differ: field-compare vs
normalize+stringify) — only how dirty is *consumed* is shared. Derive it (a
`const`/`useMemo`), never store it in `useState`.
- **CRITICAL — rules of hooks:** call `useSettingsUnsavedGuard(...)`
**unconditionally, before every early-return gate** (entitlement / loading /
not-entitled `return <SettingsEmptyState>`). A hook placed after a gate is
skipped on gated renders and crashes.
- The route-based credential detail keeps its own `useUnsavedChangesGuard` (it
guards real `router.push` navigation + browser Back via a history sentinel);
it already shares `UnsavedChangesModal`, so copy stays unified.
- **`useSettingsUnsavedGuard({ isDirty, navigationBlocked, onDiscard })`** from
`@/components/settings/use-settings-unsaved-guard` registers one editor with the
shared settings store. Register every full-page draft, including inline creation
forms. Dirty computation stays local and derived; fetched defaults stay clean.
- **`onDiscard` resets the registered draft.** The root `SettingsNavigationGuard`
owns the discard dialog, internal link interception, browser Back/Forward, and
refresh protection for registered editors. Do not add a per-page dialog or
history listener for an editor using this hook. Skill create/detail pages retain
their existing `useUnsavedChangesGuard` and local dialog until they migrate to
the shared registration.
- **Native history needs entry indexes.** The Navigation API supplies them for
legacy entries. Without it, native traversal to an unindexed entry cannot be
cancelled reliably; never guess a direction or rewrite the history stack.
- **History confirmation authorizes traversal before discarding.** Drafts are
discarded only when the browser reports the confirmed traversal, so a no-op
Back or Forward retains edits. Known cross-document traversal uses native unload
protection. An unknown cross-document target on a classic History browser can
require a second native confirmation after the shared dialog.
- **Detail back controls** call `guard.guardBack(closeFn)`. Other destructive view
transitions, such as switching an editor's direction or environment, also use
the shared `requestLeave` action before resetting their draft.
- **`navigationBlocked` covers pending saves and uploads.** The shared guard blocks
navigation while requests are pending. Attempts are not queued; retry after they
settle. Disable or preserve edits made during requests;
failed saves retain drafts, and successful saves only clear committed values.
- **Call the hook unconditionally, before every early-return gate** (entitlement,
loading, or empty-state return), so gated renders preserve hook order.

## Detail sub-views

Expand Down
Loading
Loading