pixelcrew 0.2.2 → 0.2.3
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/package.json +1 -1
- package/src/orchestrator/code-generator.js +994 -0
- package/src/orchestrator/engine.js +11 -1
- package/src/orchestrator/oneshot.js +80 -1277
- package/src/orchestrator/planner.js +329 -0
- package/src/orchestrator/skills-registry.js +194 -0
- package/src/orchestrator/task-queue.js +128 -0
- package/src/server/server.js +9 -2
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PIXEL CREW — Dynamic Project Planner & Task Graph Engine
|
|
3
|
+
*
|
|
4
|
+
* Analyzes user prompts from first principles and creates:
|
|
5
|
+
* 1. Deep Project Specification (Domain, Components, Features, Data Models)
|
|
6
|
+
* 2. Dynamic Task Graph (DAG) with explicit dependency resolution
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { SkillRegistry } from './skills-registry.js';
|
|
10
|
+
|
|
11
|
+
export class DynamicPlanner {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.skillRegistry = new SkillRegistry();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Step 1: Analyze Requirements from User Prompt
|
|
18
|
+
*/
|
|
19
|
+
analyzeRequirements(prompt, options = {}) {
|
|
20
|
+
const p = (prompt || '').toLowerCase();
|
|
21
|
+
|
|
22
|
+
// 1. Target Framework & Stack
|
|
23
|
+
let framework = options.targetFramework || 'nextjs';
|
|
24
|
+
if (p.includes('react') && !p.includes('next')) framework = 'react';
|
|
25
|
+
else if (p.includes('vue')) framework = 'vue';
|
|
26
|
+
else if (p.includes('vanilla')) framework = 'vanilla';
|
|
27
|
+
|
|
28
|
+
// 2. Domain Classification
|
|
29
|
+
let domain = 'custom';
|
|
30
|
+
if (p.includes('portfolio') || p.includes('resume') || p.includes('showcase my project') || p.includes('developer portfolio') || p.includes('personal site')) {
|
|
31
|
+
domain = 'portfolio';
|
|
32
|
+
} else if (p.includes('restaurant') || p.includes('culinary') || p.includes('dining') || p.includes('cafe') || p.includes('bistro') || p.includes('menu')) {
|
|
33
|
+
domain = 'restaurant';
|
|
34
|
+
} else if (p.includes('ecommerce') || p.includes('shop') || p.includes('store') || p.includes('product store') || p.includes('clothing')) {
|
|
35
|
+
domain = 'ecommerce';
|
|
36
|
+
} else if (p.includes('saas') || p.includes('platform') || p.includes('subscription') || p.includes('analytics') || p.includes('pricing calculator')) {
|
|
37
|
+
domain = 'saas';
|
|
38
|
+
} else if (p.includes('agency') || p.includes('studio') || p.includes('creative lab') || p.includes('design agency')) {
|
|
39
|
+
domain = 'agency';
|
|
40
|
+
} else if (p.includes('database') || p.includes('infra') || p.includes('developer tool') || p.includes('query') || p.includes('api engine')) {
|
|
41
|
+
domain = 'devtool';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// 3. Motion & Animation Intent
|
|
45
|
+
const hasAnimations = p.includes('animation') || p.includes('motion') || p.includes('interactive') || p.includes('kinetic') || true;
|
|
46
|
+
|
|
47
|
+
// 4. Extract Entity / Project Name
|
|
48
|
+
let projectName = "Bespoke System";
|
|
49
|
+
let companyName = "Studio Artisan";
|
|
50
|
+
let roleOrSubtitle = "Modern Digital Platform";
|
|
51
|
+
let summary = "Engineered with intentional restraint and zero generic AI slop.";
|
|
52
|
+
|
|
53
|
+
if (domain === 'portfolio') {
|
|
54
|
+
projectName = "Modern Developer Portfolio";
|
|
55
|
+
companyName = "Alex Rivera";
|
|
56
|
+
roleOrSubtitle = "Staff Systems Architect & Creative Technologist";
|
|
57
|
+
summary = "Designing high-order distributed architectures, sub-millisecond query engines, and kinetic human-grade web interfaces.";
|
|
58
|
+
} else if (domain === 'restaurant') {
|
|
59
|
+
projectName = "Artisan Culinary Studio";
|
|
60
|
+
companyName = "AURELIA";
|
|
61
|
+
roleOrSubtitle = "Modern Botanical Gastronomy & Tasting Lab";
|
|
62
|
+
summary = "Hyper-seasonal tasting menus driven by foraging, fermentation, and architectural plating.";
|
|
63
|
+
} else if (domain === 'ecommerce') {
|
|
64
|
+
projectName = "Minimalist Object Store";
|
|
65
|
+
companyName = "MONOLITH GOODS";
|
|
66
|
+
roleOrSubtitle = "Precision-Crafted Hardware & Studio Tools";
|
|
67
|
+
summary = "Industrial-grade design artifacts engineered for creators, architects, and minimalists.";
|
|
68
|
+
} else if (domain === 'saas' || domain === 'devtool') {
|
|
69
|
+
projectName = "High-Performance Data Infrastructure";
|
|
70
|
+
companyName = "VectorScale";
|
|
71
|
+
roleOrSubtitle = "Real-Time Telemetry & Vector Query Engine";
|
|
72
|
+
summary = "Sub-millisecond latency query routing and deterministic state coordination for autonomous AI swarms.";
|
|
73
|
+
} else if (domain === 'agency') {
|
|
74
|
+
projectName = "Kinetic Creative Studio";
|
|
75
|
+
companyName = "KITE CREATIVE";
|
|
76
|
+
roleOrSubtitle = "Design Engineering & Spatial Digital Systems";
|
|
77
|
+
summary = "We partner with visionary founders to build category-defining digital flagships and interactive products.";
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
prompt,
|
|
82
|
+
domain,
|
|
83
|
+
framework,
|
|
84
|
+
hasAnimations,
|
|
85
|
+
projectName,
|
|
86
|
+
companyName,
|
|
87
|
+
roleOrSubtitle,
|
|
88
|
+
summary,
|
|
89
|
+
requestedFeatures: this.extractRequestedFeatures(p, domain)
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Helper: Extracts requested interactive feature modules
|
|
95
|
+
*/
|
|
96
|
+
extractRequestedFeatures(promptLower, domain) {
|
|
97
|
+
const features = [];
|
|
98
|
+
|
|
99
|
+
if (domain === 'portfolio') {
|
|
100
|
+
features.push('project-filter-matrix', 'interactive-terminal-shell', 'career-timeline', 'contact-modal');
|
|
101
|
+
} else if (domain === 'restaurant') {
|
|
102
|
+
features.push('interactive-tasting-menu', 'table-reservation-modal', 'chef-curation-slider', 'hours-location-card');
|
|
103
|
+
} else if (domain === 'ecommerce') {
|
|
104
|
+
features.push('product-bento-grid', 'interactive-cart-drawer', 'currency-toggle', 'live-spec-sheet');
|
|
105
|
+
} else if (domain === 'saas' || domain === 'devtool') {
|
|
106
|
+
features.push('interactive-latency-calculator', 'code-sandbox-tabs', 'benchmark-comparison-matrix', 'pricing-tier-switcher');
|
|
107
|
+
} else {
|
|
108
|
+
features.push('asymmetric-showcase', 'interactive-feature-tabs', 'dynamic-contact-drawer');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (promptLower.includes('dark') || promptLower.includes('theme') || promptLower.includes('toggle')) {
|
|
112
|
+
features.push('theme-toggle');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return features;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Step 2: Create Unique Project Specification
|
|
120
|
+
*/
|
|
121
|
+
createProjectSpecification(analysis) {
|
|
122
|
+
const { domain, framework, companyName, roleOrSubtitle, summary, requestedFeatures, hasAnimations } = analysis;
|
|
123
|
+
|
|
124
|
+
// 1. Design Tokens & Palette (High-contrast, zero generic AI purple blobs)
|
|
125
|
+
let palette = {
|
|
126
|
+
bg: "#090a0f",
|
|
127
|
+
surface: "#10121a",
|
|
128
|
+
surfaceRaised: "#181b26",
|
|
129
|
+
border: "rgba(255, 255, 255, 0.08)",
|
|
130
|
+
borderHover: "rgba(255, 255, 255, 0.25)",
|
|
131
|
+
textPrimary: "#f8fafc",
|
|
132
|
+
textSecondary: "#94a3b8",
|
|
133
|
+
accent: "#38bdf8",
|
|
134
|
+
accentGlow: "rgba(56, 189, 248, 0.15)"
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
let fonts = {
|
|
138
|
+
display: "'Space Grotesk', -apple-system, sans-serif",
|
|
139
|
+
body: "'Plus Jakarta Sans', -apple-system, sans-serif",
|
|
140
|
+
mono: "'JetBrains Mono', monospace",
|
|
141
|
+
googleFontsUrl: "https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=Plus+Jakarta+Sans:wght@300;400;500;600;700&family=Space+Grotesk:wght@500;600;700&display=swap"
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
if (domain === 'restaurant') {
|
|
145
|
+
palette = {
|
|
146
|
+
bg: "#0c0b0a",
|
|
147
|
+
surface: "#141311",
|
|
148
|
+
surfaceRaised: "#1c1b18",
|
|
149
|
+
border: "rgba(217, 196, 163, 0.12)",
|
|
150
|
+
borderHover: "rgba(217, 196, 163, 0.35)",
|
|
151
|
+
textPrimary: "#f5f2eb",
|
|
152
|
+
textSecondary: "#a8a29e",
|
|
153
|
+
accent: "#d4af37",
|
|
154
|
+
accentGlow: "rgba(212, 175, 55, 0.15)"
|
|
155
|
+
};
|
|
156
|
+
fonts = {
|
|
157
|
+
display: "'Cormorant Garamond', Georgia, serif",
|
|
158
|
+
body: "'Plus Jakarta Sans', sans-serif",
|
|
159
|
+
mono: "'JetBrains Mono', monospace",
|
|
160
|
+
googleFontsUrl: "https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,600;1,400&family=Plus+Jakarta+Sans:wght@300;400;500;600&display=swap"
|
|
161
|
+
};
|
|
162
|
+
} else if (domain === 'agency' || domain === 'portfolio') {
|
|
163
|
+
palette = {
|
|
164
|
+
bg: "#08090c",
|
|
165
|
+
surface: "#0f1117",
|
|
166
|
+
surfaceRaised: "#161922",
|
|
167
|
+
border: "rgba(255, 255, 255, 0.08)",
|
|
168
|
+
borderHover: "rgba(255, 255, 255, 0.3)",
|
|
169
|
+
textPrimary: "#ffffff",
|
|
170
|
+
textSecondary: "#9ca3af",
|
|
171
|
+
accent: "#10b981",
|
|
172
|
+
accentGlow: "rgba(16, 185, 129, 0.15)"
|
|
173
|
+
};
|
|
174
|
+
fonts = {
|
|
175
|
+
display: "'Instrument Serif', Georgia, serif",
|
|
176
|
+
body: "'Inter', -apple-system, sans-serif",
|
|
177
|
+
mono: "'JetBrains Mono', monospace",
|
|
178
|
+
googleFontsUrl: "https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap"
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// 2. Dynamic Section Topology
|
|
183
|
+
const sections = this.buildSectionTopology(domain, companyName, roleOrSubtitle, summary, requestedFeatures);
|
|
184
|
+
|
|
185
|
+
return {
|
|
186
|
+
projectName: analysis.projectName,
|
|
187
|
+
domain,
|
|
188
|
+
framework,
|
|
189
|
+
companyName,
|
|
190
|
+
headline: roleOrSubtitle,
|
|
191
|
+
summary,
|
|
192
|
+
hasAnimations,
|
|
193
|
+
palette,
|
|
194
|
+
fonts,
|
|
195
|
+
requestedFeatures,
|
|
196
|
+
sections,
|
|
197
|
+
apiRoutes: [
|
|
198
|
+
{ path: 'src/app/api/contact/route.ts', purpose: 'Handles inquiries with RFC 7807 validation' },
|
|
199
|
+
{ path: 'src/app/api/data/route.ts', purpose: 'Serves dynamic domain entities & filtering' }
|
|
200
|
+
]
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Helper: Builds domain-specific section hierarchy
|
|
206
|
+
*/
|
|
207
|
+
buildSectionTopology(domain, name, headline, summary, features) {
|
|
208
|
+
if (domain === 'portfolio') {
|
|
209
|
+
return [
|
|
210
|
+
{ id: 'navbar', component: 'Navbar', title: name, navLinks: ['Projects', 'Console', 'Timeline', 'Contact'] },
|
|
211
|
+
{ id: 'hero', component: 'Hero', headline: "Architecting high-order distributed systems & kinetic web platforms.", subheadline: summary, primaryCta: "Explore Selected Works", secondaryCta: "Launch Interactive Shell" },
|
|
212
|
+
{ id: 'projects', component: 'ProjectsGrid', title: "Selected Works & Architectures", categories: ["All", "Distributed Systems", "AI & RAG", "Frontend Islands", "Open Source"] },
|
|
213
|
+
{ id: 'terminal', component: 'TerminalBio', title: "Interactive Developer Shell", subtitle: "Type `skills`, `architecture`, `experience`, or `contact`" },
|
|
214
|
+
{ id: 'experience', component: 'ExperienceTimeline', title: "Career & Technical Milestones" },
|
|
215
|
+
{ id: 'contact', component: 'ContactSection', title: "Let's build something exceptional together.", email: "alex@example.com" }
|
|
216
|
+
];
|
|
217
|
+
} else if (domain === 'restaurant') {
|
|
218
|
+
return [
|
|
219
|
+
{ id: 'navbar', component: 'Navbar', title: name, navLinks: ['Tasting Menu', 'Philosophy', 'Private Dining', 'Reservations'] },
|
|
220
|
+
{ id: 'hero', component: 'Hero', headline: "Hyper-seasonal gastronomy rooted in botanical exploration.", subheadline: summary, primaryCta: "Reserve a Table", secondaryCta: "View Seasonal Menu" },
|
|
221
|
+
{ id: 'tasting-menu', component: 'TastingMenu', title: "Autumn Tasting Course", categories: ["All", "First Course", "Main Course", "Dessert", "Wine Pairings"] },
|
|
222
|
+
{ id: 'philosophy', component: 'ChefPhilosophy', title: "From Soil to Plate", quote: "We cook not to impress, but to connect guests with the untamed landscape." },
|
|
223
|
+
{ id: 'reservation', component: 'ReservationSection', title: "Join Us at the Table", cta: "Book Reservation" }
|
|
224
|
+
];
|
|
225
|
+
} else {
|
|
226
|
+
return [
|
|
227
|
+
{ id: 'navbar', component: 'Navbar', title: name, navLinks: ['Capabilities', 'Architecture', 'Throughput', 'Contact'] },
|
|
228
|
+
{ id: 'hero', component: 'Hero', headline: headline, subheadline: summary, primaryCta: "Launch Interactive Sandbox", secondaryCta: "Explore Specs" },
|
|
229
|
+
{ id: 'showcase', component: 'BentoShowcase', title: "Engineered from First Principles", cards: 4 },
|
|
230
|
+
{ id: 'interactive', component: 'InteractiveCalculator', title: "Performance ROI Calculator" },
|
|
231
|
+
{ id: 'contact', component: 'ContactSection', title: "Deploy Modern Architecture", email: "team@example.com" }
|
|
232
|
+
];
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Step 3: Create Dynamic Task Graph (DAG)
|
|
238
|
+
*/
|
|
239
|
+
createTaskGraph(spec) {
|
|
240
|
+
const tasks = [
|
|
241
|
+
{
|
|
242
|
+
id: 'task-plan',
|
|
243
|
+
agentId: 'orchestrator',
|
|
244
|
+
name: 'Project Requirement Analysis & DAG Compilation',
|
|
245
|
+
task: `Deconstruct brief for ${spec.domain.toUpperCase()} project into modular task DAG`,
|
|
246
|
+
skills: ['frontend/nextjs'],
|
|
247
|
+
dependsOn: [],
|
|
248
|
+
status: 'queued'
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
id: 'task-design-director',
|
|
252
|
+
agentId: 'creativeDirector',
|
|
253
|
+
name: 'Visual Direction & Anti-AI Guardian Strategy',
|
|
254
|
+
task: `Formulate authentic visual personality, fluid clamp typography, and ban purple gradients & repetitive cards`,
|
|
255
|
+
skills: ['design/ui-design', 'design/typography', 'anti-ai/slop-guardian'],
|
|
256
|
+
dependsOn: ['task-plan'],
|
|
257
|
+
status: 'queued'
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
id: 'task-content-strategist',
|
|
261
|
+
agentId: 'contentStrategist',
|
|
262
|
+
name: 'Grounded Technical Copywriting & Domain Data',
|
|
263
|
+
task: `Author bespoke domain fixtures and technical value props with zero placeholder cliché copy`,
|
|
264
|
+
skills: ['content/copywriting', 'backend/data-models'],
|
|
265
|
+
dependsOn: ['task-plan'],
|
|
266
|
+
status: 'queued'
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
id: 'task-frontend-scaffold',
|
|
270
|
+
agentId: 'frontend',
|
|
271
|
+
name: 'Next.js 14/15 App Router Scaffolding & Root Layout',
|
|
272
|
+
task: `Synthesize package.json, tsconfig.json, tailwind.config.ts, src/app/layout.tsx, and globals.css`,
|
|
273
|
+
skills: ['frontend/nextjs', 'frontend/react', 'frontend/tailwind'],
|
|
274
|
+
dependsOn: ['task-design-director'],
|
|
275
|
+
status: 'queued'
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
id: 'task-frontend-components',
|
|
279
|
+
agentId: 'frontend',
|
|
280
|
+
name: 'Bespoke Asymmetric Section Components & Pages',
|
|
281
|
+
task: `Build src/app/page.tsx and all section components (${spec.sections.map(s => s.component).join(', ')})`,
|
|
282
|
+
skills: ['frontend/nextjs', 'frontend/react', 'design/ui-design'],
|
|
283
|
+
dependsOn: ['task-frontend-scaffold', 'task-content-strategist'],
|
|
284
|
+
status: 'queued'
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
id: 'task-backend-routes',
|
|
288
|
+
agentId: 'backend',
|
|
289
|
+
name: 'TypeScript API Route Handlers & Data Contract',
|
|
290
|
+
task: `Synthesize src/app/api/contact/route.ts and src/app/api/data/route.ts with RFC 7807 validation`,
|
|
291
|
+
skills: ['backend/route-handlers', 'backend/data-models'],
|
|
292
|
+
dependsOn: ['task-frontend-scaffold'],
|
|
293
|
+
status: 'queued'
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
id: 'task-animation-motion',
|
|
297
|
+
agentId: 'animationSpecialist',
|
|
298
|
+
name: 'Framer Motion Transitions & Interactive Micro-Interactions',
|
|
299
|
+
task: `Add smooth reveal choreography, interactive category filtering, and terminal emulator logic`,
|
|
300
|
+
skills: ['motion/framer-motion', 'motion/micro-interactions'],
|
|
301
|
+
dependsOn: ['task-frontend-components'],
|
|
302
|
+
status: 'queued'
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
id: 'task-responsive-specialist',
|
|
306
|
+
agentId: 'responsiveSpecialist',
|
|
307
|
+
name: 'Responsive Viewport Optimization & Layout Integrity',
|
|
308
|
+
task: `Ensure zero horizontal scroll, fluid clamp() font scaling, and touch target sizing`,
|
|
309
|
+
skills: ['quality/responsive-design', 'frontend/accessibility'],
|
|
310
|
+
dependsOn: ['task-frontend-components'],
|
|
311
|
+
status: 'queued'
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
id: 'task-qa-visual-critic',
|
|
315
|
+
agentId: 'visualCritic',
|
|
316
|
+
name: 'Anti-AI Rubric Review & Build Verification',
|
|
317
|
+
task: `Audit generated codebase against 6-dimension Anti-AI rubric and verify final threshold >= 8.5/10`,
|
|
318
|
+
skills: ['quality/visual-review', 'quality/browser-testing'],
|
|
319
|
+
dependsOn: ['task-animation-motion', 'task-responsive-specialist', 'task-backend-routes'],
|
|
320
|
+
status: 'queued'
|
|
321
|
+
}
|
|
322
|
+
];
|
|
323
|
+
|
|
324
|
+
return {
|
|
325
|
+
spec,
|
|
326
|
+
tasks
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PIXEL CREW — Modular Skill Registry
|
|
3
|
+
*
|
|
4
|
+
* Reusable capability definitions across Frontend, Design, Motion, Quality, Backend, and Content.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const SKILL_DEFINITIONS = {
|
|
8
|
+
// Frontend Skills
|
|
9
|
+
'frontend/nextjs': {
|
|
10
|
+
id: 'frontend/nextjs',
|
|
11
|
+
name: 'Next.js 14/15 App Router',
|
|
12
|
+
category: 'frontend',
|
|
13
|
+
description: 'Server Components, Streaming SSR, Layout hierarchy, and Metadata APIs',
|
|
14
|
+
targetAgents: ['frontend']
|
|
15
|
+
},
|
|
16
|
+
'frontend/react': {
|
|
17
|
+
id: 'frontend/react',
|
|
18
|
+
name: 'React 18/19 Primitives',
|
|
19
|
+
category: 'frontend',
|
|
20
|
+
description: 'Custom React hooks, client-side state management, and component islands',
|
|
21
|
+
targetAgents: ['frontend']
|
|
22
|
+
},
|
|
23
|
+
'frontend/tailwind': {
|
|
24
|
+
id: 'frontend/tailwind',
|
|
25
|
+
name: 'Tailwind CSS & Token System',
|
|
26
|
+
category: 'frontend',
|
|
27
|
+
description: 'Utility-first styling, design token mapping, fluid clamp scales, and dark mode',
|
|
28
|
+
targetAgents: ['frontend', 'designSystem']
|
|
29
|
+
},
|
|
30
|
+
'frontend/accessibility': {
|
|
31
|
+
id: 'frontend/accessibility',
|
|
32
|
+
name: 'WCAG 2.1 AA/AAA Accessibility',
|
|
33
|
+
category: 'frontend',
|
|
34
|
+
description: 'ARIA landmarks, keyboard focus management, and color contrast compliance',
|
|
35
|
+
targetAgents: ['frontend', 'qa']
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
// Design Skills
|
|
39
|
+
'design/ui-design': {
|
|
40
|
+
id: 'design/ui-design',
|
|
41
|
+
name: 'Bespoke UI & Asymmetric Layouts',
|
|
42
|
+
category: 'design',
|
|
43
|
+
description: 'High-contrast visual hierarchy, intentional whitespace, and Bento grid topologies',
|
|
44
|
+
targetAgents: ['creativeDirector', 'uxPlanner']
|
|
45
|
+
},
|
|
46
|
+
'design/typography': {
|
|
47
|
+
id: 'design/typography',
|
|
48
|
+
name: 'Expressive Typography Scales',
|
|
49
|
+
category: 'design',
|
|
50
|
+
description: 'Mathematical fluid clamp() type scales, display serif and geometric sans pairings',
|
|
51
|
+
targetAgents: ['creativeDirector', 'designSystem']
|
|
52
|
+
},
|
|
53
|
+
'design/design-system': {
|
|
54
|
+
id: 'design/design-system',
|
|
55
|
+
name: 'Design System Architecture',
|
|
56
|
+
category: 'design',
|
|
57
|
+
description: 'CSS Custom Properties, HSL color tokens, surface elevation tiers, and borders',
|
|
58
|
+
targetAgents: ['designSystem']
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
// Motion & Animation Skills
|
|
62
|
+
'motion/framer-motion': {
|
|
63
|
+
id: 'motion/framer-motion',
|
|
64
|
+
name: 'Framer Motion & View Transitions',
|
|
65
|
+
category: 'motion',
|
|
66
|
+
description: 'Smooth scroll-driven reveals, staggered entrance choreography, and gesture physics',
|
|
67
|
+
targetAgents: ['animationSpecialist', 'frontend']
|
|
68
|
+
},
|
|
69
|
+
'motion/micro-interactions': {
|
|
70
|
+
id: 'motion/micro-interactions',
|
|
71
|
+
name: 'Interactive Micro-Interactions',
|
|
72
|
+
category: 'motion',
|
|
73
|
+
description: 'Hover states, magnetic buttons, live filter transitions, and interactive terminal state',
|
|
74
|
+
targetAgents: ['animationSpecialist', 'frontend']
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
// Quality & Review Skills
|
|
78
|
+
'quality/responsive-design': {
|
|
79
|
+
id: 'quality/responsive-design',
|
|
80
|
+
name: 'Adaptive Responsive Design',
|
|
81
|
+
category: 'quality',
|
|
82
|
+
description: 'Fluid viewports from 360px mobile to 4K desktop with zero horizontal overflow',
|
|
83
|
+
targetAgents: ['responsiveSpecialist', 'frontend']
|
|
84
|
+
},
|
|
85
|
+
'quality/visual-review': {
|
|
86
|
+
id: 'quality/visual-review',
|
|
87
|
+
name: '6-Dimension Anti-AI Rubric Review',
|
|
88
|
+
category: 'quality',
|
|
89
|
+
description: 'Originality, Typography, Layout, Hierarchy, Brand Consistency, and AI Slop Penalty audit',
|
|
90
|
+
targetAgents: ['visualCritic', 'qa']
|
|
91
|
+
},
|
|
92
|
+
'quality/browser-testing': {
|
|
93
|
+
id: 'quality/browser-testing',
|
|
94
|
+
name: 'Build Verification & Smoke Testing',
|
|
95
|
+
category: 'quality',
|
|
96
|
+
description: 'Syntax validation, TypeScript type-checking, and layout integrity checks',
|
|
97
|
+
targetAgents: ['qa']
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
// Backend & Data Skills
|
|
101
|
+
'backend/route-handlers': {
|
|
102
|
+
id: 'backend/route-handlers',
|
|
103
|
+
name: 'TypeScript Route Handlers',
|
|
104
|
+
category: 'backend',
|
|
105
|
+
description: 'Next.js App Router API routes, JSON schema validation, and RFC 7807 error envelopes',
|
|
106
|
+
targetAgents: ['backend']
|
|
107
|
+
},
|
|
108
|
+
'backend/data-models': {
|
|
109
|
+
id: 'backend/data-models',
|
|
110
|
+
name: 'Structured Data Modeling',
|
|
111
|
+
category: 'backend',
|
|
112
|
+
description: 'Domain entities, TypeScript interfaces, and static fixtures',
|
|
113
|
+
targetAgents: ['backend', 'database']
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
// Content & Anti-AI Skills
|
|
117
|
+
'content/copywriting': {
|
|
118
|
+
id: 'content/copywriting',
|
|
119
|
+
name: 'Grounded Technical Copywriting',
|
|
120
|
+
category: 'content',
|
|
121
|
+
description: 'Zero AI cliché copy, authentic product propositions, and real technical metrics',
|
|
122
|
+
targetAgents: ['contentStrategist', 'uxPlanner']
|
|
123
|
+
},
|
|
124
|
+
'anti-ai/slop-guardian': {
|
|
125
|
+
id: 'anti-ai/slop-guardian',
|
|
126
|
+
name: 'Anti-AI Pattern Detection Guardian',
|
|
127
|
+
category: 'quality',
|
|
128
|
+
description: 'Bans purple/blue mesh gradient blobs, repeating 3-card grids, and fake AI sparkles',
|
|
129
|
+
targetAgents: ['creativeDirector', 'visualCritic']
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export class SkillRegistry {
|
|
134
|
+
constructor() {
|
|
135
|
+
this.skills = new Map(Object.entries(SKILL_DEFINITIONS));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
getSkill(skillId) {
|
|
139
|
+
return this.skills.get(skillId) || null;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
getAllSkills() {
|
|
143
|
+
return Array.from(this.skills.values());
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
getSkillsByCategory(category) {
|
|
147
|
+
return Array.from(this.skills.values()).filter(s => s.category === category);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Matches task requirements to skill IDs
|
|
152
|
+
*/
|
|
153
|
+
matchSkills(taskRequirement) {
|
|
154
|
+
const text = (taskRequirement || '').toLowerCase();
|
|
155
|
+
const matched = new Set();
|
|
156
|
+
|
|
157
|
+
if (text.includes('next') || text.includes('component') || text.includes('page')) {
|
|
158
|
+
matched.add('frontend/nextjs');
|
|
159
|
+
matched.add('frontend/react');
|
|
160
|
+
matched.add('frontend/tailwind');
|
|
161
|
+
}
|
|
162
|
+
if (text.includes('design') || text.includes('visual') || text.includes('artistic')) {
|
|
163
|
+
matched.add('design/ui-design');
|
|
164
|
+
matched.add('design/typography');
|
|
165
|
+
matched.add('design/design-system');
|
|
166
|
+
matched.add('anti-ai/slop-guardian');
|
|
167
|
+
}
|
|
168
|
+
if (text.includes('animation') || text.includes('motion') || text.includes('interaction')) {
|
|
169
|
+
matched.add('motion/framer-motion');
|
|
170
|
+
matched.add('motion/micro-interactions');
|
|
171
|
+
}
|
|
172
|
+
if (text.includes('responsive') || text.includes('mobile') || text.includes('tablet')) {
|
|
173
|
+
matched.add('quality/responsive-design');
|
|
174
|
+
}
|
|
175
|
+
if (text.includes('api') || text.includes('backend') || text.includes('route')) {
|
|
176
|
+
matched.add('backend/route-handlers');
|
|
177
|
+
matched.add('backend/data-models');
|
|
178
|
+
}
|
|
179
|
+
if (text.includes('qa') || text.includes('test') || text.includes('review') || text.includes('rubric')) {
|
|
180
|
+
matched.add('quality/visual-review');
|
|
181
|
+
matched.add('quality/browser-testing');
|
|
182
|
+
}
|
|
183
|
+
if (text.includes('copy') || text.includes('content') || text.includes('text')) {
|
|
184
|
+
matched.add('content/copywriting');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (matched.size === 0) {
|
|
188
|
+
matched.add('frontend/nextjs');
|
|
189
|
+
matched.add('frontend/tailwind');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return Array.from(matched);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PIXEL CREW — Autonomous Agent Runtime & DAG Task Queue
|
|
3
|
+
*
|
|
4
|
+
* Manages dynamic DAG task scheduling, parallel execution, and granular event streaming.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { EventEmitter } from 'node:events';
|
|
8
|
+
|
|
9
|
+
export class TaskQueue extends EventEmitter {
|
|
10
|
+
constructor(tasks = []) {
|
|
11
|
+
super();
|
|
12
|
+
this.tasks = new Map(tasks.map(t => [t.id, { ...t }]));
|
|
13
|
+
this.completedTasks = new Set();
|
|
14
|
+
this.runningTasks = new Set();
|
|
15
|
+
this.failedTasks = new Set();
|
|
16
|
+
this.history = [];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Retrieves all tasks currently ready for execution
|
|
21
|
+
* (all dependencies completed and task is currently queued)
|
|
22
|
+
*/
|
|
23
|
+
getReadyTasks() {
|
|
24
|
+
const ready = [];
|
|
25
|
+
for (const [id, task] of this.tasks.entries()) {
|
|
26
|
+
if (task.status === 'queued') {
|
|
27
|
+
const depsMet = task.dependsOn.every(depId => this.completedTasks.has(depId));
|
|
28
|
+
if (depsMet) {
|
|
29
|
+
ready.push(task);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return ready;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
isCompleted() {
|
|
37
|
+
return this.tasks.size === this.completedTasks.size;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
hasFailed() {
|
|
41
|
+
return this.failedTasks.size > 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Executes the entire DAG with autonomous agent dispatching
|
|
46
|
+
*/
|
|
47
|
+
async execute(runtimeContext = {}, onEvent = () => {}) {
|
|
48
|
+
const emit = (event) => {
|
|
49
|
+
this.history.push(event);
|
|
50
|
+
this.emit('event', event);
|
|
51
|
+
onEvent(event);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
while (!this.isCompleted() && !this.hasFailed()) {
|
|
55
|
+
const readyTasks = this.getReadyTasks();
|
|
56
|
+
|
|
57
|
+
if (readyTasks.length === 0 && this.runningTasks.size === 0) {
|
|
58
|
+
throw new Error('Deadlock detected in Task Graph: cyclic dependency or unmet prerequisite');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Execute all ready tasks in parallel batch
|
|
62
|
+
const promises = readyTasks.map(async (task) => {
|
|
63
|
+
task.status = 'running';
|
|
64
|
+
this.runningTasks.add(task.id);
|
|
65
|
+
|
|
66
|
+
emit({
|
|
67
|
+
type: 'agent.started',
|
|
68
|
+
agent: task.agentId,
|
|
69
|
+
taskId: task.id,
|
|
70
|
+
taskName: task.name,
|
|
71
|
+
message: `Workstation activated for: ${task.name}`
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Activate required skills
|
|
75
|
+
for (const skill of task.skills) {
|
|
76
|
+
emit({
|
|
77
|
+
type: 'skill.activated',
|
|
78
|
+
agent: task.agentId,
|
|
79
|
+
taskId: task.id,
|
|
80
|
+
skill,
|
|
81
|
+
message: `Applying skill: ${skill}`
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Execute actual agent task payload if handler exists
|
|
86
|
+
if (runtimeContext.executeTaskHandler) {
|
|
87
|
+
try {
|
|
88
|
+
await runtimeContext.executeTaskHandler(task, emit);
|
|
89
|
+
} catch (err) {
|
|
90
|
+
task.status = 'failed';
|
|
91
|
+
this.failedTasks.add(task.id);
|
|
92
|
+
this.runningTasks.delete(task.id);
|
|
93
|
+
emit({
|
|
94
|
+
type: 'task.failed',
|
|
95
|
+
agent: task.agentId,
|
|
96
|
+
taskId: task.id,
|
|
97
|
+
error: err.message
|
|
98
|
+
});
|
|
99
|
+
throw err;
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
await new Promise(r => setTimeout(r, 400));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
task.status = 'completed';
|
|
106
|
+
this.runningTasks.delete(task.id);
|
|
107
|
+
this.completedTasks.add(task.id);
|
|
108
|
+
|
|
109
|
+
emit({
|
|
110
|
+
type: 'task.completed',
|
|
111
|
+
agent: task.agentId,
|
|
112
|
+
taskId: task.id,
|
|
113
|
+
taskName: task.name,
|
|
114
|
+
message: `Completed: ${task.name}`
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
await Promise.all(promises);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
success: !this.hasFailed(),
|
|
123
|
+
completedCount: this.completedTasks.size,
|
|
124
|
+
totalTasks: this.tasks.size,
|
|
125
|
+
history: this.history
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
package/src/server/server.js
CHANGED
|
@@ -4,8 +4,15 @@ import fsSync from 'node:fs';
|
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
6
|
|
|
7
|
-
export function createServer(
|
|
8
|
-
|
|
7
|
+
export function createServer(engineOrRootDir, maybeEngine, options = {}) {
|
|
8
|
+
let engine = engineOrRootDir;
|
|
9
|
+
let rootDir = engine?.rootDir || process.cwd();
|
|
10
|
+
|
|
11
|
+
if (typeof engineOrRootDir === 'string') {
|
|
12
|
+
rootDir = engineOrRootDir;
|
|
13
|
+
engine = maybeEngine;
|
|
14
|
+
}
|
|
15
|
+
|
|
9
16
|
const dashboardDir = path.join(rootDir, '.pixel-agents', 'dashboard');
|
|
10
17
|
const legacyDashboardDir = path.join(rootDir, '.pixel-dashboard');
|
|
11
18
|
const fallbackDashboardDir = fileURLToPath(new URL('../dashboard', import.meta.url));
|