@pactor-app/skills 1.24.0

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.
Files changed (80) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +40 -0
  3. package/package.json +26 -0
  4. package/pactor/SKILL.md +373 -0
  5. package/pactor/references/dsl-authoring.md +448 -0
  6. package/prd-to-app/SKILL.md +75 -0
  7. package/prd-to-app/references/acceptance-checklist.md +47 -0
  8. package/prd-to-app/references/component-mapping.md +41 -0
  9. package/prd-to-app/references/mock-data-routes.md +66 -0
  10. package/prd-to-app/references/page-templates.md +274 -0
  11. package/prd-to-app/references/project-structure.md +89 -0
  12. package/prd-to-app/references/theme-and-style.md +41 -0
  13. package/prd-to-app/template/README.md +26 -0
  14. package/prd-to-app/template/app/[[...slug]]/page.tsx +7 -0
  15. package/prd-to-app/template/app/api/auth/login/route.ts +32 -0
  16. package/prd-to-app/template/app/api/auth/logout/route.ts +22 -0
  17. package/prd-to-app/template/app/api/data/[...parts]/route.ts +118 -0
  18. package/prd-to-app/template/app/api/public/pages/[id]/route.ts +40 -0
  19. package/prd-to-app/template/app/api/sitemap/route.ts +21 -0
  20. package/prd-to-app/template/app/api/users/route.ts +57 -0
  21. package/prd-to-app/template/app/favicon.ico +0 -0
  22. package/prd-to-app/template/app/globals.css +248 -0
  23. package/prd-to-app/template/app/layout.tsx +49 -0
  24. package/prd-to-app/template/app/login.css +122 -0
  25. package/prd-to-app/template/eslint.config.mjs +18 -0
  26. package/prd-to-app/template/next-env.d.ts +7 -0
  27. package/prd-to-app/template/next.config.js +32 -0
  28. package/prd-to-app/template/package.json +34 -0
  29. package/prd-to-app/template/pnpm-lock.yaml +6854 -0
  30. package/prd-to-app/template/pnpm-workspace.yaml +7 -0
  31. package/prd-to-app/template/postcss.config.mjs +7 -0
  32. package/prd-to-app/template/public/file.svg +1 -0
  33. package/prd-to-app/template/public/globe.svg +1 -0
  34. package/prd-to-app/template/public/next.svg +1 -0
  35. package/prd-to-app/template/public/skins/chenwunaifu.css +111 -0
  36. package/prd-to-app/template/public/skins/taijingshenlin.css +109 -0
  37. package/prd-to-app/template/public/skins/xuanzhimoyun.css +110 -0
  38. package/prd-to-app/template/public/vercel.svg +1 -0
  39. package/prd-to-app/template/public/window.svg +1 -0
  40. package/prd-to-app/template/scripts/build.mjs +35 -0
  41. package/prd-to-app/template/src/pactor/App.tsx +55 -0
  42. package/prd-to-app/template/src/pactor/actions.ts +438 -0
  43. package/prd-to-app/template/src/pactor/components/card-links.tsx +86 -0
  44. package/prd-to-app/template/src/pactor/components/chip-filter.tsx +89 -0
  45. package/prd-to-app/template/src/pactor/components/chip-node.tsx +46 -0
  46. package/prd-to-app/template/src/pactor/components/debug-chat.tsx +189 -0
  47. package/prd-to-app/template/src/pactor/components/index.ts +28 -0
  48. package/prd-to-app/template/src/pactor/components/log-status.tsx +64 -0
  49. package/prd-to-app/template/src/pactor/components/status-badge.tsx +46 -0
  50. package/prd-to-app/template/src/pactor/components/theme-switcher.tsx +136 -0
  51. package/prd-to-app/template/src/pactor/config.ts +28 -0
  52. package/prd-to-app/template/src/pactor/mocks/audit-mock.ts +403 -0
  53. package/prd-to-app/template/src/pactor/mocks/call-logs-mock.ts +875 -0
  54. package/prd-to-app/template/src/pactor/mocks/client-debug-mock.ts +188 -0
  55. package/prd-to-app/template/src/pactor/mocks/client-templates-mock.ts +497 -0
  56. package/prd-to-app/template/src/pactor/mocks/clients-mock.ts +483 -0
  57. package/prd-to-app/template/src/pactor/mocks/costs-mock.ts +406 -0
  58. package/prd-to-app/template/src/pactor/mocks/dashboard-mock.ts +192 -0
  59. package/prd-to-app/template/src/pactor/mocks/model-debug-mock.ts +144 -0
  60. package/prd-to-app/template/src/pactor/mocks/models-mock.ts +799 -0
  61. package/prd-to-app/template/src/pactor/mocks/ops-usage-mock.ts +806 -0
  62. package/prd-to-app/template/src/pactor/mocks/providers-mock.ts +424 -0
  63. package/prd-to-app/template/src/pactor/mocks/routes-mock.ts +604 -0
  64. package/prd-to-app/template/src/pactor/services.ts +185 -0
  65. package/prd-to-app/template/src/pactor/skin.ts +52 -0
  66. package/prd-to-app/template/src/server/accounts.ts +63 -0
  67. package/prd-to-app/template/src/server/cors.ts +34 -0
  68. package/prd-to-app/template/src/server/sitemap.ts +176 -0
  69. package/prd-to-app/template/src/server/yaml/common/dashboard.yaml +498 -0
  70. package/prd-to-app/template/src/server/yaml/common/login.yaml +84 -0
  71. package/prd-to-app/template/src/server/yaml/provider/provider-create.yaml +340 -0
  72. package/prd-to-app/template/src/server/yaml/provider/provider-detail.yaml +780 -0
  73. package/prd-to-app/template/src/server/yaml/provider/provider-edit.yaml +366 -0
  74. package/prd-to-app/template/src/server/yaml/provider/provider-list.yaml +1989 -0
  75. package/prd-to-app/template/src/server/yaml/route/route-create.yaml +511 -0
  76. package/prd-to-app/template/src/server/yaml/route/route-detail.yaml +610 -0
  77. package/prd-to-app/template/src/server/yaml/route/route-edit.yaml +809 -0
  78. package/prd-to-app/template/src/server/yaml/route/route-list.yaml +1793 -0
  79. package/prd-to-app/template/src/server/yaml/sitemap.yaml +250 -0
  80. package/prd-to-app/template/tsconfig.json +34 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Pactor Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # @pactor-app/skills
