Skip to content

Commit b5a30e9

Browse files
committed
refactor(emcn): consolidate shared UI and platform refinements
Move modern shared controls into EMCN and surface compositions into Auth, Docs, and Platform packages. Preserve existing application consumers through emcn-legacy and migrate imports, generators, audits, styles, fonts, and CI together. Consolidate integration details, credentials, modal fields, responsive people tables, destructive actions, and disabled explanations. Record the combined local handoff and verification evidence. Validation: repository lint, types, 67 audits, complete 20-task test gate, Platform build, block registry, browser regressions, and actual Electron checks passed. Production-runtime and fixture-off verification of the shipping commit remains a separate pre-publish step.
1 parent cf841e5 commit b5a30e9

2,479 files changed

Lines changed: 16380 additions & 12757 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-column-type/SKILL.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ Decide what a cell literally holds in `user_table_rows.data` (JSONB). This drive
5050

5151
## Step 2: Add the icon
5252

53-
Create `packages/emcn/src/icons/type-{name}.tsx`, copying the geometry conventions of its siblings exactly:
53+
Create `packages/emcn-legacy/src/icons/type-{name}.tsx`, copying the geometry conventions of its siblings exactly:
5454

5555
```tsx
5656
import type { SVGProps } from 'react'
@@ -82,7 +82,7 @@ export function Type{Pascal}(props: SVGProps<SVGSVGElement>) {
8282

8383
- `viewBox='-1.75 -1.5 24 24'` is the **`type-*` family** value, not the set-wide default. Match the family.
8484
- Center the glyph on the viewBox's optical center (**y = 10.5**, **x = 10.25**) — every sibling does, and a few tenths off is visible at `size-[14px]`.
85-
- Export alphabetically **by component name** in `packages/emcn/src/icons/index.ts`.
85+
- Export alphabetically **by component name** in `packages/emcn-legacy/src/icons/index.ts`.
8686

8787
## Step 3: Write the type file
8888

@@ -118,7 +118,7 @@ Prefer set-based SQL. When the transform genuinely needs JS (`currency`'s separa
118118

119119
- **Import cycles.** `column-types/select.ts` imports `lib/table/select-values.ts`, so `select-values.ts` must **not** import the registry — that closes a cycle and fails at module init. Inside a type's own helper module the string literal is the implementation, not a config leak.
120120
- **The client-safe boundary.** `registry.ts` and everything it imports must stay free of `@sim/db`, `drizzle-orm`, and `next/server` — the tables grid imports it directly. A React icon is fine (it's a component *reference*, never called server-side). Only `registry.server.ts` may touch drizzle.
121-
- **Don't re-export the registry from `@/lib/table`.** Dozens of server modules import that barrel; routing this through it pulls `@sim/emcn/icons` into all of them. Deep-import `@/lib/table/column-types`.
121+
- **Don't re-export the registry from `@/lib/table`.** Dozens of server modules import that barrel; routing this through it pulls `@sim/emcn-legacy/icons` into all of them. Deep-import `@/lib/table/column-types`.
122122
- **`import.ts`'s `coerceValue` is a SECOND write path and is not opt-in.** Importing into a column of your type always hits it, and its `default` arm silently `String(value)`s — so a missing `case` stores text in a column whose `jsonbCast` is numeric, and then every filter and sort on that column errors in Postgres. Add a `case`, even though the switch compiles without one. (It is deliberately separate from the registry's `coerce`: an import wants an unparseable value to survive as its raw string so the row error can name it.)
123123
- **CSV inference** is an ordered heuristic in `import.ts`, deliberately not registry-driven. A new type is not inferred from a CSV unless you extend `inferColumnType` — usually you should not, since inference cannot supply configuration (an option set, a currency code).
124124

‎.agents/skills/add-enrichment/SKILL.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ Why it matters: the cascade runner only bills (and only reads `output.cost.total
6565
Create `apps/sim/enrichments/{id}/{id}.ts` and a barrel `index.ts`. Mirror the entries registered in `enrichments/registry.ts`.
6666

6767
```typescript
68-
import { SomeIcon } from '@sim/emcn/icons'
68+
import { SomeIcon } from '@sim/emcn-legacy/icons'
6969
import { filterUndefined } from '@sim/utils/object'
7070
import { normalizeDomain, splitName, str, toolProvider } from '@/enrichments/providers'
7171
import type { EnrichmentConfig } from '@/enrichments/types'
@@ -111,7 +111,7 @@ export { myEnrichment } from './my-enrichment'
111111
```
112112

