Skip to content

Commit ea94cdf

Browse files
committed
chore(platform): drop the dead schedule client layer and repair stale rule and skill docs
Follow-up cleanup for the platform commit, which removed the workspace scheduled-tasks surface and migrated off lucide-react. Both left dead tails that type-check clean, so nothing flagged them. Six mutation hooks in hooks/queries/schedules.ts lost their only consumer when the scheduled-tasks page was deleted: useDisableSchedule, useResumeSchedule, useDeleteSchedule, useExcludeOccurrence, useUpdateSchedule, useCreateSchedule. They are removed along with the three contract objects that served only them — disableScheduleContract, excludeOccurrenceContract, deleteScheduleContract. disableScheduleBodySchema and excludeOccurrenceBodySchema are deliberately kept: both are members of scheduleUpdateSchema, the discriminated union the live PUT /api/schedules/[id] route parses. Dropping them would collapse the union and 400 the disable and exclude_occurrence actions. The schedule-calendar tree and its utils stay unmounted for later reuse. Its TSDoc now says so, since it has no importer and would otherwise read as dead code on the next sweep. The add-enrichment skill templated an import from lucide-react, a dependency the platform commit deleted, so running it produced an unresolvable import. It now points at @sim/emcn/icons, matching all five shipped enrichments. The emcn-design-review skill and several rule files still pointed at apps/sim/components/emcn/**, which moved to packages/emcn/**. Also corrects the documented Chip variant list — it advertised a ghost variant that never existed and omitted border — repoints the sim-url-state date-parser example at an inline snippet now that its source file is gone, and normalizes the one strokeWidth the icon migration left at 1.5 in bubble-chat-delay.
1 parent cbe6789 commit ea94cdf

16 files changed

Lines changed: 47 additions & 287 deletions

File tree

.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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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`. 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`.
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-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`.

.cursor/rules/sim-styling.mdc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ Value text `--text-body`; muted/placeholder/labels `--text-muted`; icons `--text
5050

5151
## Chip Components (consumer usage)
5252

53-
`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.
53+
`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.
5454

5555
### Props over className
5656

0 commit comments

Comments
 (0)