2
+
3
+ Agent skills for rapidly building [Pactor](https://github.com/426-330/pactor) Server-Driven UI applications. One install, all skills.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -D @pactor-app/skills
9
+ # 或
10
+ pnpm add -D @pactor-app/skills
11
+ ```
12
+
13
+ ## Shipped skills
14
+
15
+ | Skill | Description |
16
+ | --- | --- |
17
+ | `pactor` | Pactor framework guidance: DSL authoring, custom components/actions/services, theming, routing, resources, permissions. See `pactor/SKILL.md`. |
18
+ | `prd-to-app` | Generate a runnable pactor app from PRD documents and markdown wireframes (pages in YAML DSL, http dataSources + mock API routes). See `prd-to-app/SKILL.md`. |
19
+
20
+ ## Usage
21
+
22
+ Each skill is a self-contained directory (`SKILL.md` + optional `references/` and `template/`). Copy or symlink the skill directory you need into your agent's skill directory (the `references/` subfolder must come along — `SKILL.md` points to it; `prd-to-app` additionally needs its `template/` starter project):
23
+
24
+ ```bash
25
+ # 例如 Claude Code:~/.claude/skills/<skill-name>/
26
+ ln -s node_modules/@pactor-app/skills/pactor ~/.claude/skills/pactor
27
+ ln -s node_modules/@pactor-app/skills/prd-to-app ~/.claude/skills/prd-to-app
28
+ ```
29
+
30
+ Skills use standard YAML frontmatter (`name`, `description`, `version`) followed by markdown guidance.
31
+
32
+ ## Adding a skill
33
+
34
+ 1. Create `<skill-name>/` directly under the package root.
35
+ 2. Write `SKILL.md` with standard YAML frontmatter (`name` consistent with the directory name) and add `references/` if the skill needs deep documentation.
36
+ 3. The skill ships with the package automatically on next publish.
37
+
38
+ ## License
39
+
40
+ MIT
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@pactor-app/skills",
3
+ "version": "1.24.0",
4
+ "description": "Agent skills for rapidly building pactor Server-Driven UI applications",
5
+ "keywords": [
6
+ "pactor",
7
+ "dsl",
8
+ "server-driven-ui",
9
+ "skill",
10
+ "skills",
11
+ "agent"
12
+ ],
13
+ "license": "MIT",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/426-330/pactor.git",
17
+ "directory": "packages/skills"
18
+ },
19
+ "homepage": "https://github.com/426-330/pactor/tree/main/packages/skills",
20
+ "bugs": "https://github.com/426-330/pactor/issues",
21
+ "type": "module",
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "scripts": {}
26
+ }
@@ -0,0 +1,373 @@
1
+ ---
2
+ name: pactor
3
+ description: |
4
+ Use when working with Pactor — any @pactor-app/* package or the pactor-app meta package. Especially when writing, generating, editing, or debugging Pactor DSL files (*.page.yaml: pages, state, dataSources, components, events, actions, expressions); also when bootstrapping a Pactor app (createPactorApplication, StaticDslLoader), registering custom components/actions/services, building AI chat pages (Chat, ChatShell), configuring themes/layouts/routing/resources/permissions, or using @pactor-app/vite-plugin / @pactor-app/cli (pactor validate).
5
+ version: 1.9.0
6
+ ---
7
+
8
+ # pactor-app
9
+
10
+ ## When to activate
11
+
12
+ Activate this skill when the user works with **Pactor** — any `@pactor-app/*` package or the `pactor-app` meta package:
13
+
14
+ - Building or extending a Pactor application
15
+ - Using `createPactorApplication`, `@pactor-app/app`, or `StaticDslLoader`
16
+ - Writing YAML/JSON DSL pages, components, events, or actions
17
+ - Creating or registering custom components / actions / services
18
+ - Building AI chat pages (`Chat`, `ChatShell`, `ChatServicesProvider`)
19
+ - Configuring themes, skins, layouts, menus, or sidebars
20
+ - Integrating data sources, routers, resources, or permissions
21
+ - Handling form linkage, event linkage, or action orchestration
22
+ - Using `@pactor-app/vite-plugin` or `@pactor-app/cli`
23
+ - Mentioning packages: `@pactor-app/core`, `@pactor-app/runtime`, `@pactor-app/app`, `@pactor-app/ui`, `@pactor-app/router`, `@pactor-app/resource`, `@pactor-app/permission`, `@pactor-app/expression`, `@pactor-app/schema`, `@pactor-app/chat`, `@pactor-app/markdown`
24
+
25
+ ## What you can do with this skill
26
+
27
+ - Explain Pactor architecture, package boundaries, and dependency rules
28
+ - Guide a user from zero to a running Server-Driven UI app
29
+ - Register custom components, actions, services, and capabilities
30
+ - Design data flow, expressions, events, and action orchestration
31
+ - Configure themes/skins, layouts, routing, resources, and permissions
32
+ - Assemble AI chat workspaces with the `Chat` DSL component
33
+ - Provide exact commands and example project pointers
34
+
35
+ ## Framework in one sentence
36
+
37
+ **Pactor — Dynamic Application Runtime**: an enterprise-oriented **Server-Driven UI + AI-Native frontend runtime** where pages are YAML/JSON DSL rendered by a shared browser Runtime. Business projects install the framework via npm; ordinary pages do not need to be rebuilt or rebundled.
38
+
39
+ ## Package map
40
+
41
+ | Directory | Package | What it provides |
42
+ |-----------|---------|------------------|
43
+ | `packages/core` | `@pactor-app/core` | DSL protocol types, AST, Registry interfaces |
44
+ | `packages/schema` | `@pactor-app/schema` | JSON Schema, TS types, validation rules |
45
+ | `packages/expression` | `@pactor-app/expression` | Controlled expression engine (no eval) |
46
+ | `packages/runtime` | `@pactor-app/runtime` | Renderer, RuntimeContext, State, DataSource, Action, Page Runtime |
47
+ | `packages/resource` | `@pactor-app/resource` | DSL loaders (HTTP / static), cache, versioning |
48
+ | `packages/router` | `@pactor-app/router` | Dynamic routing, Path Matcher, menu registry |
49
+ | `packages/permission` | `@pactor-app/permission` | Page/menu/component/action guards |
50
+ | `packages/ui` | `@pactor-app/ui` | Built-in default UI implementation, shadcn style (components + prebuilt stylesheet + interaction core) |
51
+ | `packages/markdown` | `@pactor-app/markdown` | Markdown + DSL Part rendering |
52
+ | `packages/chat` | `@pactor-app/chat` | AI conversation: message protocol, streaming, ChatView, `Chat`/`ChatShell` DSL components, artifact panel |
53
+ | `packages/vite-plugin` | `@pactor-app/vite-plugin` | Vite YAML modules, build-time validation, HMR |
54
+ | `packages/cli` | `@pactor-app/cli` | DSL validation, inspection, scaffolding |
55
+ | `packages/app` | `@pactor-app/app` | One-stop composition (`createPactorApplication`) |
56
+ | `packages/pactor` | `pactor-app` | Meta package — depends on all modules, re-exports `@pactor-app/app` |
57
+ | `packages/skills` | `@pactor-app/skills` | Agent skills collection (this skill lives at `pactor/`) |
58
+
59
+ ## Dependency rules
60
+
61
+ Dependencies are strictly one-way:
62
+
63
+ ```text
64
+ core ← schema ← expression ← runtime
65
+ ↓
66
+ {permission, resource, router, ui} ← app
67
+ ```
68
+
69
+ - Business apps depend only on `@pactor-app/app` + `@pactor-app/ui`, or install the `pactor-app` meta package to get every module at once.
70
+ - Never import implementation details from sibling packages.
71
+ - Renderer logic must resolve components via Registry, not `if (type === 'X')` branches.
72
+
73
+ ## Quick start
74
+
75
+ ### Install
76
+
77
+ ```bash
78
+ # meta package: installs every module at once
79
+ pnpm add pactor-app
80
+
81
+ # or install only what you need (shadcn-style built-in UI)
82
+ pnpm add @pactor-app/app @pactor-app/ui
83
+ ```
84
+
85
+ ### Bootstrap with API loader
86
+
87
+ ```tsx
88
+ import { createPactorApplication } from '@pactor-app/app';
89
+ import '@pactor-app/ui/styles.css'; // required
90
+
91
+ createPactorApplication({
92
+ appId: 'my-app',
93
+ api: { baseURL: '/api/runtime' },
94
+ }).mount('#root');
95
+ ```
96
+
97
+ Server must provide the Envelope endpoints:
98
+
99
+ - `{baseURL}/bootstrap` — app, user, permissions, menus, layout
100
+ - `{baseURL}/pages/{id}` — page DSL
101
+
102
+ ### Bootstrap locally with StaticDslLoader
103
+
104
+ ```tsx
105
+ import { createPactorApplication } from '@pactor-app/app';
106
+ import { StaticDslLoader } from '@pactor-app/resource';
107
+ import '@pactor-app/ui/styles.css';
108
+ import homePage from './pages/home.page.yaml';
109
+
110
+ const loader = new StaticDslLoader({
111
+ bootstrap: {
112
+ app: { name: 'My App' },
113
+ menus: [{ id: 'home', type: 'page', title: 'Home', path: '/', pageId: 'home' }],
114
+ layout: { type: 'admin' },
115
+ },
116
+ pages: { home: homePage },
117
+ });
118
+
119
+ createPactorApplication({ appId: 'my-app', loader }).mount('#root');
120
+ ```
121
+
122
+ For YAML imports add `@pactor-app/vite-plugin` to `vite.config.ts` and declare `*.page.yaml` modules.
123
+
124
+ ## UI at a glance
125
+
126
+ The built-in shadcn-style UI (`@pactor-app/ui`) registers these DSL component types — reference them by `type` in pages:
127
+
128
+ - **Page & layout**: `Page`, `Layout` / `Header` / `Sider` / `Content` / `Footer`, `Grid`, `Flex`, `Card`, `Sidebar`
129
+ - **Basic**: `Button`, `Alert`, `Statistic`, `Menu`, `Link`, `Text`, `Typography`, `Icon`
130
+ - **Data**: `Table`, `Tabs`, `DataTable`, `Chart`
131
+ - **Form**: `Form`, `Input`, `NumberInput`, `Select`, `Textarea`, `Checkbox`, `RadioGroup`, `Switch`, `Slider`, `Label`, `Field`, `ChatInput`, `DatePicker`
132
+ - **Display**: `Badge`, `Avatar`, `Skeleton`, `Separator`, `Kbd`, `Spinner`, `Empty`, `AspectRatio`, `Progress`, `Calendar`, `Carousel`, `Item`
133
+ - **Navigation**: `Breadcrumb`, `Pagination`, `Menubar`, `NavigationMenu`, `DropdownMenu`, `ContextMenu`
134
+ - **Overlay & feedback**: `Dialog`, `AlertDialog`, `Drawer`, `Sheet`, `Popover`, `Tooltip`, `HoverCard`, `Sonner`, `Accordion`, `Collapsible`
135
+ - **Composite input**: `InputOTP`, `Combobox`, `Command`, `InputGroup`, `ButtonGroup`, `Toggle`, `ToggleGroup`, `Resizable`, `ScrollArea`
136
+
137
+ Notable behaviors:
138
+
139
+ - `Icon` renders from a lucide whitelist (~100 names, kebab-case keys; PascalCase/camelCase auto-normalized); unknown names render a placeholder.
140
+ - `Sidebar` is a full app shell: brand area, `items` nav or `content` free slot, `sidebarFooter`, desktop icon-rail collapse (hover shows tooltip), mobile overlay drawer.
141
+ - `ChatInput` is the generic AI input structure (textarea + toolbar slots + header/footer slots).
142
+ - Registered layouts: `admin`, `blank`, `login`, `landing`, `chat` (resolve via the `layout` field).
143
+
144
+ Component contracts and per-component props: see the docs site (`docs/src/content/docs/components/`).
145
+
146
+ ## Workflow: authoring DSL pages
147
+
148
+ When the user asks to build / generate / edit a Pactor DSL file (`*.page.yaml`):
149
+
150
+ 1. Start from the page skeleton below — never invent the top-level shape.
151
+ 2. Declare `state` and `dataSources` first, then compose the `body` tree from registered component `type`s only.
152
+ 3. Wire interactions via `events` → standard actions; expressions `${...}` read the scope chain.
153
+ 4. Validate before delivering: `npx pactor validate <file>` (from `@pactor-app/cli`; inside this monorepo: `node packages/cli/dist/cli.js validate <file>`). Note: the validator checks schema shape only, not component props semantics — use the reference for correct props.
154
+
155
+ ```yaml
156
+ dsl: '1.0' # required, DSL spec version
157
+ page: # required
158
+ id: customer-list # globally unique
159
+ title: Customer List
160
+ permission: customer:view # optional page guard
161
+ state: # optional, reactive initial state
162
+ keyword: ''
163
+ dataSources: # optional, named data sources
164
+ customers:
165
+ type: service # static | service | http
166
+ service: customer.list
167
+ autoLoad: true
168
+ params:
169
+ keyword: ${state.keyword} # expressions, evaluated at load time
170
+ body: # UI tree root (DslNode)
171
+ type: Page
172
+ props: { title: Customer List }
173
+ children: [...]
174
+ ```
175
+
176
+ Facts that are NOT guessable and must be followed:
177
+
178
+ - Top level is `{ dsl, page, state?, dataSources?, actions?, components?, lifecycle?, body? }` — `page` is a wrapper object, `dsl: '1.0'` is mandatory.
179
+ - `Table` reads data via an **expression** (`dataSource: ${data.customers}`), not a source name; column templates use the `cell` key (not `render`) with `${row.x}` scope; pagination is `pagination: { pageSize: 5 }`.
180
+ - Form fields bind via `props.name`; the submit button uses `submit: true` (not `htmlType`); `Form onSubmit` receives all values as `${event.<field>}`.
181
+ - `navigate` takes `to`; `message` takes `text` + `messageType` (a `type` key in action `params` disables expression evaluation).
182
+ - Query linkage = `onSubmit: [setState, reload]`; the data source's `params` referencing `${state.x}` pick up new values on reload.
183
+
184
+ **Full DSL grammar, action catalog, expression/scopes tables, and copy-paste recipes: read `references/dsl-authoring.md` bundled next to this SKILL.md — read it before writing any non-trivial page.** In the monorepo, per-component props live in `docs/src/content/docs/components/` and the exhaustive DSL reference in `docs/src/content/docs/reference/dsl.md`.
185
+
186
+ ## Workflow: custom component
187
+
188
+ 1. Write a React component in the business project
189
+ 2. Register via `components` option or `app.registerComponent`
190
+ 3. Reference in DSL by `type`
191
+
192
+ ```tsx
193
+ import { createPactorApplication } from '@pactor-app/app';
194
+ import { RiskScore } from './components/RiskScore';
195
+
196
+ createPactorApplication({
197
+ appId: 'risk-admin',
198
+ api: { baseURL: '/api/runtime' },
199
+ components: { RiskScore },
200
+ });
201
+ ```
202
+
203
+ ```yaml
204
+ body:
205
+ type: RiskScore
206
+ props:
207
+ score: "${row.riskScore}"
208
+ ```
209
+
210
+ Custom components receive RuntimeContext (state, data, permissions, routing, services, actions).
211
+
212
+ ## Workflow: events and data flow
213
+
214
+ Expressions access runtime scopes:
215
+
216
+ ```yaml
217
+ text: "${state.user.name}"
218
+ visible: "${state.status == 'ACTIVE'}"
219
+ disabled: "${!permission('customer:edit')}"
220
+ ```
221
+
222
+ Scope chain:
223
+
224
+ ```text
225
+ global → app → page → overlay → form → component → row → event
226
+ ```
227
+
228
+ Action orchestration:
229
+
230
+ ```yaml
231
+ events:
232
+ onSubmit:
233
+ - action: setState
234
+ params: { keyword: "${event.keyword}" }
235
+ - action: reload
236
+ params: { dataSource: todos }
237
+ ```
238
+
239
+ Standard actions: `request`, `reload`, `setState`, `resetState`, `navigate`, `message`, `confirm`, `validate`, `submit`, `open`, `close`, `download`, `upload`, `sequence`, `parallel`, `if`, etc. Business can register custom actions.
240
+
241
+ Pitfall: action `params` objects with a `type` (or `action`) key are treated as nested DSL/action configs and skip expression evaluation — rename the key (e.g. use `messageType` instead of `type`).
242
+
243
+ ## Workflow: theming and skins
244
+
245
+ - The built-in kit is shadcn (`@pactor-app/ui`); theming = overriding its CSS variable tokens at `:root` (`--primary` / `--muted` / `--radius` / ...), dark via `data-pactor-theme="dark"`
246
+ - Portaled overlays (Tooltip / Select / DropdownMenu popups) mount at `document.body` — token overrides must live at `:root`, not on an inner container
247
+ - Chat surfaces use a separate `--pactor-chat-*` token set (same override + dark mechanism)
248
+ - Layout and theme config usually come from bootstrap
249
+ - For business skin settings, see `examples/admin` (`skin.ts` / `SkinSettings`)
250
+ - Use `providers` and `headerExtra` slots in `@pactor-app/app` to inject global providers and settings entry
251
+
252
+ ## Workflow: routing, resources, permissions
253
+
254
+ - **Routing** (`@pactor-app/router`): dynamic routes from bootstrap `menus`, supports Path Matcher, params, hidden routes
255
+ - **Resources** (`@pactor-app/resource`): loads page/fragment DSL with HttpDslResourceLoader or StaticDslLoader, cache, versioning
256
+ - **Permissions** (`@pactor-app/permission`): page/menu/component/action guards. Frontend permissions only control UI; backend APIs must still authorize
257
+
258
+ Bootstrap orchestration:
259
+
260
+ ```text
261
+ load bootstrap → write PermissionStore → build MenuRegistry → resolve layout → assemble shared registries → render page
262
+ ```
263
+
264
+ ## Workflow: AI chat workspace
265
+
266
+ `@pactor-app/chat` provides a complete conversation workspace, and `Chat` is a first-class DSL component (registered alongside `ChatShell` by `registerChatComponent(registry)`). Runtime services are injected once by the host via `ChatServicesProvider` (`transport` required; `callService(name, params)` service bridge resolves dynamic data sources).
267
+
268
+ With pactor-app, use the convenience factory `createChatComponentRegistry()` (built-in components + Chat/ChatShell) as the `componentRegistry` option; bootstrap `layout.type: 'chat'` resolves to the built-in ChatLayout (sidebar + menu shell) without custom registration.
269
+
270
+ ```yaml
271
+ body:
272
+ type: Chat
273
+ props:
274
+ greeting: Hello
275
+ menu:
276
+ - { key: new, label: New Chat, icon: plus }
277
+ models: # built-in model selector (controlled: model + onModelChange)
278
+ - { value: demo, label: demo-mock }
279
+ model: ${state.model}
280
+ contexts: # @ mention / + context popovers; service refs resolve via callService
281
+ - { trigger: '@', label: Agents, service: agents }
282
+ composerFooter: # composer footer slot (below the toolbar, with divider)
283
+ type: DropdownMenu
284
+ props:
285
+ items: [{ label: Default Workspace, value: Default Workspace, icon: folder }]
286
+ children:
287
+ - type: Button
288
+ props: { text: Select Workspace, variant: text, size: small }
289
+ messageActions: [copy, regenerate, edit]
290
+ events:
291
+ onModelChange:
292
+ - action: setState
293
+ params: { model: ${event.model} }
294
+ ```
295
+
296
+ Feature checklist (all DSL-declarable props):
297
+
298
+ - **Composer**: attachments (paste / drag / file pick handled by the host), `toolbarStart` / `toolbarEnd` / `composerFooter` / `composerBottom` slots, `hideToolbar` (hide the default toolbar row, Enter still sends)
299
+ - **Model selector**: `models` + `modelPlacement: composer | header`
300
+ - **Contexts**: `@` / `+` anchored popovers, selected items become chips and travel with the message (structured, never concatenated into text)
301
+ - **Message actions**: `messageActions` — the array is the truth (built-ins not listed do not appear); custom actions dispatch via the service bridge
302
+ - **Artifact panel**: `artifact` / `panelOpen` controlled props, `inspector` slot, `onArtifact` / `onPanelClose` / `onOpenArtifact` events; markdown / code / text / dsl built-in renderers
303
+ - **Header**: auto-rendered only when it has content; `title` / `headerActions: [export, theme, clear]` / `editableTitle`
304
+ - **Shell**: `menu` sidebar (icons / badge / dot / group / disabled), `sidebar` replacement slot; `ChatShell` for menu-driven multi-page shells (brand, collapsible icon rail, sidebarFooter)
305
+
306
+ Pure-React hosts can use `<ChatServicesProvider>` + `<Chat>` directly; `createChatWorkspace(services)` remains as a compatibility path (same composition, same DSL props). Full assembly: `examples/chat`.
307
+
308
+ ## Common commands
309
+
310
+ ```bash
311
+ # install dependencies
312
+ pnpm install
313
+
314
+ # build all packages (ESM + CJS + d.ts)
315
+ pnpm build
316
+
317
+ # run all tests
318
+ pnpm test
319
+
320
+ # TypeScript check
321
+ pnpm typecheck
322
+
323
+ # start docs site
324
+ pnpm --filter pactor-docs dev
325
+
326
+ # examples
327
+ pnpm --filter example-vite-starter dev # minimal starter
328
+ pnpm --filter example-admin dev # shadcn admin dashboard (skin settings)
329
+ pnpm --filter example-chat dev # AI chat (built on createPactorApplication)
330
+
331
+ # @pactor-app/cli
332
+ pnpm pactor validate src/pages/**/*.page.yaml
333
+ pnpm pactor inspect src/pages/home.page.yaml
334
+ pnpm pactor create my-app
335
+ ```
336
+
337
+ > Examples reference workspace `dist` outputs. After changing package code, run `pnpm build` before examples pick up changes.
338
+
339
+ ## Design principles
340
+
341
+ 1. **DSL is a protocol**, not just a config file: it describes app, page, state, data sources, components, events, actions, and lifecycle
342
+ 2. **Dynamic DSL, static capabilities**: the server can deliver pages/menus/permissions, but components, actions, services, and capabilities must be defined by the frontend Runtime registries. Never inject arbitrary JavaScript through DSL
343
+ 3. **Runtime is the core**: DSL → Parser/Validator → Runtime Context → expression/permission/data-source → Component Registry → React Renderer
344
+ 4. **Allow React escape hatch**: 70%–80% ordinary pages use pure DSL; complex pages can be written directly in React
345
+ 5. **Frontend permissions only control UI**: hiding menus, buttons, or intercepting actions does not replace backend authorization
346
+ 6. **No eval in expressions**: use a controlled AST; disallow access to `window`, `document`, `localStorage`, `fetch`, `eval`, and other globals
347
+
348
+ ## Common pitfalls
349
+
350
+ - **Do not** import UI package internals directly into business DSL pages; use registered component names.
351
+ - **Do not** write `if (type === 'Button')` branches in a Renderer; use `ComponentRegistry`.
352
+ - **Do not** inject JavaScript from the server into DSL; register actions/services/capabilities in the frontend.
353
+ - **Do not** rely on frontend permission checks for security; enforce authorization on backend APIs.
354
+ - **Do not** forget to import `@pactor-app/ui/styles.css` when using the default shadcn kit (`@pactor-app/chat/styles.css` additionally for chat surfaces).
355
+ - **Do not** put a `type` key in action `params` (see the events workflow pitfall).
356
+ - **Do not** expect DslNode slots (sidebar / toolbar / inspector / …) to render outside a page runtime; in pure React hosts pass ReactNode instead.
357
+
358
+ ## References
359
+
360
+ - **DSL authoring reference (bundled)**: `references/dsl-authoring.md` — full page grammar, dataSources, expressions/scopes, action catalog, recipes, common mistakes. Read it before writing DSL.
361
+ - Framework design specification: `docs/src/content/docs/framework-design.md`
362
+ - Quick start: `docs/src/content/docs/guides/getting-started.md`
363
+ - @pactor-app/app docs: `docs/src/content/docs/packages/app.md`
364
+ - @pactor-app/chat docs: `docs/src/content/docs/packages/chat.md`
365
+ - Component reference: `docs/src/content/docs/components/`
366
+ - Example projects:
367
+ - `examples/vite-starter` — minimal starter
368
+ - `examples/admin` — shadcn admin dashboard with skin settings
369
+ - `examples/chat` — AI chat workspace (pactor-app assembly)
370
+
371
+ ## How to use this skill
372
+
373
+ This skill is maintained as `packages/skills/pactor/SKILL.md` together with `references/dsl-authoring.md`. AI agents can copy or link the whole `packages/skills/pactor` directory into their skill directory to provide contextual guidance when reading or editing Pactor projects.