113113
Rules:
114-
- 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.
114+
- Keep the file **client-safe**: import only `@sim/emcn-legacy/icons`, `@sim/utils/*`, `@/enrichments/providers`, and the types. **Never import `@/tools`** here — the runner does the tool call.
115115
- `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).
116116
- Output `id`s are the keys `mapOutput` returns; output `name`s are the default column names (the user can rename them in the config).
117117

‎.agents/skills/design-taste-frontend/SKILL.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ source: https://github.com/leonxlnx/taste-skill — skills/taste-skill/SKILL.md
44
description: Anti-slop frontend skill for landing pages, portfolios, and redesigns. The agent reads the brief, infers the right design direction, and ships interfaces that do not look templated. Real design systems when applicable, audit-first on redesigns, strict pre-flight check.
55
---
66

7-
> **In this repo:** Tailwind 4 (CSS-first config in `apps/sim/app/_styles/globals.css`); animation via `import { motion } from 'framer-motion'` (not `motion/react`); icons from `@sim/emcn/icons`; colors through the CSS-variable tokens in `.claude/rules/sim-styling.md` (no hardcoded `text-gray-*`/hex/`zinc` utilities, no paired `dark:` utilities). This note overrides any conflicting guidance or code sample anywhere in this file. Fonts are fixed (Season body, Inter); never introduce new families, and never use Martian Mono on landing (`apps/sim/app/(landing)/CLAUDE.md`). Font weight is only `font-normal`/`font-medium`/`font-semibold`. Elevation uses the `shadow-subtle|medium|overlay|card` tokens. Type size uses named tokens, never `text-[Npx]`. Every labeled field inside a `ChipModalBody` is a `ChipModalField`. Use `bunx`, never `npx`. Do not add GSAP, Lenis, Three, or shadcn. On landing pages, motion is CSS first; an animation library stays out of the initial bundle and loads below the fold through `next/dynamic` (`apps/sim/app/(landing)/CLAUDE.md`). Landing copy and SEO follow `.claude/rules/constitution.md` and `.claude/rules/landing-seo-geo.md`.
7+
> **In this repo:** Tailwind 4 (CSS-first config in `apps/sim/app/_styles/globals.css`); animation via `import { motion } from 'framer-motion'` (not `motion/react`); icons from `@sim/emcn-legacy/icons`; colors through the CSS-variable tokens in `.claude/rules/sim-styling.md` (no hardcoded `text-gray-*`/hex/`zinc` utilities, no paired `dark:` utilities). This note overrides any conflicting guidance or code sample anywhere in this file. Fonts are fixed (Season body, Inter); never introduce new families, and never use Martian Mono on landing (`apps/sim/app/(landing)/CLAUDE.md`). Font weight is only `font-normal`/`font-medium`/`font-semibold`. Elevation uses the `shadow-subtle|medium|overlay|card` tokens. Type size uses named tokens, never `text-[Npx]`. Every labeled field inside a `ChipModalBody` is a `ChipModalField`. Use `bunx`, never `npx`. Do not add GSAP, Lenis, Three, or shadcn. On landing pages, motion is CSS first; an animation library stays out of the initial bundle and loads below the fold through `next/dynamic` (`apps/sim/app/(landing)/CLAUDE.md`). Landing copy and SEO follow `.claude/rules/constitution.md` and `.claude/rules/landing-seo-geo.md`.
88

99
# tasteskill: Anti-Slop Frontend Skill
1010

@@ -141,7 +141,7 @@ Unless the design read picks a real design system (Section 2.A), these are the d
141141
* **NEVER** use `useState` to track continuous values driven by user input (mouse position, scroll progress, pointer physics, magnetic hover). Use Motion's `useMotionValue` / `useTransform` / `useScroll`. `useState` re-renders the React tree on every change and collapses on mobile.
142142

143143
### 3.C Icons
144-
* **Icons:** in this repo, `@sim/emcn/icons` only — one family per tree, `strokeWidth` standardized. Outside this repo, pick one maintained library and standardize on it.
144+
* **Icons:** in this repo, `@sim/emcn-legacy/icons` only — one family per tree, `strokeWidth` standardized. Outside this repo, pick one maintained library and standardize on it.
145145

146146
### 3.D Emoji Policy
147147
Discouraged by default in code, markup, and visible text. Replace symbols with icon-library glyphs. **Override:** allow emojis only when the user explicitly asks for a playful / chat-style / social-native vibe - and even then use them sparingly with intent.

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ User arguments: $ARGUMENTS
1414

1515
## Context
1616

17-
The existing Sim app uses `packages/emcn`, its Radix primitives, CVA variants, and CSS tokens. For `apps/sim/platform/**`, use [implement-platform](../implement-platform/SKILL.md). For mixed scopes, review each file under its owning system and preserve the requested `fix` mode for both.
17+
The existing Sim app uses `packages/emcn-legacy`, its Radix primitives, CVA variants, and CSS tokens. For `apps/sim/platform/**`, use [implement-platform](../implement-platform/SKILL.md). For mixed scopes, review each file under its owning system and preserve the requested `fix` mode for both.
1818

1919
## Steps
2020

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`
21+
1. Read the emcn public barrel at `packages/emcn-legacy/src/index.ts` (re-exports components, Calendar, Table*, and icons) to know what's available; for the full icon set read `packages/emcn-legacy/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.
@@ -27,8 +27,8 @@ The existing Sim app uses `packages/emcn`, its Radix primitives, CVA variants, a
2727

2828
## Imports
2929

30-
- Components, `cn`, and tokens from the `@sim/emcn` barrel, never component subpaths
31-
- Icons from `@sim/emcn/icons`
30+
- Components, `cn`, and tokens from the `@sim/emcn-legacy` barrel, never component subpaths
31+
- Icons from `@sim/emcn-legacy/icons`
3232

3333
## Design Tokens
3434

@@ -52,7 +52,7 @@ Use `ChipConfirmModal` (title "Delete/Remove {ItemType}", `confirm={{ label, onC
5252

5353
## Toast
5454

55-
`toast.success()`, `toast.error()`, `toast()` from `@sim/emcn`. Never custom notification UI.
55+
`toast.success()`, `toast.error()`, `toast()` from `@sim/emcn-legacy`. Never custom notification UI.
5656

5757
## Badges
5858

‎.agents/skills/implement-platform/SKILL.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Start in the Sim checkout containing the requested product work. Read the [Platf
1010
1. **Establish scope on the real route.** Identify the product entry, interaction, phase, and affected consumers. When rebuilding an existing workflow, trace the old navigation target, its access gate, and the actions reachable by that viewer. Use that evidence to decide which controls belong on the new page before consulting the broader API or provider catalog. Phase 1 owns foundations and the library. Phase 2 owns working UI and transient interaction state, with examples supplied through the server fixture flag. Phase 3 connects real data and operations. Reuse the same renderer in the browser and Sim Desktop. Read the installed Next guides for the file structure or framework behavior you are changing.
1111
For organization Settings, inventory the old sidebar in order, its viewer/deployment gates and every action reachable from each section. Map old header buttons to the row or section they act on. Verify the same destination and drilldown on the fixture and authenticated routes; keep real writes outside fixture sessions.
1212
2. **Resolve design intent.** For Paper-backed work, use `$sim-paper-design` to locate the live Shared or Platform master and the product states that use it. Exclude Marcus. Preserve the key and theme roles. Treat artboard sizes as reference measurements. For code-first changes, follow the latest explicit product direction and inspect the rendered route. Identify any source you could not verify. Update the Paper canvas when the request includes Paper changes.
13-
3. **Choose or change the owner.** Start with the behavior. An action, navigation row, value picker, or disclosure has an existing keyboard and pointer contract. Different interactions may share visual roles while retaining different semantics. Use the existing family and named props for a change in size, intent, icon, or content. Toolbar choices use ChoiceMenu, as Home's period does; Select/SelectField belong to forms and settings. Compare the rendered trigger, not just its variant name. Put unique anatomy and its CSS together in `_components/<component>/<component>.tsx` and `<component>.module.css`. Match an existing semantic rhythm, such as Home's ActivityRow, for a custom composition. Keep page files free of styling. Only EMCN owns the appearance of its controls. Use Base UI there for complex keyboard, floating, and dismissal behavior.
13+
3. **Choose or change the owner.** Shared controls and foundations belong to `packages/emcn`; Platform-specific compositions belong to `packages/emcn-platform`. Auth and Docs compose the same Shared primitives through their own packages. Use public family subpaths, colocated CSS Modules and the single scoped style entry for each surface. Keep `@sim/emcn-legacy` outside the modern package graph. Start with the behavior. An action, navigation row, value picker, or disclosure has an existing keyboard and pointer contract. Different interactions may share visual roles while retaining different semantics. Use the existing family and named props for a change in size, intent, icon, or content. Toolbar choices use ChoiceMenu, as Home's period does; Select/SelectField belong to labeled forms. Immediate preferences, row roles and toolbar filters use compact text triggers without borders or chevrons. Compare the rendered trigger, not just its variant name. Put unique anatomy and its CSS together in `_components/<component>/<component>.tsx` and `<component>.module.css`. Match an existing semantic rhythm, such as Home's ActivityRow, for a custom composition. Keep page files free of styling. Only EMCN owns the appearance of its controls. Use Base UI there for complex keyboard, floating, and dismissal behavior.
1414
4. **Trace the full change.** On a second independent feature use, promote the original implementation and migrate both callers. For consolidation, compare semantics, map every consumer to its replacement, then remove the obsolete implementation, export, variant styles, and unused registrations. For deletion, also check menus, preferences, fixture data, workbench references, and tests that existed only for the removed feature. Preserve unrelated consumers and historical Paper evidence. Before adding a shared visual variant, name at least two independent real consumers. A single feature composes the existing primitives in its local owner; a label, icon, data value or responsive arrangement does not justify another variant. Keep the public API small enough to understand at the call site. Edit the source or compiler for generated foundations and recipes.
1515
5. **Verify where people use it.** Run the design audit and applicable checks from the README. Render the changed product route with empty, full, stress, and fixture-off data as relevant. Check both themes, widths between artboards, long content, text scaling, keyboard, and pointer states. Compare shared controls in their actual consumers. Check the actual scroll edge and the open popup when space is tight. For shell, panel, or desktop work, exercise the real Electron renderer. For substantial implementations and consolidations, use an independent agent during design or implementation and for a final review of the changed owners and routes. Reuse the single review server at localhost:3125. Check its process working directory and branch before starting a server or moving work. Separate task worktrees do not update that preview until reconciled into its checkout. Provide the working route for visual review.
1616
6. **Keep decisions durable.** Follow the contract’s maintenance guidance when an approved correction changes a shared rule. Record feature-specific decisions with their feature. For sustained work, keep a task checkpoint with the code revision, verified states, evidence, and outstanding work. Include the branch or PR, checkpoint path, and localhost route in a handoff. On resumption, compare the checkpoint with the current branch, working tree, and relevant live sources before acting.

‎.agents/skills/make-interfaces-feel-better/SKILL.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ Add a subtle 1px low-opacity outline to images; see surfaces.md. In this repo, u
6565

6666
### 12. Scale on Press
6767

68-
A subtle scale-down (about 0.96-0.97) on press gives tactile feedback. In this repo a press affordance belongs in the emcn `Button`/`Chip` chrome (`packages/emcn`), not in consumer classes — neither component implements one today, so propose it there rather than adding per-call-site transforms.
68+
A subtle scale-down (about 0.96-0.97) on press gives tactile feedback. In this repo a press affordance belongs in the emcn `Button`/`Chip` chrome (`packages/emcn-legacy`), not in consumer classes — neither component implements one today, so propose it there rather than adding per-call-site transforms.
6969

7070
### 13. Skip Animation on Page Load
7171

@@ -119,7 +119,7 @@ Present changes as markdown tables with **Before** and **After** columns, one ta
119119
#### Scale on press
120120
| Before | After |
121121
| --- | --- |
122-
| `Chip` has no press affordance | Proposed in `packages/emcn/src/components/chip/chip.tsx` (`chipVariants`): `active:scale-[0.96] transition-transform` |
122+
| `Chip` has no press affordance | Proposed in `packages/emcn-legacy/src/components/chip/chip.tsx` (`chipVariants`): `active:scale-[0.96] transition-transform` |
123123
| `scale(0.9)` on press | Raised to `scale(0.96)` — anything below `0.95` feels exaggerated |
124124

125125
Rows should cite the specific file and the specific property that changed when it isn't obvious from the snippet. If a principle was reviewed but nothing needed to change, omit that table entirely — empty tables add noise.

‎.agents/skills/validate-integration/SKILL.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ The integration's page must carry a `{/* MANUAL-CONTENT-START:intro */}` section
460460
`<BlockInfoCard />`. If it is missing, write one using the template in add-integration → Step 8, and
461461
check an existing intro against what the block actually ships (no removed or unshipped operations).
462462

463-
If an icon changed, `apps/sim/components/icons.tsx` is the source of truth and `apps/docs/components/icons.tsx` is its generated mirror — they must end up byte-identical for that component.
463+
If an icon changed, `apps/sim/components/icons.tsx` is the source of truth and `apps/docs/components/icons/icons.tsx` is its generated mirror — they must end up byte-identical for that component.
464464

465465
### Validation Output
466466

0 commit comments

Comments
 (0)