pixelcrew 0.2.3 โ 0.2.6
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/README.md +389 -315
- package/bin/pixel-agents.js +306 -149
- package/package.json +3 -1
- package/skill/SKILL.md +185 -0
- package/skill/references/anti-ai-rubric.md +30 -0
- package/skill/references/anti-ai-slop-encyclopedia.md +181 -0
- package/skill/references/commands-reference.md +135 -0
- package/skill/references/testing-and-qa-strategy.md +25 -0
- package/skill/references/token-efficiency.md +20 -0
- package/src/adapters/adapter.interface.js +77 -0
- package/src/adapters/antigravity.js +138 -0
- package/src/adapters/claude-code.js +149 -0
- package/src/adapters/codex.js +131 -0
- package/src/adapters/cursor.js +133 -0
- package/src/adapters/generic.js +63 -0
- package/src/adapters/index.js +15 -0
- package/src/adapters/kiro.js +134 -0
- package/src/adapters/registry.js +150 -0
- package/src/backend/analyzer/complexity-analyzer.js +104 -0
- package/src/backend/analyzer/requirement-analyzer.js +213 -0
- package/src/backend/analyzer/threat-analyzer.js +122 -0
- package/src/backend/api/api-designer.js +90 -0
- package/src/backend/api/error-contract.js +132 -0
- package/src/backend/api/route-generator.js +92 -0
- package/src/backend/api/schema-generator.js +64 -0
- package/src/backend/architecture/adr-generator.js +62 -0
- package/src/backend/architecture/architecture-reasoner.js +119 -0
- package/src/backend/architecture/architecture-selector.js +57 -0
- package/src/backend/architecture/tradeoff-analyzer.js +92 -0
- package/src/backend/data/data-modeler.js +114 -0
- package/src/backend/data/index-analyzer.js +93 -0
- package/src/backend/data/query-analyzer.js +41 -0
- package/src/backend/data/schema-generator.js +92 -0
- package/src/backend/data/transaction-analyzer.js +49 -0
- package/src/backend/index.js +67 -0
- package/src/backend/observability/logging-engine.js +80 -0
- package/src/backend/observability/metrics-engine.js +31 -0
- package/src/backend/observability/tracing-engine.js +16 -0
- package/src/backend/patterns/pattern-registry.js +74 -0
- package/src/backend/patterns/pattern-selector.js +39 -0
- package/src/backend/patterns/tradeoff-engine.js +17 -0
- package/src/backend/performance/cache-analyzer.js +31 -0
- package/src/backend/performance/concurrency-analyzer.js +34 -0
- package/src/backend/performance/performance-engine.js +98 -0
- package/src/backend/performance/query-optimizer.js +16 -0
- package/src/backend/reliability/failure-analyzer.js +22 -0
- package/src/backend/reliability/idempotency-engine.js +56 -0
- package/src/backend/reliability/resilience-engine.js +141 -0
- package/src/backend/reliability/retry-analyzer.js +15 -0
- package/src/backend/security/auth-selector.js +33 -0
- package/src/backend/security/authorization-engine.js +90 -0
- package/src/backend/security/policy-engine.js +49 -0
- package/src/backend/security/secret-analyzer.js +39 -0
- package/src/backend/security/security-engine.js +122 -0
- package/src/backend/security/threat-model.js +59 -0
- package/src/backend/synthesis/backend-synthesizer.js +98 -0
- package/src/backend/synthesis/infrastructure-synthesizer.js +108 -0
- package/src/backend/synthesis/module-synthesizer.js +262 -0
- package/src/backend/validation/architecture-validator.js +70 -0
- package/src/backend/validation/backend-quality-validator.js +71 -0
- package/src/backend/validation/dependency-validator.js +20 -0
- package/src/backend/validation/performance-validator.js +38 -0
- package/src/backend/validation/security-validator.js +73 -0
- package/src/commands/adapt.js +105 -0
- package/src/commands/add.js +78 -0
- package/src/commands/animate.js +48 -0
- package/src/commands/assemble.js +57 -0
- package/src/commands/audit.js +93 -0
- package/src/commands/backend.js +125 -0
- package/src/commands/bento.js +25 -0
- package/src/commands/blueprint.js +65 -0
- package/src/commands/bolder.js +48 -0
- package/src/commands/boss-fight.js +60 -0
- package/src/commands/build.js +39 -0
- package/src/commands/calibrate.js +25 -0
- package/src/commands/chromatic.js +25 -0
- package/src/commands/clarify.js +52 -0
- package/src/commands/colorize.js +57 -0
- package/src/commands/command.interface.js +28 -0
- package/src/commands/commands.js +84 -0
- package/src/commands/craft.js +57 -0
- package/src/commands/crew.js +66 -0
- package/src/commands/critique.js +25 -0
- package/src/commands/de-slop.js +25 -0
- package/src/commands/delight.js +46 -0
- package/src/commands/deploy.js +42 -0
- package/src/commands/distill.js +48 -0
- package/src/commands/doctor.js +89 -0
- package/src/commands/document.js +83 -0
- package/src/commands/eight-bit.js +25 -0
- package/src/commands/extract.js +75 -0
- package/src/commands/fix.js +46 -0
- package/src/commands/harden.js +85 -0
- package/src/commands/index.js +67 -0
- package/src/commands/install.js +75 -0
- package/src/commands/layout.js +48 -0
- package/src/commands/live.js +44 -0
- package/src/commands/manifest.js +25 -0
- package/src/commands/office.js +25 -0
- package/src/commands/onboard.js +46 -0
- package/src/commands/oneshot.js +60 -0
- package/src/commands/optimize.js +46 -0
- package/src/commands/overdrive.js +46 -0
- package/src/commands/parser.js +143 -0
- package/src/commands/pixelcrew.js +96 -0
- package/src/commands/plan.js +66 -0
- package/src/commands/polish.js +45 -0
- package/src/commands/quieter.js +48 -0
- package/src/commands/recap.js +358 -0
- package/src/commands/registry.js +353 -0
- package/src/commands/render.js +26 -0
- package/src/commands/retrofit.js +25 -0
- package/src/commands/review.js +118 -0
- package/src/commands/roster.js +25 -0
- package/src/commands/sentinel.js +25 -0
- package/src/commands/shape.js +66 -0
- package/src/commands/skills.js +57 -0
- package/src/commands/status.js +48 -0
- package/src/commands/stop.js +50 -0
- package/src/commands/sync.js +58 -0
- package/src/commands/typeset.js +58 -0
- package/src/commands/warp.js +25 -0
- package/src/core/agent-runtime.js +94 -0
- package/src/core/event-bus.js +98 -0
- package/src/core/index.js +9 -0
- package/src/core/orchestrator.js +234 -0
- package/src/core/scheduler.js +124 -0
- package/src/core/task-graph.js +185 -0
- package/src/dashboard/app.js +1172 -30
- package/src/dashboard/index.html +223 -23
- package/src/dashboard/styles.css +870 -0
- package/src/index.js +16 -0
- package/src/orchestrator/artifact-graph.js +104 -0
- package/src/orchestrator/ast-normalizer.js +147 -0
- package/src/orchestrator/code-generator.js +632 -780
- package/src/orchestrator/design-engine.js +203 -0
- package/src/orchestrator/engine.js +307 -38
- package/src/orchestrator/oneshot.js +367 -380
- package/src/orchestrator/ontology.js +394 -0
- package/src/orchestrator/planner.js +231 -258
- package/src/orchestrator/repair-planner.js +67 -0
- package/src/orchestrator/requirement-contract.js +177 -0
- package/src/orchestrator/requirement-validator.js +39 -0
- package/src/orchestrator/semantic-engine.js +582 -0
- package/src/orchestrator/semantic-reviewer.js +179 -0
- package/src/orchestrator/task-planner.js +111 -0
- package/src/orchestrator/telemetry.js +209 -0
- package/src/orchestrator/ui-synthesizer.js +245 -0
- package/src/orchestrator/visual-critic.js +106 -0
- package/src/policies/architecture/layering.policy.js +14 -0
- package/src/policies/performance/indexing.policy.js +13 -0
- package/src/policies/reliability/resilience.policy.js +13 -0
- package/src/policies/security/auth.policy.js +31 -0
- package/src/protocol/agent.js +124 -0
- package/src/protocol/event.js +78 -0
- package/src/protocol/index.js +8 -0
- package/src/protocol/skill.js +54 -0
- package/src/protocol/task.js +100 -0
- package/src/scaffold/claude-generator.js +60 -0
- package/src/scaffold/commands-catalog.js +321 -0
- package/src/scaffold/cursor-generator.js +74 -0
- package/src/scaffold/ide-rules.js +133 -0
- package/src/scaffold/init.js +415 -91
- package/src/scaffold/installer.js +571 -0
- package/src/scaffold/kiro-generator.js +86 -0
- package/src/scaffold/skills-bundle.js +520 -0
- package/src/scaffold/templates.js +57 -4
- package/src/scaffold/workstations.js +364 -0
- package/src/server/server.js +283 -40
- package/src/utils/fs-safe.js +168 -0
- package/src/utils/markdown-report.js +175 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PIXEL CREW โ Open-World UI Synthesizer
|
|
3
|
+
*
|
|
4
|
+
* Compiles ViewDefinition + EntityDefinition + DesignSpec into high-fidelity,
|
|
5
|
+
* fully interactive React 18/19 Next.js App Router TSX components.
|
|
6
|
+
*
|
|
7
|
+
* Works for ANY domain dynamically by composing universal UI primitives
|
|
8
|
+
* (Collection, Table, Form, Timeline, Inspector, Search, Filter).
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { LAYOUT_PRIMITIVES } from './ontology.js';
|
|
12
|
+
|
|
13
|
+
export class UISynthesizer {
|
|
14
|
+
/**
|
|
15
|
+
* Synthesize a complete TSX component file from a ViewDefinition and its target entities.
|
|
16
|
+
*/
|
|
17
|
+
static synthesizeViewComponent(view, entities = [], designSpec = {}) {
|
|
18
|
+
const compName = view.componentName || 'DynamicView';
|
|
19
|
+
const targetEntityName = (view.targetEntities && view.targetEntities[0]) || (entities[0] ? entities[0].name : 'Item');
|
|
20
|
+
const entity = entities.find(e => e.name === targetEntityName) || entities[0] || {
|
|
21
|
+
name: targetEntityName,
|
|
22
|
+
title: targetEntityName,
|
|
23
|
+
fields: [
|
|
24
|
+
{ name: 'id', type: 'string', label: 'ID' },
|
|
25
|
+
{ name: 'name', type: 'string', label: 'Name' },
|
|
26
|
+
{ name: 'status', type: 'string', label: 'Status' }
|
|
27
|
+
],
|
|
28
|
+
seedData: []
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const fields = entity.fields || [];
|
|
32
|
+
const seedData = entity.seedData || [];
|
|
33
|
+
const layoutType = (view.layout && view.layout.type) || LAYOUT_PRIMITIVES.SPLIT;
|
|
34
|
+
|
|
35
|
+
const isSplit = layoutType === LAYOUT_PRIMITIVES.SPLIT || layoutType === LAYOUT_PRIMITIVES.WORKSPACE;
|
|
36
|
+
|
|
37
|
+
return `'use client';
|
|
38
|
+
|
|
39
|
+
import React, { useState } from 'react';
|
|
40
|
+
import { Search, Filter, Plus, ArrowUpRight, CheckCircle2, AlertCircle, RefreshCw, Download, Database } from 'lucide-react';
|
|
41
|
+
|
|
42
|
+
export interface ${entity.name}Record {
|
|
43
|
+
${fields.map(f => ` ${f.name}${f.required ? '' : '?'}: ${f.type === 'number' ? 'number' : (f.type === 'boolean' ? 'boolean' : 'string')};`).join('\n')}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const INITIAL_RECORDS: ${entity.name}Record[] = ${JSON.stringify(seedData, null, 2)};
|
|
47
|
+
|
|
48
|
+
export function ${compName}() {
|
|
49
|
+
const [records, setRecords] = useState<${entity.name}Record[]>(INITIAL_RECORDS);
|
|
50
|
+
const [searchQuery, setSearchQuery] = useState('');
|
|
51
|
+
const [selectedStatus, setSelectedStatus] = useState<string>('ALL');
|
|
52
|
+
const [selectedRecord, setSelectedRecord] = useState<${entity.name}Record | null>(INITIAL_RECORDS[0] || null);
|
|
53
|
+
const [isCreating, setIsCreating] = useState(false);
|
|
54
|
+
const [newTitle, setNewTitle] = useState('');
|
|
55
|
+
|
|
56
|
+
const statuses = ['ALL', ...Array.from(new Set(records.map(r => r.status).filter(Boolean)))];
|
|
57
|
+
|
|
58
|
+
const filteredRecords = records.filter(record => {
|
|
59
|
+
const matchesSearch = !searchQuery ||
|
|
60
|
+
(record.name && record.name.toLowerCase().includes(searchQuery.toLowerCase())) ||
|
|
61
|
+
(record.id && record.id.toLowerCase().includes(searchQuery.toLowerCase()));
|
|
62
|
+
const matchesStatus = selectedStatus === 'ALL' || record.status === selectedStatus;
|
|
63
|
+
return matchesSearch && matchesStatus;
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const handleCreate = (e: React.FormEvent) => {
|
|
67
|
+
e.preventDefault();
|
|
68
|
+
if (!newTitle.trim()) return;
|
|
69
|
+
const newEntry: ${entity.name}Record = {
|
|
70
|
+
id: '${entity.name.toLowerCase()}-' + String(records.length + 1).padStart(3, '0'),
|
|
71
|
+
name: newTitle.trim(),
|
|
72
|
+
status: 'Active',
|
|
73
|
+
createdAt: new Date().toISOString()
|
|
74
|
+
};
|
|
75
|
+
setRecords([newEntry, ...records]);
|
|
76
|
+
setSelectedRecord(newEntry);
|
|
77
|
+
setNewTitle('');
|
|
78
|
+
setIsCreating(false);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<section id="${view.id || compName.toLowerCase()}" className="py-16 px-6 max-w-7xl mx-auto border-b border-white/10">
|
|
83
|
+
{/* Header & Controls */}
|
|
84
|
+
<div className="flex flex-col md:flex-row md:items-end justify-between mb-8 gap-4">
|
|
85
|
+
<div>
|
|
86
|
+
<div className="text-xs font-mono text-neutral-400 uppercase tracking-widest mb-2">
|
|
87
|
+
// ${entity.name.toUpperCase()} REGISTRY & WORKSPACE
|
|
88
|
+
</div>
|
|
89
|
+
<h2 className="font-display text-2xl md:text-3xl text-white font-normal">
|
|
90
|
+
${view.title || `${entity.title || entity.name} Console`}
|
|
91
|
+
</h2>
|
|
92
|
+
<p className="text-sm text-neutral-400 mt-1 max-w-xl font-light">
|
|
93
|
+
${view.purpose || `Manage, inspect, and track real-time telemetry across ${entity.plural || entity.name}.`}
|
|
94
|
+
</p>
|
|
95
|
+
</div>
|
|
96
|
+
|
|
97
|
+
<div className="flex items-center gap-3">
|
|
98
|
+
<button
|
|
99
|
+
onClick={() => setIsCreating(!isCreating)}
|
|
100
|
+
className="flex items-center gap-2 px-4 py-2 bg-white text-black text-xs font-mono font-medium rounded-sm hover:bg-neutral-200 transition-colors"
|
|
101
|
+
>
|
|
102
|
+
<Plus className="w-3.5 h-3.5" />
|
|
103
|
+
New ${entity.name}
|
|
104
|
+
</button>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
{/* Quick Action Modal / Create Form */}
|
|
109
|
+
{isCreating && (
|
|
110
|
+
<form onSubmit={handleCreate} className="mb-8 p-4 bg-brandSurface border border-brandBorder rounded-sm flex items-center gap-4">
|
|
111
|
+
<input
|
|
112
|
+
type="text"
|
|
113
|
+
placeholder="Enter ${entity.name} identifier or name..."
|
|
114
|
+
value={newTitle}
|
|
115
|
+
onChange={(e) => setNewTitle(e.target.value)}
|
|
116
|
+
className="flex-1 bg-brandBg border border-brandBorder px-3 py-2 text-sm text-white rounded-sm focus:outline-none focus:border-white/40"
|
|
117
|
+
autoFocus
|
|
118
|
+
/>
|
|
119
|
+
<button
|
|
120
|
+
type="submit"
|
|
121
|
+
className="px-4 py-2 bg-emerald-500 text-black text-xs font-mono font-medium rounded-sm hover:bg-emerald-400 transition-colors"
|
|
122
|
+
>
|
|
123
|
+
Commit Entry
|
|
124
|
+
</button>
|
|
125
|
+
<button
|
|
126
|
+
type="button"
|
|
127
|
+
onClick={() => setIsCreating(false)}
|
|
128
|
+
className="px-3 py-2 text-xs font-mono text-neutral-400 hover:text-white"
|
|
129
|
+
>
|
|
130
|
+
Cancel
|
|
131
|
+
</button>
|
|
132
|
+
</form>
|
|
133
|
+
)}
|
|
134
|
+
|
|
135
|
+
{/* Filter Bar */}
|
|
136
|
+
<div className="flex flex-col sm:flex-row items-center justify-between gap-4 mb-6 p-3 bg-brandSurface/40 border border-brandBorder rounded-sm">
|
|
137
|
+
<div className="relative w-full sm:w-72">
|
|
138
|
+
<Search className="w-4 h-4 text-neutral-500 absolute left-3 top-2.5" />
|
|
139
|
+
<input
|
|
140
|
+
type="text"
|
|
141
|
+
placeholder="Filter records..."
|
|
142
|
+
value={searchQuery}
|
|
143
|
+
onChange={(e) => setSearchQuery(e.target.value)}
|
|
144
|
+
className="w-full bg-brandBg/80 border border-brandBorder pl-9 pr-3 py-1.5 text-xs text-white rounded-sm focus:outline-none focus:border-white/30"
|
|
145
|
+
/>
|
|
146
|
+
</div>
|
|
147
|
+
|
|
148
|
+
<div className="flex items-center gap-2 w-full sm:w-auto overflow-x-auto">
|
|
149
|
+
{statuses.map(st => (
|
|
150
|
+
<button
|
|
151
|
+
key={st}
|
|
152
|
+
onClick={() => setSelectedStatus(st)}
|
|
153
|
+
className={\`px-2.5 py-1 text-xs font-mono rounded-sm transition-colors border \${selectedStatus === st ? 'bg-white text-black border-white font-medium' : 'bg-brandBg text-neutral-400 border-brandBorder hover:text-white'}\`}
|
|
154
|
+
>
|
|
155
|
+
{st}
|
|
156
|
+
</button>
|
|
157
|
+
))}
|
|
158
|
+
</div>
|
|
159
|
+
</div>
|
|
160
|
+
|
|
161
|
+
{/* Main Workspace / View Content */}
|
|
162
|
+
<div className="${isSplit ? 'grid grid-cols-1 lg:grid-cols-12 gap-6' : 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6'}">
|
|
163
|
+
{/* Record List / Table */}
|
|
164
|
+
<div className="${isSplit ? 'lg:col-span-7' : 'col-span-full'} space-y-3">
|
|
165
|
+
{filteredRecords.length === 0 ? (
|
|
166
|
+
<div className="p-8 text-center bg-brandSurface/20 border border-dashed border-brandBorder rounded-sm text-neutral-400 text-xs font-mono">
|
|
167
|
+
No matching ${entity.plural || entity.name} records found.
|
|
168
|
+
</div>
|
|
169
|
+
) : (
|
|
170
|
+
filteredRecords.map(record => (
|
|
171
|
+
<div
|
|
172
|
+
key={record.id}
|
|
173
|
+
onClick={() => setSelectedRecord(record)}
|
|
174
|
+
className={\`p-4 rounded-sm border transition-all cursor-pointer \${selectedRecord?.id === record.id ? 'bg-brandSurfaceRaised border-white/40 shadow-sm' : 'bg-brandSurface border-brandBorder hover:border-brandBorderHover'}\`}
|
|
175
|
+
>
|
|
176
|
+
<div className="flex items-center justify-between mb-2">
|
|
177
|
+
<div className="flex items-center gap-3">
|
|
178
|
+
<span className="font-mono text-xs text-neutral-500">{record.id}</span>
|
|
179
|
+
<h3 className="text-sm font-medium text-white">{record.name}</h3>
|
|
180
|
+
</div>
|
|
181
|
+
<span className="text-[10px] font-mono uppercase px-2 py-0.5 rounded-sm bg-white/5 border border-white/10 text-neutral-300">
|
|
182
|
+
{record.status || 'Active'}
|
|
183
|
+
</span>
|
|
184
|
+
</div>
|
|
185
|
+
|
|
186
|
+
<div className="grid grid-cols-2 sm:grid-cols-3 gap-2 mt-3 pt-3 border-t border-white/5 text-xs text-neutral-400 font-mono">
|
|
187
|
+
${fields.filter(f => f.name !== 'id' && f.name !== 'name' && f.name !== 'status').slice(0, 3).map(f => `
|
|
188
|
+
<div>
|
|
189
|
+
<span className="text-neutral-500 block text-[10px]">${f.label}:</span>
|
|
190
|
+
<span className="text-neutral-200">{String((record as any)['${f.name}'] || 'โ')}</span>
|
|
191
|
+
</div>`).join('\n')}
|
|
192
|
+
</div>
|
|
193
|
+
</div>
|
|
194
|
+
))
|
|
195
|
+
)}
|
|
196
|
+
</div>
|
|
197
|
+
|
|
198
|
+
{/* Inspector Detail Panel (if split layout) */}
|
|
199
|
+
${isSplit ? `
|
|
200
|
+
<div className="lg:col-span-5 bg-brandSurface border border-brandBorder rounded-sm p-6 flex flex-col justify-between">
|
|
201
|
+
<div>
|
|
202
|
+
<div className="flex items-center justify-between pb-4 mb-4 border-b border-white/10">
|
|
203
|
+
<span className="text-xs font-mono text-neutral-400 uppercase tracking-wider">
|
|
204
|
+
Telemetry Inspector
|
|
205
|
+
</span>
|
|
206
|
+
<span className="text-[10px] font-mono text-emerald-400 bg-emerald-500/10 px-2 py-0.5 rounded border border-emerald-500/20">
|
|
207
|
+
Live Data Link
|
|
208
|
+
</span>
|
|
209
|
+
</div>
|
|
210
|
+
|
|
211
|
+
{selectedRecord ? (
|
|
212
|
+
<div className="space-y-4">
|
|
213
|
+
<div>
|
|
214
|
+
<h4 className="text-lg font-display text-white font-normal">{selectedRecord.name}</h4>
|
|
215
|
+
<span className="font-mono text-xs text-neutral-500 block mt-0.5">ID: {selectedRecord.id}</span>
|
|
216
|
+
</div>
|
|
217
|
+
|
|
218
|
+
<div className="space-y-3 pt-2">
|
|
219
|
+
${fields.map(f => `
|
|
220
|
+
<div className="flex items-center justify-between text-xs py-1.5 border-b border-white/5">
|
|
221
|
+
<span className="text-neutral-400 font-mono">${f.label}</span>
|
|
222
|
+
<span className="text-neutral-200 font-medium">{String((selectedRecord as any)['${f.name}'] ?? 'โ')}</span>
|
|
223
|
+
</div>`).join('\n')}
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
) : (
|
|
227
|
+
<div className="py-12 text-center text-neutral-500 text-xs font-mono">
|
|
228
|
+
Select a record from the registry to inspect parameters.
|
|
229
|
+
</div>
|
|
230
|
+
)}
|
|
231
|
+
</div>
|
|
232
|
+
|
|
233
|
+
<div className="pt-6 mt-6 border-t border-white/10 flex items-center justify-between text-xs font-mono text-neutral-400">
|
|
234
|
+
<span>Verified Schema: ${entity.name}</span>
|
|
235
|
+
<span>REST: /api/${entity.name.toLowerCase()}s</span>
|
|
236
|
+
</div>
|
|
237
|
+
</div>
|
|
238
|
+
` : ''}
|
|
239
|
+
</div>
|
|
240
|
+
</section>
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
`;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PIXEL CREW โ Visual Critic & Anti-AI Slop Auditor
|
|
3
|
+
*
|
|
4
|
+
* Inspects generated source code, CSS tokens, and component trees against the
|
|
5
|
+
* 64-Pattern Impeccable Anti-AI Slop Catalog.
|
|
6
|
+
* Scores are calculated dynamically from verified code evidence (NO fake hardcoded scores).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export class VisualCritic {
|
|
10
|
+
/**
|
|
11
|
+
* Audit generated code files for AI slop patterns and aesthetic quality.
|
|
12
|
+
*/
|
|
13
|
+
static evaluateProject(files = {}) {
|
|
14
|
+
const findings = [];
|
|
15
|
+
let slopPenalty = 0;
|
|
16
|
+
const fileEntries = Object.entries(files);
|
|
17
|
+
|
|
18
|
+
for (const [filepath, content] of fileEntries) {
|
|
19
|
+
if (typeof content !== 'string') continue;
|
|
20
|
+
|
|
21
|
+
// 1. Check for decorative gridlines background
|
|
22
|
+
if (content.includes('bg-grid') || content.includes('grid-white/[0.05]') || content.includes('svg-grid')) {
|
|
23
|
+
findings.push({
|
|
24
|
+
rule: 'SLOP-001: Decorative Gridlines Background',
|
|
25
|
+
severity: 'high',
|
|
26
|
+
file: filepath,
|
|
27
|
+
evidence: 'Found decorative graph-paper gridline background classes.'
|
|
28
|
+
});
|
|
29
|
+
slopPenalty += 2.0;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// 2. Check for fake macOS terminal window
|
|
33
|
+
if (content.includes('๐ด') || content.includes('arnel@arch') || content.includes('terminal-window') || content.includes('bash -c')) {
|
|
34
|
+
findings.push({
|
|
35
|
+
rule: 'SLOP-002: Fake macOS Terminal Window',
|
|
36
|
+
severity: 'high',
|
|
37
|
+
file: filepath,
|
|
38
|
+
evidence: 'Found decorative fake macOS terminal window in UI.'
|
|
39
|
+
});
|
|
40
|
+
slopPenalty += 2.5;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// 3. Check for 4-box stat strip under hero
|
|
44
|
+
if (content.includes('486h') && content.includes('4+') && content.includes('3+')) {
|
|
45
|
+
findings.push({
|
|
46
|
+
rule: 'SLOP-027: Hero Metric 4-Box Stat Strip',
|
|
47
|
+
severity: 'medium',
|
|
48
|
+
file: filepath,
|
|
49
|
+
evidence: 'Found symmetrical 4-box stat metric strip.'
|
|
50
|
+
});
|
|
51
|
+
slopPenalty += 1.5;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 4. Check for skill percentage progress bars
|
|
55
|
+
if (content.includes('Expert') && content.includes('Proficient') && (content.includes('h-2 bg-') || content.includes('progress-bar'))) {
|
|
56
|
+
findings.push({
|
|
57
|
+
rule: 'SLOP-028: Fake Skill Progress Bars',
|
|
58
|
+
severity: 'medium',
|
|
59
|
+
file: filepath,
|
|
60
|
+
evidence: 'Found arbitrary skill proficiency progress meters.'
|
|
61
|
+
});
|
|
62
|
+
slopPenalty += 1.5;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// 5. Check for marketing buzzwords
|
|
66
|
+
const buzzwords = ['streamline', 'empower', 'supercharge', 'world-class', 'seamlessly'];
|
|
67
|
+
for (const bw of buzzwords) {
|
|
68
|
+
if (new RegExp(`\\b${bw}\\b`, 'i').test(content) && !filepath.includes('test')) {
|
|
69
|
+
findings.push({
|
|
70
|
+
rule: `SLOP-045: AI Marketing Buzzword ('${bw}')`,
|
|
71
|
+
severity: 'low',
|
|
72
|
+
file: filepath,
|
|
73
|
+
evidence: `Found generic AI clichรฉ buzzword '${bw}'.`
|
|
74
|
+
});
|
|
75
|
+
slopPenalty += 0.5;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// 6. Check for purple/cyan gradient halo
|
|
80
|
+
if (content.includes('from-purple-500') && content.includes('to-cyan-400') && content.includes('blur-3xl')) {
|
|
81
|
+
findings.push({
|
|
82
|
+
rule: 'SLOP-020: Radial Gradient Halo Blob',
|
|
83
|
+
severity: 'high',
|
|
84
|
+
file: filepath,
|
|
85
|
+
evidence: 'Found purple/cyan radial gradient blob in background.'
|
|
86
|
+
});
|
|
87
|
+
slopPenalty += 2.0;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const baseScore = 10.0;
|
|
92
|
+
const finalScore = Math.max(1.0, Math.round((baseScore - slopPenalty) * 10) / 10);
|
|
93
|
+
const passed = findings.filter(f => f.severity === 'high').length === 0 && finalScore >= 8.5;
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
passed,
|
|
97
|
+
score: finalScore,
|
|
98
|
+
slopPenalty,
|
|
99
|
+
totalFindings: findings.length,
|
|
100
|
+
findings,
|
|
101
|
+
summary: passed
|
|
102
|
+
? `Clean, human-grade design verified (Score: ${finalScore}/10). Zero critical AI-slop anti-patterns detected.`
|
|
103
|
+
: `Visual review flagged ${findings.length} AI-slop anti-patterns (Score: ${finalScore}/10). Remediation recommended.`
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PIXEL CREW โ Layering & Architectural Purity Policy
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export const LayeringPolicy = {
|
|
6
|
+
id: 'POL-ARCH-LAYERING',
|
|
7
|
+
name: 'Clean Architecture Boundary Policy',
|
|
8
|
+
rules: [
|
|
9
|
+
{ id: 'LAYER-01', description: 'Controllers must never access the database directly; they must delegate to services.' },
|
|
10
|
+
{ id: 'LAYER-02', description: 'Services contain business logic and policy enforcement; they delegate persistence to repositories.' },
|
|
11
|
+
{ id: 'LAYER-03', description: 'Repositories encapsulate database queries and caching.' },
|
|
12
|
+
{ id: 'LAYER-04', description: 'All errors must conform to RFC 7807 Problem Details format.' }
|
|
13
|
+
]
|
|
14
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PIXEL CREW โ Indexing & Performance Policy
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export const IndexingPolicy = {
|
|
6
|
+
id: 'POL-PERF-INDEXING',
|
|
7
|
+
name: 'Database Indexing & Query Performance Policy',
|
|
8
|
+
rules: [
|
|
9
|
+
{ id: 'INDEX-01', description: 'Foreign keys must be indexed to avoid table scans on JOINs.' },
|
|
10
|
+
{ id: 'INDEX-02', description: 'Tenant-scoped collections must have compound indexes: (organizationId, createdAt DESC).' },
|
|
11
|
+
{ id: 'INDEX-03', description: 'Unique identifiers (email, slug) must have unique database constraints.' }
|
|
12
|
+
]
|
|
13
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PIXEL CREW โ Resilience & Reliability Policy
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export const ResiliencePolicy = {
|
|
6
|
+
id: 'POL-REL-RESILIENCE',
|
|
7
|
+
name: 'Resilience & Fault Tolerance Policy',
|
|
8
|
+
rules: [
|
|
9
|
+
{ id: 'REL-01', description: 'Mutating operations must support Idempotency-Key validation.' },
|
|
10
|
+
{ id: 'REL-02', description: 'Asynchronous workers must have dead-letter queues and retry backoff.' },
|
|
11
|
+
{ id: 'REL-03', description: 'Applications must handle SIGTERM/SIGINT with graceful resource cleanup.' }
|
|
12
|
+
]
|
|
13
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PIXEL CREW โ Declarative Security Policies
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export const AuthPolicy = {
|
|
6
|
+
id: 'POL-SEC-AUTH',
|
|
7
|
+
name: 'Authentication Guard Policy',
|
|
8
|
+
rules: [
|
|
9
|
+
{ id: 'AUTH-01', description: 'Mutating endpoints (POST, PATCH, DELETE) require authenticated session context by default.' },
|
|
10
|
+
{ id: 'AUTH-02', description: 'Session tokens must be transmitted in HttpOnly SameSite secure cookies.' },
|
|
11
|
+
{ id: 'AUTH-03', description: 'Password hashes must use Argon2id or bcrypt.' }
|
|
12
|
+
]
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const RBACPolicy = {
|
|
16
|
+
id: 'POL-SEC-RBAC',
|
|
17
|
+
name: 'Role-Based Access Control Policy',
|
|
18
|
+
rules: [
|
|
19
|
+
{ id: 'RBAC-01', description: 'Deny by default: missing explicit allow rule returns 403 Forbidden.' },
|
|
20
|
+
{ id: 'RBAC-02', description: 'Resource deletion restricted strictly to admin or verified owner.' }
|
|
21
|
+
]
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const TenantPolicy = {
|
|
25
|
+
id: 'POL-SEC-TENANT',
|
|
26
|
+
name: 'Multi-Tenant Isolation Policy',
|
|
27
|
+
rules: [
|
|
28
|
+
{ id: 'TENANT-01', description: 'Tenant context must be derived from validated session token, never trusted from request body.' },
|
|
29
|
+
{ id: 'TENANT-02', description: 'All tenant-scoped database queries must include WHERE organization_id = session.orgId.' }
|
|
30
|
+
]
|
|
31
|
+
};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PIXEL CREW โ Universal Agent Protocol & Roles
|
|
3
|
+
*
|
|
4
|
+
* Standardized agent roles, states, expressions, and capability contracts.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const AGENT_STATES = {
|
|
8
|
+
IDLE: 'IDLE',
|
|
9
|
+
SPAWNING: 'SPAWNING',
|
|
10
|
+
ANALYZING: 'ANALYZING',
|
|
11
|
+
WORKING: 'WORKING',
|
|
12
|
+
BLOCKED: 'BLOCKED',
|
|
13
|
+
VERIFYING: 'VERIFYING',
|
|
14
|
+
COMPLETED: 'COMPLETED',
|
|
15
|
+
ERROR: 'ERROR'
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const AGENT_EXPRESSIONS = {
|
|
19
|
+
IDLE: 'โ_โ',
|
|
20
|
+
SPAWNING: 'โ_โ',
|
|
21
|
+
ANALYZING: 'โ_โ',
|
|
22
|
+
WORKING: 'โโโ',
|
|
23
|
+
BLOCKED: '?_?',
|
|
24
|
+
VERIFYING: '๐_๐',
|
|
25
|
+
COMPLETED: '^_^',
|
|
26
|
+
ERROR: 'x_x'
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const ORCHESTRATOR_EXPRESSIONS = {
|
|
30
|
+
IDLE: 'โ_โ',
|
|
31
|
+
COORDINATING: 'โ_โ โก',
|
|
32
|
+
ANALYZING: 'โ_โ',
|
|
33
|
+
COMPLETED: 'โ
_โ
',
|
|
34
|
+
ERROR: 'x_x'
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const AGENT_ROLES = {
|
|
38
|
+
orchestrator: {
|
|
39
|
+
id: 'orchestrator',
|
|
40
|
+
name: 'Tech Lead / Master CPU',
|
|
41
|
+
title: 'Staff Swarm Architect & Project Lead',
|
|
42
|
+
color: '#ffd700',
|
|
43
|
+
icon: '๐',
|
|
44
|
+
defaultSkills: ['anti-ai/slop-guardian']
|
|
45
|
+
},
|
|
46
|
+
creativeDirector: {
|
|
47
|
+
id: 'creativeDirector',
|
|
48
|
+
name: 'Creative Director',
|
|
49
|
+
title: 'Lead Aesthetic Strategist & Brand Architect',
|
|
50
|
+
color: '#ff9900',
|
|
51
|
+
icon: 'โจ',
|
|
52
|
+
defaultSkills: ['design/ui-design', 'design/typography', 'anti-ai/slop-guardian']
|
|
53
|
+
},
|
|
54
|
+
frontend: {
|
|
55
|
+
id: 'frontend',
|
|
56
|
+
name: 'Frontend Builder',
|
|
57
|
+
title: 'Senior UI/UX & Component Engineer',
|
|
58
|
+
color: '#00f0ff',
|
|
59
|
+
icon: '๐จ',
|
|
60
|
+
defaultSkills: ['frontend/nextjs', 'frontend/react', 'frontend/tailwind', 'frontend/accessibility']
|
|
61
|
+
},
|
|
62
|
+
backend: {
|
|
63
|
+
id: 'backend',
|
|
64
|
+
name: 'Backend Engineer',
|
|
65
|
+
title: 'Principal API & Distributed Systems Engineer',
|
|
66
|
+
color: '#ff007f',
|
|
67
|
+
icon: 'โก',
|
|
68
|
+
defaultSkills: ['backend/route-handlers', 'backend/data-models']
|
|
69
|
+
},
|
|
70
|
+
database: {
|
|
71
|
+
id: 'database',
|
|
72
|
+
name: 'Database Architect',
|
|
73
|
+
title: 'Principal DBA & Query Performance Engineer',
|
|
74
|
+
color: '#ffd700',
|
|
75
|
+
icon: '๐๏ธ',
|
|
76
|
+
defaultSkills: ['backend/data-models']
|
|
77
|
+
},
|
|
78
|
+
security: {
|
|
79
|
+
id: 'security',
|
|
80
|
+
name: 'Security Sentinel',
|
|
81
|
+
title: 'InfoSec Lead & OWASP Auditor',
|
|
82
|
+
color: '#ff3344',
|
|
83
|
+
icon: '๐ก๏ธ',
|
|
84
|
+
defaultSkills: ['frontend/accessibility']
|
|
85
|
+
},
|
|
86
|
+
performance: {
|
|
87
|
+
id: 'performance',
|
|
88
|
+
name: 'Performance Profiler',
|
|
89
|
+
title: 'Core Web Vitals & Runtime Optimizer',
|
|
90
|
+
color: '#00ff88',
|
|
91
|
+
icon: '๐',
|
|
92
|
+
defaultSkills: ['quality/responsive-design']
|
|
93
|
+
},
|
|
94
|
+
qa: {
|
|
95
|
+
id: 'qa',
|
|
96
|
+
name: 'QA & Visual Critic',
|
|
97
|
+
title: 'Lead Verification & Anti-AI Rubric Guardian',
|
|
98
|
+
color: '#bd00ff',
|
|
99
|
+
icon: '๐งช',
|
|
100
|
+
defaultSkills: ['quality/visual-review', 'quality/browser-testing', 'anti-ai/slop-guardian']
|
|
101
|
+
},
|
|
102
|
+
animationSpecialist: {
|
|
103
|
+
id: 'animationSpecialist',
|
|
104
|
+
name: 'Motion Specialist',
|
|
105
|
+
title: 'Senior Kinetic Choreographer & Micro-Interactions',
|
|
106
|
+
color: '#38bdf8',
|
|
107
|
+
icon: '๐ฌ',
|
|
108
|
+
defaultSkills: ['motion/framer-motion', 'motion/micro-interactions']
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Creates and normalizes an Agent Capabilities record
|
|
114
|
+
*/
|
|
115
|
+
export function normalizeCapabilities(capabilities = {}) {
|
|
116
|
+
return {
|
|
117
|
+
fileAccess: Boolean(capabilities.fileAccess ?? true),
|
|
118
|
+
terminalAccess: Boolean(capabilities.terminalAccess ?? true),
|
|
119
|
+
subagents: Boolean(capabilities.subagents ?? false),
|
|
120
|
+
backgroundTasks: Boolean(capabilities.backgroundTasks ?? true),
|
|
121
|
+
streaming: Boolean(capabilities.streaming ?? true),
|
|
122
|
+
toolCalls: Boolean(capabilities.toolCalls ?? true)
|
|
123
|
+
};
|
|
124
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PIXEL CREW โ Universal Event Protocol
|
|
3
|
+
*
|
|
4
|
+
* Standardized telemetry, lifecycle, and progress events across all agent providers.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const EVENT_TYPES = {
|
|
8
|
+
AGENT_STARTED: 'agent.started',
|
|
9
|
+
AGENT_THINKING: 'agent.thinking',
|
|
10
|
+
SKILL_ACTIVATED: 'skill.activated',
|
|
11
|
+
TOOL_INVOKED: 'tool.invoked',
|
|
12
|
+
PROGRESS: 'progress',
|
|
13
|
+
TASK_COMPLETED: 'task.completed',
|
|
14
|
+
TASK_FAILED: 'task.failed',
|
|
15
|
+
ORCHESTRATION_STARTED: 'orchestration.started',
|
|
16
|
+
ORCHESTRATION_COMPLETED: 'orchestration.completed',
|
|
17
|
+
ORCHESTRATION_FAILED: 'orchestration.failed',
|
|
18
|
+
STATE_CHANGE: 'state.change'
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Creates and validates a standardized AgentEvent object
|
|
23
|
+
*/
|
|
24
|
+
export function createEvent(options = {}) {
|
|
25
|
+
const event = {
|
|
26
|
+
id: options.id || `evt-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
|
|
27
|
+
timestamp: options.timestamp || Date.now(),
|
|
28
|
+
agent: options.agent || 'orchestrator',
|
|
29
|
+
type: options.type || EVENT_TYPES.PROGRESS,
|
|
30
|
+
taskId: options.taskId || null,
|
|
31
|
+
taskName: options.taskName || null,
|
|
32
|
+
skill: options.skill || null,
|
|
33
|
+
message: String(options.message || ''),
|
|
34
|
+
provider: options.provider || 'generic',
|
|
35
|
+
data: typeof options.data === 'object' && options.data !== null ? { ...options.data } : {}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
validateEvent(event);
|
|
39
|
+
return event;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Validates that an AgentEvent object satisfies contract
|
|
44
|
+
*/
|
|
45
|
+
export function validateEvent(event) {
|
|
46
|
+
if (!event || typeof event !== 'object') {
|
|
47
|
+
throw new Error('Event must be a non-null object');
|
|
48
|
+
}
|
|
49
|
+
if (!event.id || typeof event.id !== 'string') {
|
|
50
|
+
throw new Error('Event must have a valid string id');
|
|
51
|
+
}
|
|
52
|
+
if (typeof event.timestamp !== 'number') {
|
|
53
|
+
throw new Error('Event must have a numeric timestamp');
|
|
54
|
+
}
|
|
55
|
+
if (!event.agent || typeof event.agent !== 'string') {
|
|
56
|
+
throw new Error('Event must have a valid agent name');
|
|
57
|
+
}
|
|
58
|
+
if (!event.type || typeof event.type !== 'string') {
|
|
59
|
+
throw new Error('Event must have a valid event type');
|
|
60
|
+
}
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Serializes event for JSONL log line
|
|
66
|
+
*/
|
|
67
|
+
export function serializeEvent(event) {
|
|
68
|
+
validateEvent(event);
|
|
69
|
+
return JSON.stringify(event);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Deserializes an event from JSON string or object
|
|
74
|
+
*/
|
|
75
|
+
export function deserializeEvent(raw) {
|
|
76
|
+
const data = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
|
77
|
+
return createEvent(data);
|
|
78
|
+
}
|