@archetypeai/ds-cli 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +123 -0
- package/bin.js +77 -0
- package/commands/add.js +42 -0
- package/commands/create.js +238 -0
- package/commands/init.js +199 -0
- package/files/AGENTS.md +63 -0
- package/files/CLAUDE.md +63 -0
- package/files/LICENSE +21 -0
- package/files/rules/accessibility.md +219 -0
- package/files/rules/charts.md +352 -0
- package/files/rules/components.md +267 -0
- package/files/rules/design-principles.md +56 -0
- package/files/rules/linting.md +31 -0
- package/files/rules/state.md +405 -0
- package/files/rules/styling.md +245 -0
- package/files/skills/apply-ds/SKILL.md +117 -0
- package/files/skills/apply-ds/scripts/setup.sh +271 -0
- package/files/skills/build-pattern/SKILL.md +202 -0
- package/files/skills/create-dashboard/SKILL.md +189 -0
- package/files/skills/deploy-worker/SKILL.md +231 -0
- package/files/skills/deploy-worker/references/wrangler-commands.md +327 -0
- package/files/skills/fix-accessibility/SKILL.md +184 -0
- package/files/skills/fix-metadata/SKILL.md +118 -0
- package/files/skills/fix-metadata/assets/favicon.ico +0 -0
- package/files/skills/setup-chart/SKILL.md +225 -0
- package/files/skills/setup-chart/data/embedding.csv +42 -0
- package/files/skills/setup-chart/data/timeseries.csv +173 -0
- package/files/skills/setup-chart/references/scatter-chart.md +229 -0
- package/files/skills/setup-chart/references/sensor-chart.md +156 -0
- package/lib/add-ds-config-codeagent.js +154 -0
- package/lib/add-ds-ui-svelte.js +93 -0
- package/lib/scaffold-ds-svelte-project.js +272 -0
- package/lib/use-package-manager.js +65 -0
- package/lib/use-shadcn-svelte-registry.js +26 -0
- package/lib/validate-url.js +31 -0
- package/package.json +34 -0
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
---
|
|
2
|
+
paths:
|
|
3
|
+
- '**/components/**/*.svelte'
|
|
4
|
+
- '$lib/**/*.svelte'
|
|
5
|
+
- '**/primitives/**/*.svelte'
|
|
6
|
+
- '**/patterns/**/*.svelte'
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Component Authoring Rules
|
|
10
|
+
|
|
11
|
+
## Props Pattern
|
|
12
|
+
|
|
13
|
+
Every component should destructure props using `$props()` with this standard pattern:
|
|
14
|
+
|
|
15
|
+
```svelte
|
|
16
|
+
<script>
|
|
17
|
+
import { cn } from '$lib/utils.js';
|
|
18
|
+
|
|
19
|
+
let { ref = $bindable(null), class: className, children, ...restProps } = $props();
|
|
20
|
+
</script>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Key points:
|
|
24
|
+
|
|
25
|
+
- `ref = $bindable(null)` - enables parent to bind to DOM element
|
|
26
|
+
- `class: className` - rename to avoid reserved word conflict
|
|
27
|
+
- `children` - snippet for slot content
|
|
28
|
+
- `...restProps` - capture remaining props for spreading
|
|
29
|
+
|
|
30
|
+
## data-slot Attributes
|
|
31
|
+
|
|
32
|
+
Add `data-slot` to root elements for identification and styling hooks:
|
|
33
|
+
|
|
34
|
+
```svelte
|
|
35
|
+
<div bind:this={ref} data-slot="card" class={cn('bg-card ...', className)} {...restProps}>
|
|
36
|
+
{@render children?.()}
|
|
37
|
+
</div>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
This enables parent styling like `*:data-[slot=card]:p-4`.
|
|
41
|
+
|
|
42
|
+
## Class Merging with cn()
|
|
43
|
+
|
|
44
|
+
Always use `cn()` for class composition - never raw string concatenation:
|
|
45
|
+
|
|
46
|
+
```svelte
|
|
47
|
+
<!-- Correct -->
|
|
48
|
+
<div class={cn('bg-card text-card-foreground', className)}>
|
|
49
|
+
|
|
50
|
+
<!-- Wrong -->
|
|
51
|
+
<div class={`bg-card text-card-foreground ${className}`}>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`cn()` uses clsx + tailwind-merge to properly handle class conflicts.
|
|
55
|
+
|
|
56
|
+
## bits-ui Wrapper Pattern
|
|
57
|
+
|
|
58
|
+
When wrapping bits-ui primitives, import the primitive and wrap it:
|
|
59
|
+
|
|
60
|
+
```svelte
|
|
61
|
+
<script>
|
|
62
|
+
import { Select as SelectPrimitive } from 'bits-ui';
|
|
63
|
+
import { cn } from '$lib/utils.js';
|
|
64
|
+
|
|
65
|
+
let { ref = $bindable(null), class: className, children, ...restProps } = $props();
|
|
66
|
+
</script>
|
|
67
|
+
|
|
68
|
+
<SelectPrimitive.Trigger
|
|
69
|
+
bind:ref
|
|
70
|
+
data-slot="select-trigger"
|
|
71
|
+
class={cn('border-input bg-transparent ...', className)}
|
|
72
|
+
{...restProps}
|
|
73
|
+
>
|
|
74
|
+
{@render children?.()}
|
|
75
|
+
</SelectPrimitive.Trigger>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Common bits-ui primitives:
|
|
79
|
+
|
|
80
|
+
- `Dialog` - Dialog.Root, Dialog.Portal, Dialog.Content, Dialog.Trigger, Dialog.Close
|
|
81
|
+
- `AlertDialog` - AlertDialog.Root, AlertDialog.Trigger, AlertDialog.Content, AlertDialog.Action, AlertDialog.Cancel
|
|
82
|
+
- `Select` - Select.Root, Select.Trigger, Select.Content, Select.Item
|
|
83
|
+
- `Popover` - Popover.Root, Popover.Portal, Popover.Content, Popover.Trigger
|
|
84
|
+
- `HoverCard` - HoverCard.Root, HoverCard.Trigger, HoverCard.Content
|
|
85
|
+
- `Tooltip` - Tooltip.Root, Tooltip.Trigger, Tooltip.Content
|
|
86
|
+
- `DropdownMenu` - DropdownMenu.Root, DropdownMenu.Trigger, DropdownMenu.Content, DropdownMenu.Item
|
|
87
|
+
- `ContextMenu` - ContextMenu.Root, ContextMenu.Trigger, ContextMenu.Content, ContextMenu.Item
|
|
88
|
+
- `Accordion` - Accordion.Root, Accordion.Item, Accordion.Trigger, Accordion.Content
|
|
89
|
+
- `Tabs` - Tabs.Root, Tabs.List, Tabs.Trigger, Tabs.Content
|
|
90
|
+
- `Collapsible` - Collapsible.Root, Collapsible.Trigger, Collapsible.Content
|
|
91
|
+
- `Command` - Command.Root, Command.Input, Command.List, Command.Item
|
|
92
|
+
|
|
93
|
+
Additional bits-ui primitives: Calendar, RangeCalendar, Checkbox, Switch, Slider, Toggle, ToggleGroup, RadioGroup, Menubar, NavigationMenu, Pagination, InputOTP, Sidebar, Progress, Label, Separator, AspectRatio, Avatar, ScrollArea, Sheet. Check the source files for their wrapper patterns.
|
|
94
|
+
|
|
95
|
+
## tailwind-variants (tv)
|
|
96
|
+
|
|
97
|
+
Define variants in `<script module>` for reuse and export:
|
|
98
|
+
|
|
99
|
+
```svelte
|
|
100
|
+
<script module>
|
|
101
|
+
import { cn } from '$lib/utils.js';
|
|
102
|
+
import { tv } from 'tailwind-variants';
|
|
103
|
+
|
|
104
|
+
export const buttonVariants = tv({
|
|
105
|
+
base: 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors',
|
|
106
|
+
variants: {
|
|
107
|
+
variant: {
|
|
108
|
+
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
|
109
|
+
destructive: 'bg-destructive text-white hover:bg-destructive/90',
|
|
110
|
+
outline: 'border bg-background hover:bg-accent',
|
|
111
|
+
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
|
112
|
+
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
|
113
|
+
link: 'text-primary underline-offset-4 hover:underline'
|
|
114
|
+
},
|
|
115
|
+
size: {
|
|
116
|
+
default: 'h-9 px-4 py-2',
|
|
117
|
+
sm: 'h-8 px-3 rounded-md',
|
|
118
|
+
lg: 'h-10 px-6 rounded-md',
|
|
119
|
+
icon: 'size-9'
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
defaultVariants: {
|
|
123
|
+
variant: 'default',
|
|
124
|
+
size: 'default'
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
</script>
|
|
128
|
+
|
|
129
|
+
<script>
|
|
130
|
+
let { variant = 'default', size = 'default', class: className, ...restProps } = $props();
|
|
131
|
+
</script>
|
|
132
|
+
|
|
133
|
+
<button class={cn(buttonVariants({ variant, size }), className)} {...restProps}>
|
|
134
|
+
{@render children?.()}
|
|
135
|
+
</button>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Snippet Slots
|
|
139
|
+
|
|
140
|
+
Use `{@render}` for slot content:
|
|
141
|
+
|
|
142
|
+
```svelte
|
|
143
|
+
<!-- Default slot -->
|
|
144
|
+
{@render children?.()}
|
|
145
|
+
|
|
146
|
+
<!-- Named snippets (passed as props) -->
|
|
147
|
+
{#snippet icon()}
|
|
148
|
+
<ChevronDown />
|
|
149
|
+
{/snippet}
|
|
150
|
+
|
|
151
|
+
<Button {icon}>Click me</Button>
|
|
152
|
+
|
|
153
|
+
<!-- In component, render the snippet prop -->
|
|
154
|
+
{@render icon?.()}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## restProps Spreading
|
|
158
|
+
|
|
159
|
+
Always spread `...restProps` on the root element to pass through attributes:
|
|
160
|
+
|
|
161
|
+
```svelte
|
|
162
|
+
<button
|
|
163
|
+
bind:this={ref}
|
|
164
|
+
data-slot="button"
|
|
165
|
+
class={cn(buttonVariants({ variant, size }), className)}
|
|
166
|
+
{type}
|
|
167
|
+
{disabled}
|
|
168
|
+
{...restProps}
|
|
169
|
+
>
|
|
170
|
+
{@render children?.()}
|
|
171
|
+
</button>
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Conditional Rendering
|
|
175
|
+
|
|
176
|
+
Use standard Svelte `{#if}` blocks for conditional content:
|
|
177
|
+
|
|
178
|
+
```svelte
|
|
179
|
+
{#if href}
|
|
180
|
+
<a bind:this={ref} data-slot="button" {href} {...restProps}>
|
|
181
|
+
{@render children?.()}
|
|
182
|
+
</a>
|
|
183
|
+
{:else}
|
|
184
|
+
<button bind:this={ref} data-slot="button" {...restProps}>
|
|
185
|
+
{@render children?.()}
|
|
186
|
+
</button>
|
|
187
|
+
{/if}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Icon Handling
|
|
191
|
+
|
|
192
|
+
Icons from Lucide use consistent sizing classes:
|
|
193
|
+
|
|
194
|
+
```svelte
|
|
195
|
+
<script>
|
|
196
|
+
import ChevronDownIcon from '@lucide/svelte/icons/chevron-down';
|
|
197
|
+
</script>
|
|
198
|
+
|
|
199
|
+
<ChevronDownIcon class="size-4 opacity-50" />
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Default icon sizing in buttons: `[&_svg:not([class*='size-'])]:size-4`
|
|
203
|
+
|
|
204
|
+
## Example: Complete Card Component
|
|
205
|
+
|
|
206
|
+
```svelte
|
|
207
|
+
<script>
|
|
208
|
+
import { cn } from '$lib/utils.js';
|
|
209
|
+
|
|
210
|
+
let { ref = $bindable(null), class: className, children, ...restProps } = $props();
|
|
211
|
+
</script>
|
|
212
|
+
|
|
213
|
+
<div
|
|
214
|
+
bind:this={ref}
|
|
215
|
+
data-slot="card"
|
|
216
|
+
class={cn(
|
|
217
|
+
'bg-card text-card-foreground flex flex-col gap-6 rounded-md border py-6 shadow-sm',
|
|
218
|
+
className
|
|
219
|
+
)}
|
|
220
|
+
{...restProps}
|
|
221
|
+
>
|
|
222
|
+
{@render children?.()}
|
|
223
|
+
</div>
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## Example: Dialog Content with bits-ui
|
|
227
|
+
|
|
228
|
+
```svelte
|
|
229
|
+
<script>
|
|
230
|
+
import { Dialog as DialogPrimitive } from 'bits-ui';
|
|
231
|
+
import DialogPortal from './dialog-portal.svelte';
|
|
232
|
+
import XIcon from '@lucide/svelte/icons/x';
|
|
233
|
+
import * as Dialog from './index.js';
|
|
234
|
+
import { cn } from '$lib/utils.js';
|
|
235
|
+
|
|
236
|
+
let {
|
|
237
|
+
ref = $bindable(null),
|
|
238
|
+
class: className,
|
|
239
|
+
portalProps,
|
|
240
|
+
children,
|
|
241
|
+
showCloseButton = true,
|
|
242
|
+
...restProps
|
|
243
|
+
} = $props();
|
|
244
|
+
</script>
|
|
245
|
+
|
|
246
|
+
<DialogPortal {...portalProps}>
|
|
247
|
+
<Dialog.Overlay />
|
|
248
|
+
<DialogPrimitive.Content
|
|
249
|
+
bind:ref
|
|
250
|
+
data-slot="dialog-content"
|
|
251
|
+
class={cn(
|
|
252
|
+
'bg-background fixed top-[50%] left-[50%] z-50 w-full max-w-lg translate-x-[-50%] translate-y-[-50%] rounded-lg border p-6 shadow-lg',
|
|
253
|
+
'data-[state=open]:animate-in data-[state=closed]:animate-out',
|
|
254
|
+
className
|
|
255
|
+
)}
|
|
256
|
+
{...restProps}
|
|
257
|
+
>
|
|
258
|
+
{@render children?.()}
|
|
259
|
+
{#if showCloseButton}
|
|
260
|
+
<DialogPrimitive.Close class="absolute end-4 top-4 rounded-xs opacity-70 hover:opacity-100">
|
|
261
|
+
<XIcon />
|
|
262
|
+
<span class="sr-only">Close</span>
|
|
263
|
+
</DialogPrimitive.Close>
|
|
264
|
+
{/if}
|
|
265
|
+
</DialogPrimitive.Content>
|
|
266
|
+
</DialogPortal>
|
|
267
|
+
```
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Physical AI Design Principles
|
|
2
|
+
|
|
3
|
+
## Scope
|
|
4
|
+
|
|
5
|
+
This design system targets the **Measure** and **Reason** layers of the Physical AI stack. Interfaces built with it should support **augmentation** (helping humans perceive the physical world) and **dialogue** (helping humans reason about it). Operation and cooperation — where AI takes action in the world — are out of scope currently but will become relevant in the future.
|
|
6
|
+
|
|
7
|
+
## The Physical AI Stack
|
|
8
|
+
|
|
9
|
+
Physical AI capabilities form a dependency stack where each layer builds on the one below:
|
|
10
|
+
|
|
11
|
+
1. **Interpret** — Make the physical world legible by surfacing signals, anomalies, and structures from sensor data
|
|
12
|
+
2. **Reason** — Enable shared reasoning between humans and AI: explore hypotheses, compare alternatives, support decisions
|
|
13
|
+
3. **Operate** — Delegated action: human sets intent, system executes within defined boundaries (future scope)
|
|
14
|
+
4. **Co-operate** — Joint action: shared agency through mutual adjustment between humans and AI (future scope)
|
|
15
|
+
|
|
16
|
+
## Agency
|
|
17
|
+
|
|
18
|
+
### Human Agency Comes First
|
|
19
|
+
|
|
20
|
+
At the Measure layer, the AI augments human perception — it surfaces what would otherwise remain invisible. The human retains full responsibility to interpret and act. Interfaces should present information without prescribing conclusions.
|
|
21
|
+
|
|
22
|
+
At the Reason layer, interaction is dialogic. The AI contributes explanations and comparisons, but the human drives inquiry and judgment. Interfaces should enable exploration, not deliver verdicts.
|
|
23
|
+
|
|
24
|
+
At the Operate layer, humans shift from direct control to goal-setting and supervision. The AI executes within defined boundaries, and responsibility becomes distributed. Interfaces should make intent, constraints, and system behavior transparent.
|
|
25
|
+
|
|
26
|
+
At the Co-operate layer, humans and AI act as coordinated participants. Action is jointly negotiated, and intent, context, and responsibility are shared and continuously adjusted. Interfaces should support mutual awareness and fluid handoffs.
|
|
27
|
+
|
|
28
|
+
### Interaction Is Situated
|
|
29
|
+
|
|
30
|
+
Interaction unfolds within a three-way relationship: **person, system, and physical world**. Meaning arises from how sensor data, context, and human intent come together in a specific place and moment. Interfaces must maintain this connection to the physical context being observed — sensor sources, locations, time ranges, environmental conditions. Do not abstract away the situational grounding.
|
|
31
|
+
|
|
32
|
+
## Design Implications
|
|
33
|
+
|
|
34
|
+
### Make the World Legible
|
|
35
|
+
|
|
36
|
+
- Prioritize data clarity: visualizations should reveal structure in sensor data — trends, anomalies, distributions, correlations
|
|
37
|
+
- Use semantic tokens (e.g. `text-atai-good`, `text-atai-warning`, `text-atai-critical`) to communicate meaningful states, not for decorative emphasis
|
|
38
|
+
- Design for continuous monitoring: prefer dashboards and live views over static reports
|
|
39
|
+
|
|
40
|
+
### Support Dialogue, Not Monologue
|
|
41
|
+
|
|
42
|
+
- Provide entry points for inquiry: interfaces should invite questions, comparisons, and hypothesis exploration
|
|
43
|
+
- Frame AI output as contribution, not conclusion — use language and layout that position AI reasoning as input to human judgment
|
|
44
|
+
- Enable iterative refinement: conversational flows, follow-up exploration, adjustable parameters
|
|
45
|
+
|
|
46
|
+
### Preserve Physical Context
|
|
47
|
+
|
|
48
|
+
- Show provenance: which sensors, what time range, what conditions produced the data being displayed
|
|
49
|
+
- Ground abstract representations in physical reality — link charts to sensor locations, timestamps to real events
|
|
50
|
+
- Consider operational environments: interfaces may be used in the field, not only at a desk
|
|
51
|
+
|
|
52
|
+
### Respect the Stack Boundary
|
|
53
|
+
|
|
54
|
+
- Default to interfaces that support perception and reasoning rather than autonomous AI action
|
|
55
|
+
- Where possible, distinguish between "the system shows" (Measure) and "the system suggests" (Reason)
|
|
56
|
+
- Prefer framing AI output as observations or suggestions rather than commands or decisions
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Linting & Formatting
|
|
2
|
+
|
|
3
|
+
## Commands
|
|
4
|
+
|
|
5
|
+
| Command | Description |
|
|
6
|
+
| ---------------------- | -------------------------------- |
|
|
7
|
+
| `npm run lint` | Check for linting errors |
|
|
8
|
+
| `npm run lint:fix` | Auto-fix linting errors |
|
|
9
|
+
| `npm run format` | Format all files with Prettier |
|
|
10
|
+
| `npm run format:check` | Check formatting without changes |
|
|
11
|
+
|
|
12
|
+
## Stack
|
|
13
|
+
|
|
14
|
+
- **ESLint** - Flat config (v9+) with `eslint-plugin-svelte`
|
|
15
|
+
- **Prettier** - Code formatting
|
|
16
|
+
- **prettier-plugin-svelte** - Svelte file formatting
|
|
17
|
+
- **prettier-plugin-tailwindcss** - Auto-sorts Tailwind classes
|
|
18
|
+
|
|
19
|
+
## Workflow
|
|
20
|
+
|
|
21
|
+
Run linting and formatting before committing:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm run lint:fix && npm run format
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Or check without auto-fixing:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm run lint && npm run format:check
|
|
31
|
+
```
|