Skip to content

Commit 93c6320

Browse files
committed
Merge remote-tracking branch 'origin/staging' into feat/func-cli-resolver
# Conflicts: # apps/sim/background/schedule-execution.test.ts # apps/sim/background/schedule-execution.ts # apps/sim/lib/copilot/chat/workspace-context.ts
2 parents 6a257db + 9b9da81 commit 93c6320

482 files changed

Lines changed: 3177 additions & 9161 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/add-enrichment/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ Why it matters: the cascade runner only bills (and only reads `output.cost.total
6363
Create `apps/sim/enrichments/{name}/{name}.ts` and a barrel `index.ts`. Mirror the existing entries (`work-email`, `phone-number`, `company-domain`, `company-info`).
6464

6565
```typescript
66-
import { SomeIcon } from 'lucide-react'
66+
import { SomeIcon } from '@sim/emcn/icons'
6767
import { filterUndefined } from '@sim/utils/object'
6868
import { normalizeDomain, splitName, str, toolProvider } from '@/enrichments/providers'
6969
import type { EnrichmentConfig } from '@/enrichments/types'
@@ -109,7 +109,7 @@ export { myEnrichment } from './my-enrichment'
109109
```
110110

111111
Rules:
112-
- Keep the file **client-safe**: import only `lucide-react`, `@sim/utils/*`, `@/enrichments/providers`, and the types. **Never import `@/tools`** here — the runner does the tool call.
112+
- Keep the file **client-safe**: import only `@sim/emcn/icons`, `@sim/utils/*`, `@/enrichments/providers`, and the types. **Never import `@/tools`** here — the runner does the tool call.
113113
- `buildParams` returns `null` when inputs are insufficient (provider skipped). `mapOutput` returns `null`/empty for a miss (falls through). Use `filterUndefined` when assembling optional tool params; coerce numbers explicitly (don't pass `''` to number outputs).
114114
- Output `id`s are the keys `mapOutput` returns; output `name`s are the default column names (the user can rename them in the config).
115115

.agents/skills/emcn-design-review/SKILL.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ This codebase uses **emcn**, a custom component library built on Radix UI primit
1818

1919
## Steps
2020

21-
1. Read the emcn public barrel at `apps/sim/components/emcn/index.ts` (re-exports components, Calendar, Table*, and icons) to know what's available; for the full icon set read `apps/sim/components/emcn/icons/index.ts`
21+
1. Read the emcn public barrel at `packages/emcn/src/index.ts` (re-exports components, Calendar, Table*, and icons) to know what's available; for the full icon set read `packages/emcn/src/icons/index.ts`
2222
2. Read `apps/sim/app/_styles/globals.css` for CSS variable tokens
2323
3. Analyze the specified scope against every rule below
2424
4. If fix=true, apply the fixes. If fix=false, propose the fixes without applying.
@@ -28,7 +28,7 @@ This codebase uses **emcn**, a custom component library built on Radix UI primit
2828
## Imports
2929

3030
- Import from `@/components/emcn` barrel, never subpaths
31-
- Icons from `@/components/emcn/icons` or `lucide-react`
31+
- Icons from `@sim/emcn/icons`
3232
- Use `cn` from `@/lib/core/utils/cn` for conditional classes
3333

3434
## Design Tokens
@@ -45,7 +45,7 @@ Use CSS variable pattern (`text-[var(--text-primary)]`), never Tailwind semantic
4545

4646
## Buttons
4747

48-
Intent-to-variant mapping (read the actual `buttonVariants` in `apps/sim/components/emcn/components/button/button.tsx` for the full variant set — it exposes more than listed here):
48+
Intent-to-variant mapping (read the actual `buttonVariants` in `packages/emcn/src/components/button/button.tsx` for the full variant set — it exposes more than listed here):
4949

5050
| Action | Variant |
5151
|--------|---------|

.claude/commands/add-enrichment.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ Why it matters: the cascade runner only bills (and only reads `output.cost.total
6262
Create `apps/sim/enrichments/{name}/{name}.ts` and a barrel `index.ts`. Mirror the existing entries (`work-email`, `phone-number`, `company-domain`, `company-info`).
6363

6464
```typescript
65-
import { SomeIcon } from 'lucide-react'
65+
import { SomeIcon } from '@sim/emcn/icons'
6666
import { filterUndefined } from '@sim/utils/object'
6767
import { normalizeDomain, splitName, str, toolProvider } from '@/enrichments/providers'
6868
import type { EnrichmentConfig } from '@/enrichments/types'
@@ -108,7 +108,7 @@ export { myEnrichment } from './my-enrichment'
108108
```
109109

110110
Rules:
111-
- Keep the file **client-safe**: import only `lucide-react`, `@sim/utils/*`, `@/enrichments/providers`, and the types. **Never import `@/tools`** here — the runner does the tool call.
111+
- Keep the file **client-safe**: import only `@sim/emcn/icons`, `@sim/utils/*`, `@/enrichments/providers`, and the types. **Never import `@/tools`** here — the runner does the tool call.
112112
- `buildParams` returns `null` when inputs are insufficient (provider skipped). `mapOutput` returns `null`/empty for a miss (falls through). Use `filterUndefined` when assembling optional tool params; coerce numbers explicitly (don't pass `''` to number outputs).
113113
- Output `id`s are the keys `mapOutput` returns; output `name`s are the default column names (the user can rename them in the config).
114114

.claude/commands/emcn-design-review.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ This codebase uses **emcn**, a custom component library built on Radix UI primit
1717

1818
## Steps
1919

20-
1. Read the emcn public barrel at `apps/sim/components/emcn/index.ts` (re-exports components, Calendar, Table*, and icons) to know what's available; for the full icon set read `apps/sim/components/emcn/icons/index.ts`
20+
1. Read the emcn public barrel at `packages/emcn/src/index.ts` (re-exports components, Calendar, Table*, and icons) to know what's available; for the full icon set read `packages/emcn/src/icons/index.ts`
2121
2. Read `apps/sim/app/_styles/globals.css` for CSS variable tokens
2222
3. Analyze the specified scope against every rule below
2323
4. If fix=true, apply the fixes. If fix=false, propose the fixes without applying.
@@ -27,7 +27,7 @@ This codebase uses **emcn**, a custom component library built on Radix UI primit
2727
## Imports
2828

2929
- Import from `@/components/emcn` barrel, never subpaths
30-
- Icons from `@/components/emcn/icons` or `lucide-react`
30+
- Icons from `@sim/emcn/icons`
3131
- Use `cn` from `@/lib/core/utils/cn` for conditional classes
3232

3333
## Design Tokens
@@ -44,7 +44,7 @@ Use CSS variable pattern (`text-[var(--text-primary)]`), never Tailwind semantic
4444

4545
## Buttons
4646

47-
Intent-to-variant mapping (read the actual `buttonVariants` in `apps/sim/components/emcn/components/button/button.tsx` for the full variant set — it exposes more than listed here):
47+
Intent-to-variant mapping (read the actual `buttonVariants` in `packages/emcn/src/components/button/button.tsx` for the full variant set — it exposes more than listed here):
4848

4949
| Action | Variant |
5050
|--------|---------|

.claude/rules/emcn-components.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
paths:
3-
- "apps/sim/components/emcn/**"
3+
- "packages/emcn/**"
44
---
55

66
# EMCN Components
@@ -20,7 +20,7 @@ The menu surface intentionally diverges from the pill: `dropdown-menu.tsx` items
2020

2121
## Component catalogue
2222

23-
- **`Chip` / `ChipLink`** — the pill button (`<button>` / Next `<Link>`). Variants: `ghost`, `filled`, `primary`, `destructive`, `border-shadow`. `leftIcon`/`rightIcon`, `active`, `fullWidth`, `flush`.
23+
- **`Chip` / `ChipLink`** — the pill button (`<button>` / Next `<Link>`). Variants: `primary`, `destructive`, `border-shadow`, `border`; the bare chip is implicit (omit `variant`). `filled` is deliberately NOT a `Chip` variant — it is reserved for chip fields/triggers. For a selected/toggle chip use the `active` prop, never a variant. `leftIcon`/`rightIcon`, `active`, `fullWidth`. Chips carry **no outer margin** — space between them is the parent's `gap`. The old `mx-0.5` default and its `flush` opt-out are gone; do not reintroduce either, and never add a margin to a chip through `className`.
2424
- **`ChipInput`** — single-line text field. `icon`, `endAdornment`, `error`, `inputClassName` (inner `<input>`); `className` styles the chrome wrapper.
2525
- **`ChipCopyInput`** — the canonical view-only field: a read-only `ChipInput` at full opacity with a trailing copy-to-clipboard button. View-only is a display mode, not a disabled state — reach for it (or `ChipModalField type='copy'`) over a `disabled` (greyed) input for values the user cannot edit.
2626
- **`ChipTextarea`** — multi-line sibling. `error`, `resizable` (off by default), `viewOnly` (read-only at full opacity with the default cursor — the multi-line counterpart of `ChipCopyInput`).

.claude/rules/sim-styling.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,29 @@ Custom font sizes (`apps/sim/tailwind.config.ts`): `text-micro`=10px, `text-xs`=
5050

5151
Icons default `size-[14px]`. Equal h/w → `size-*` (`size-[14px]`, `size-4`), never `h-N w-N`.
5252

53+
## Font Weight
54+
55+
Three steps, Tailwind's stock scale, nothing else: **`font-normal` (400)**, **`font-medium` (500)**, **`font-semibold` (600)**. 400 is the document default, so body text, chip labels, sidebar items, and headings carry **no weight class at all** — they inherit. Reach for a class only to step *up* from body.
56+
57+
Never write an arbitrary weight (`font-[380]`, `font-[430]`, `font-[450]`, …), and never set `fontWeight` in an inline `style`. There was previously a CSS-variable weight scale (`--font-weight-base/medium/semibold`, remapping `font-medium` to 440/480) plus seven ad-hoc values clustered between 380 and 500; it was deleted because nothing read as hierarchical. Off-scale values are only acceptable where the design system genuinely cannot reach — react-email templates and the static `apps/sim/emails/broadcasts/*.html`, which email clients render without CSS variables.
58+
59+
Headings inherit their weight. Tailwind preflight resets `h1``h6` to `font-weight: inherit`, so an `<h1>` is 400 unless you say otherwise — that is the intended look, not a bug to patch.
60+
5361
## Color Tokens
5462

55-
Value text `--text-body`; muted/placeholder/labels `--text-muted`; icons `--text-icon`; borders `--border-1` (fields) / `--border` (dividers); surfaces `--surface-5` (light) / `--surface-4` (dark); active row `--surface-active`; error `--text-error`. No focus rings on chip surfaces.
63+
Value text `--text-body`; muted/placeholder/labels `--text-muted`; icons `--text-icon`; neutral borders and dividers `--border` (`--border-1` and `--border-muted` are legacy aliases resolving to it; `--divider` is retired); surfaces `--surface-5` (light) / `--surface-4` (dark); active row `--surface-active`; error `--text-error`. No focus rings on chip surfaces.
64+
65+
### Line weight
66+
67+
Neutral border geometry comes from `--border-width`: `1px` by default, dropping to `0.5px` under `@media (min-resolution: 2dppx)` so hidpi displays get a true hairline. Tailwind's `border*` and `divide-*` utilities resolve through it, as do `h-px`/`w-px` — the `px` key is overridden on **`spacing`**, not on `width`/`height`, so a hairline and the `-right-px`/`inset-px` offsets that position it stay in agreement.
68+
69+
**Tune line weight on `--border`, never on `--border-width`.** Browsers floor a border to whole device pixels, so on a 2dppx display every value in `(0, 1px)` collapses to the same single-pixel hairline and the next drawable step is a full `1px` — double. Width has exactly one usable position; perceived weight is a color property. Light mode gains weight by darkening `--border`, dark mode by lightening it.
70+
71+
Draw a line with a real `border-*` utility. Never hand-roll one as `shadow-[inset_0_-1px_0_…]` — box-shadow has its own width and cannot follow the token, so such a line silently renders at double weight against every neighbor. Use an explicit numeric width (or a `ring`/`outline`) only when the line is intentionally emphasized, e.g. focus and selection affordances.
5672

5773
## Chip Components (consumer usage)
5874

59-
`ChipInput`, `ChipTextarea`, `ChipModal*` own their full chrome. Consumers describe intent through PROPS; they never re-style the chrome. The canonical chrome lives in `apps/sim/components/emcn/components/chip/chip-chrome.ts` (all tokens are re-exported from the `@sim/emcn` barrel — no subpath import needed) — never hand-roll `rounded-lg`/`border`/`bg-[var(--surface-5)]`/`h-[30px]`/`px-2`/`text-sm`/focus rings.
75+
`ChipInput`, `ChipTextarea`, `ChipModal*` own their full chrome. Consumers describe intent through PROPS; they never re-style the chrome. The canonical chrome lives in `packages/emcn/src/components/chip/chip-chrome.ts` (all tokens are re-exported from the `@sim/emcn` barrel — no subpath import needed) — never hand-roll `rounded-lg`/`border`/`bg-[var(--surface-5)]`/`h-[30px]`/`px-2`/`text-sm`/focus rings.
6076

6177
### Props over className
6278

.claude/rules/sim-url-state.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,22 @@ Sort params live alongside — not inside — the feature's grouped filter parse
187187

188188
A date-only param (a calendar anchor, a date filter) is stored as `yyyy-MM-dd` — never serialize a full `Date`/timestamp when only the day matters.
189189

190-
**Local vs UTC — pick the parser that matches your date math.** nuqs's built-in `parseAsIsoDate` is **UTC-based** (`serialize` via `toISOString().slice(0, 10)`, `parse` to UTC midnight). If your `Date` is local-time (e.g. produced by local-time helpers and read by `date-fns` `startOfWeek`/`isSameDay`, which are all local), `parseAsIsoDate` will shift the day by ±1 in any non-UTC timezone on reload/deep-link/back-forward. For local-time date math, use a small local-date `createParser` that serializes/parses on local calendar fields (`getFullYear`/`getMonth`/`getDate``new Date(y, m-1, d)`) with an `eq` comparing y/m/d. Only use `parseAsIsoDate` when the value is genuinely UTC/midnight-UTC. See `scheduled-tasks/search-params.ts` (`parseAsLocalDate`).
190+
**Local vs UTC — pick the parser that matches your date math.** nuqs's built-in `parseAsIsoDate` is **UTC-based** (`serialize` via `toISOString().slice(0, 10)`, `parse` to UTC midnight). If your `Date` is local-time (e.g. produced by local-time helpers and read by `date-fns` `startOfWeek`/`isSameDay`, which are all local), `parseAsIsoDate` will shift the day by ±1 in any non-UTC timezone on reload/deep-link/back-forward. For local-time date math, use a small local-date `createParser` that serializes/parses on local calendar fields (`getFullYear`/`getMonth`/`getDate``new Date(y, m-1, d)`) with an `eq` comparing y/m/d. Only use `parseAsIsoDate` when the value is genuinely UTC/midnight-UTC.
191191

192-
When the default is **dynamic** (e.g. "today"), make the param **nullable** (omit `.withDefault`) and derive the fallback in the hook (`const anchor = param ?? today`), so a clean URL means the dynamic default and navigating back to it writes `null` (clears the param). See `scheduled-tasks/hooks/use-calendar.ts`.
192+
```typescript
193+
const parseAsLocalDate = createParser({
194+
parse: (v) => {
195+
const [y, m, d] = v.split('-').map(Number)
196+
return y && m && d ? new Date(y, m - 1, d) : null
197+
},
198+
serialize: (v) =>
199+
`${v.getFullYear()}-${String(v.getMonth() + 1).padStart(2, '0')}-${String(v.getDate()).padStart(2, '0')}`,
200+
eq: (a, b) =>
201+
a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate(),
202+
})
203+
```
204+
205+
When the default is **dynamic** (e.g. "today"), make the param **nullable** (omit `.withDefault`) and derive the fallback in the hook (`const anchor = param ?? today`), so a clean URL means the dynamic default and navigating back to it writes `null` (clears the param).
193206

194207
## Selected-entity deep-link (store the id, derive the object)
195208

.cursor/commands/add-enrichment.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ Why it matters: the cascade runner only bills (and only reads `output.cost.total
5757
Create `apps/sim/enrichments/{name}/{name}.ts` and a barrel `index.ts`. Mirror the existing entries (`work-email`, `phone-number`, `company-domain`, `company-info`).
5858

5959
```typescript
60-
import { SomeIcon } from 'lucide-react'
60+
import { SomeIcon } from '@sim/emcn/icons'
6161
import { filterUndefined } from '@sim/utils/object'
6262
import { normalizeDomain, splitName, str, toolProvider } from '@/enrichments/providers'
6363
import type { EnrichmentConfig } from '@/enrichments/types'
@@ -103,7 +103,7 @@ export { myEnrichment } from './my-enrichment'
103103
```
104104

105105
Rules:
106-
- Keep the file **client-safe**: import only `lucide-react`, `@sim/utils/*`, `@/enrichments/providers`, and the types. **Never import `@/tools`** here — the runner does the tool call.
106+
- Keep the file **client-safe**: import only `@sim/emcn/icons`, `@sim/utils/*`, `@/enrichments/providers`, and the types. **Never import `@/tools`** here — the runner does the tool call.
107107
- `buildParams` returns `null` when inputs are insufficient (provider skipped). `mapOutput` returns `null`/empty for a miss (falls through). Use `filterUndefined` when assembling optional tool params; coerce numbers explicitly (don't pass `''` to number outputs).
108108
- Output `id`s are the keys `mapOutput` returns; output `name`s are the default column names (the user can rename them in the config).
109109

.cursor/commands/emcn-design-review.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ This codebase uses **emcn**, a custom component library built on Radix UI primit
1212

1313
## Steps
1414

15-
1. Read the emcn public barrel at `apps/sim/components/emcn/index.ts` (re-exports components, Calendar, Table*, and icons) to know what's available; for the full icon set read `apps/sim/components/emcn/icons/index.ts`
15+
1. Read the emcn public barrel at `packages/emcn/src/index.ts` (re-exports components, Calendar, Table*, and icons) to know what's available; for the full icon set read `packages/emcn/src/icons/index.ts`
1616
2. Read `apps/sim/app/_styles/globals.css` for CSS variable tokens
1717
3. Analyze the specified scope against every rule below
1818
4. If fix=true, apply the fixes. If fix=false, propose the fixes without applying.
@@ -22,7 +22,7 @@ This codebase uses **emcn**, a custom component library built on Radix UI primit
2222
## Imports
2323

2424
- Import from `@/components/emcn` barrel, never subpaths
25-
- Icons from `@/components/emcn/icons` or `lucide-react`
25+
- Icons from `@sim/emcn/icons`
2626
- Use `cn` from `@/lib/core/utils/cn` for conditional classes
2727

2828
## Design Tokens
@@ -39,7 +39,7 @@ Use CSS variable pattern (`text-[var(--text-primary)]`), never Tailwind semantic
3939

4040
## Buttons
4141

42-
Intent-to-variant mapping (read the actual `buttonVariants` in `apps/sim/components/emcn/components/button/button.tsx` for the full variant set — it exposes more than listed here):
42+
Intent-to-variant mapping (read the actual `buttonVariants` in `packages/emcn/src/components/button/button.tsx` for the full variant set — it exposes more than listed here):
4343

4444
| Action | Variant |
4545
|--------|---------|

.cursor/rules/emcn-components.mdc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
description: EMCN component library patterns
3-
globs: ["apps/sim/components/emcn/**"]
3+
globs: ["packages/emcn/**"]
44
---
55
# EMCN Components
66

@@ -19,7 +19,7 @@ The menu surface intentionally diverges from the pill: `dropdown-menu.tsx` items
1919

2020
## Component catalogue
2121

22-
- **`Chip` / `ChipLink`** — the pill button (`<button>` / Next `<Link>`). Variants: `ghost`, `filled`, `primary`, `destructive`, `border-shadow`. `leftIcon`/`rightIcon`, `active`, `fullWidth`, `flush`.
22+
- **`Chip` / `ChipLink`** — the pill button (`<button>` / Next `<Link>`). Variants: `primary`, `destructive`, `border-shadow`, `border`; the bare chip is implicit (omit `variant`). `filled` is deliberately NOT a `Chip` variant — it is reserved for chip fields/triggers. For a selected/toggle chip use the `active` prop, never a variant. `leftIcon`/`rightIcon`, `active`, `fullWidth`. Chips carry **no outer margin** — space between them is the parent's `gap`. The old `mx-0.5` default and its `flush` opt-out are gone; do not reintroduce either, and never add a margin to a chip through `className`.
2323
- **`ChipInput`** — single-line text field. `icon`, `endAdornment`, `error`, `inputClassName` (inner `<input>`); `className` styles the chrome wrapper.
2424
- **`ChipTextarea`** — multi-line sibling. `error`, `resizable` (off by default).
2525
- **`ChipDropdown`** — pill that opens a menu. Single OR multi-select via the discriminated `multiple` prop (one component, not two). Owns its trailing chevron — no `rightIcon`.

0 commit comments

Comments
 (0)