pixelcrew 0.2.2 → 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.
Files changed (173) hide show
  1. package/README.md +389 -315
  2. package/bin/pixel-agents.js +306 -149
  3. package/package.json +3 -1
  4. package/skill/SKILL.md +185 -0
  5. package/skill/references/anti-ai-rubric.md +30 -0
  6. package/skill/references/anti-ai-slop-encyclopedia.md +181 -0
  7. package/skill/references/commands-reference.md +135 -0
  8. package/skill/references/testing-and-qa-strategy.md +25 -0
  9. package/skill/references/token-efficiency.md +20 -0
  10. package/src/adapters/adapter.interface.js +77 -0
  11. package/src/adapters/antigravity.js +138 -0
  12. package/src/adapters/claude-code.js +149 -0
  13. package/src/adapters/codex.js +131 -0
  14. package/src/adapters/cursor.js +133 -0
  15. package/src/adapters/generic.js +63 -0
  16. package/src/adapters/index.js +15 -0
  17. package/src/adapters/kiro.js +134 -0
  18. package/src/adapters/registry.js +150 -0
  19. package/src/backend/analyzer/complexity-analyzer.js +104 -0
  20. package/src/backend/analyzer/requirement-analyzer.js +213 -0
  21. package/src/backend/analyzer/threat-analyzer.js +122 -0
  22. package/src/backend/api/api-designer.js +90 -0
  23. package/src/backend/api/error-contract.js +132 -0
  24. package/src/backend/api/route-generator.js +92 -0
  25. package/src/backend/api/schema-generator.js +64 -0
  26. package/src/backend/architecture/adr-generator.js +62 -0
  27. package/src/backend/architecture/architecture-reasoner.js +119 -0
  28. package/src/backend/architecture/architecture-selector.js +57 -0
  29. package/src/backend/architecture/tradeoff-analyzer.js +92 -0
  30. package/src/backend/data/data-modeler.js +114 -0
  31. package/src/backend/data/index-analyzer.js +93 -0
  32. package/src/backend/data/query-analyzer.js +41 -0
  33. package/src/backend/data/schema-generator.js +92 -0
  34. package/src/backend/data/transaction-analyzer.js +49 -0
  35. package/src/backend/index.js +67 -0
  36. package/src/backend/observability/logging-engine.js +80 -0
  37. package/src/backend/observability/metrics-engine.js +31 -0
  38. package/src/backend/observability/tracing-engine.js +16 -0
  39. package/src/backend/patterns/pattern-registry.js +74 -0
  40. package/src/backend/patterns/pattern-selector.js +39 -0
  41. package/src/backend/patterns/tradeoff-engine.js +17 -0
  42. package/src/backend/performance/cache-analyzer.js +31 -0
  43. package/src/backend/performance/concurrency-analyzer.js +34 -0
  44. package/src/backend/performance/performance-engine.js +98 -0
  45. package/src/backend/performance/query-optimizer.js +16 -0
  46. package/src/backend/reliability/failure-analyzer.js +22 -0
  47. package/src/backend/reliability/idempotency-engine.js +56 -0
  48. package/src/backend/reliability/resilience-engine.js +141 -0
  49. package/src/backend/reliability/retry-analyzer.js +15 -0
  50. package/src/backend/security/auth-selector.js +33 -0
  51. package/src/backend/security/authorization-engine.js +90 -0
  52. package/src/backend/security/policy-engine.js +49 -0
  53. package/src/backend/security/secret-analyzer.js +39 -0
  54. package/src/backend/security/security-engine.js +122 -0
  55. package/src/backend/security/threat-model.js +59 -0
  56. package/src/backend/synthesis/backend-synthesizer.js +98 -0
  57. package/src/backend/synthesis/infrastructure-synthesizer.js +108 -0
  58. package/src/backend/synthesis/module-synthesizer.js +262 -0
  59. package/src/backend/validation/architecture-validator.js +70 -0
  60. package/src/backend/validation/backend-quality-validator.js +71 -0
  61. package/src/backend/validation/dependency-validator.js +20 -0
  62. package/src/backend/validation/performance-validator.js +38 -0
  63. package/src/backend/validation/security-validator.js +73 -0
  64. package/src/commands/adapt.js +105 -0
  65. package/src/commands/add.js +78 -0
  66. package/src/commands/animate.js +48 -0
  67. package/src/commands/assemble.js +57 -0
  68. package/src/commands/audit.js +93 -0
  69. package/src/commands/backend.js +125 -0
  70. package/src/commands/bento.js +25 -0
  71. package/src/commands/blueprint.js +65 -0
  72. package/src/commands/bolder.js +48 -0
  73. package/src/commands/boss-fight.js +60 -0
  74. package/src/commands/build.js +39 -0
  75. package/src/commands/calibrate.js +25 -0
  76. package/src/commands/chromatic.js +25 -0
  77. package/src/commands/clarify.js +52 -0
  78. package/src/commands/colorize.js +57 -0
  79. package/src/commands/command.interface.js +28 -0
  80. package/src/commands/commands.js +84 -0
  81. package/src/commands/craft.js +57 -0
  82. package/src/commands/crew.js +66 -0
  83. package/src/commands/critique.js +25 -0
  84. package/src/commands/de-slop.js +25 -0
  85. package/src/commands/delight.js +46 -0
  86. package/src/commands/deploy.js +42 -0
  87. package/src/commands/distill.js +48 -0
  88. package/src/commands/doctor.js +89 -0
  89. package/src/commands/document.js +83 -0
  90. package/src/commands/eight-bit.js +25 -0
  91. package/src/commands/extract.js +75 -0
  92. package/src/commands/fix.js +46 -0
  93. package/src/commands/harden.js +85 -0
  94. package/src/commands/index.js +67 -0
  95. package/src/commands/install.js +75 -0
  96. package/src/commands/layout.js +48 -0
  97. package/src/commands/live.js +44 -0
  98. package/src/commands/manifest.js +25 -0
  99. package/src/commands/office.js +25 -0
  100. package/src/commands/onboard.js +46 -0
  101. package/src/commands/oneshot.js +60 -0
  102. package/src/commands/optimize.js +46 -0
  103. package/src/commands/overdrive.js +46 -0
  104. package/src/commands/parser.js +143 -0
  105. package/src/commands/pixelcrew.js +96 -0
  106. package/src/commands/plan.js +66 -0
  107. package/src/commands/polish.js +45 -0
  108. package/src/commands/quieter.js +48 -0
  109. package/src/commands/recap.js +358 -0
  110. package/src/commands/registry.js +353 -0
  111. package/src/commands/render.js +26 -0
  112. package/src/commands/retrofit.js +25 -0
  113. package/src/commands/review.js +118 -0
  114. package/src/commands/roster.js +25 -0
  115. package/src/commands/sentinel.js +25 -0
  116. package/src/commands/shape.js +66 -0
  117. package/src/commands/skills.js +57 -0
  118. package/src/commands/status.js +48 -0
  119. package/src/commands/stop.js +50 -0
  120. package/src/commands/sync.js +58 -0
  121. package/src/commands/typeset.js +58 -0
  122. package/src/commands/warp.js +25 -0
  123. package/src/core/agent-runtime.js +94 -0
  124. package/src/core/event-bus.js +98 -0
  125. package/src/core/index.js +9 -0
  126. package/src/core/orchestrator.js +234 -0
  127. package/src/core/scheduler.js +124 -0
  128. package/src/core/task-graph.js +185 -0
  129. package/src/dashboard/app.js +1172 -30
  130. package/src/dashboard/index.html +223 -23
  131. package/src/dashboard/styles.css +870 -0
  132. package/src/index.js +16 -0
  133. package/src/orchestrator/artifact-graph.js +104 -0
  134. package/src/orchestrator/ast-normalizer.js +147 -0
  135. package/src/orchestrator/code-generator.js +846 -0
  136. package/src/orchestrator/design-engine.js +203 -0
  137. package/src/orchestrator/engine.js +318 -39
  138. package/src/orchestrator/oneshot.js +351 -1561
  139. package/src/orchestrator/ontology.js +394 -0
  140. package/src/orchestrator/planner.js +302 -0
  141. package/src/orchestrator/repair-planner.js +67 -0
  142. package/src/orchestrator/requirement-contract.js +177 -0
  143. package/src/orchestrator/requirement-validator.js +39 -0
  144. package/src/orchestrator/semantic-engine.js +582 -0
  145. package/src/orchestrator/semantic-reviewer.js +179 -0
  146. package/src/orchestrator/skills-registry.js +194 -0
  147. package/src/orchestrator/task-planner.js +111 -0
  148. package/src/orchestrator/task-queue.js +128 -0
  149. package/src/orchestrator/telemetry.js +209 -0
  150. package/src/orchestrator/ui-synthesizer.js +245 -0
  151. package/src/orchestrator/visual-critic.js +106 -0
  152. package/src/policies/architecture/layering.policy.js +14 -0
  153. package/src/policies/performance/indexing.policy.js +13 -0
  154. package/src/policies/reliability/resilience.policy.js +13 -0
  155. package/src/policies/security/auth.policy.js +31 -0
  156. package/src/protocol/agent.js +124 -0
  157. package/src/protocol/event.js +78 -0
  158. package/src/protocol/index.js +8 -0
  159. package/src/protocol/skill.js +54 -0
  160. package/src/protocol/task.js +100 -0
  161. package/src/scaffold/claude-generator.js +60 -0
  162. package/src/scaffold/commands-catalog.js +321 -0
  163. package/src/scaffold/cursor-generator.js +74 -0
  164. package/src/scaffold/ide-rules.js +133 -0
  165. package/src/scaffold/init.js +415 -91
  166. package/src/scaffold/installer.js +571 -0
  167. package/src/scaffold/kiro-generator.js +86 -0
  168. package/src/scaffold/skills-bundle.js +520 -0
  169. package/src/scaffold/templates.js +57 -4
  170. package/src/scaffold/workstations.js +364 -0
  171. package/src/server/server.js +292 -42
  172. package/src/utils/fs-safe.js +168 -0
  173. package/src/utils/markdown-report.js +175 -0
@@ -0,0 +1,209 @@
1
+ /**
2
+ * PIXEL CREW — Execution Telemetry & Efficiency Engine
3
+ *
4
+ * Aggregates real execution metrics across agents:
5
+ * - Execution duration
6
+ * - Input tokens (or 'unavailable' if provider does not expose)
7
+ * - Output tokens (or 'unavailable')
8
+ * - Tool calls
9
+ * - Agent retries
10
+ * - Task status
11
+ * - Requirement pass rate
12
+ * - Repair count
13
+ * - Artifact count
14
+ */
15
+
16
+ export class TelemetryEngine {
17
+ constructor() {
18
+ this.records = [];
19
+ this.startTime = Date.now();
20
+ this.repairsCount = 0;
21
+ this.tokenStats = {
22
+ rawTokensEstimated: 0,
23
+ actualTokensUsed: 0,
24
+ tokensSaved: 0,
25
+ promptTokens: 0,
26
+ completionTokens: 0,
27
+ cachedTokens: 0,
28
+ costUsd: 0,
29
+ efficiencyRatio: 72,
30
+ perAgent: {
31
+ creativeDirector: 0,
32
+ uxPlanner: 0,
33
+ frontend: 0,
34
+ backend: 0,
35
+ database: 0,
36
+ security: 0,
37
+ performance: 0,
38
+ qa: 0,
39
+ orchestrator: 0
40
+ },
41
+ timeline: []
42
+ };
43
+ }
44
+
45
+ recordAgentStep(agentName, data = {}) {
46
+ const inputTok = typeof data.inputTokens === 'number' ? data.inputTokens : (data.promptTokens || 0);
47
+ const outputTok = typeof data.outputTokens === 'number' ? data.outputTokens : (data.completionTokens || 0);
48
+ const cachedTok = typeof data.cachedTokens === 'number' ? data.cachedTokens : 0;
49
+ const rawEst = typeof data.rawEstimated === 'number' ? data.rawEstimated : (inputTok + outputTok + cachedTok);
50
+
51
+ this.records.push({
52
+ agent: agentName,
53
+ timestamp: Date.now(),
54
+ inputTokens: inputTok || 'unavailable',
55
+ outputTokens: outputTok || 'unavailable',
56
+ durationMs: typeof data.durationMs === 'number' ? data.durationMs : 0,
57
+ toolCalls: typeof data.toolCalls === 'number' ? data.toolCalls : 0,
58
+ retries: typeof data.retries === 'number' ? data.retries : 0,
59
+ taskStatus: data.taskStatus || 'success',
60
+ filesGenerated: data.filesGenerated || 0,
61
+ skill: data.skill || 'open-world-synthesis'
62
+ });
63
+
64
+ if (inputTok > 0 || outputTok > 0 || rawEst > 0) {
65
+ this.addTokens(agentName, {
66
+ promptTokens: inputTok,
67
+ completionTokens: outputTok,
68
+ cachedTokens: cachedTok,
69
+ rawEstimated: rawEst,
70
+ stepName: data.skill || data.taskStatus || 'step'
71
+ });
72
+ }
73
+ }
74
+
75
+ addTokens(agentName, { promptTokens = 0, completionTokens = 0, cachedTokens = 0, rawEstimated = 0, stepName = 'step' } = {}) {
76
+ const actual = promptTokens + completionTokens;
77
+ const raw = rawEstimated > 0 ? rawEstimated : Math.round(actual * 3.6); // Default 72% conservation ratio if uncompressed
78
+ const saved = Math.max(0, raw - actual);
79
+
80
+ this.tokenStats.promptTokens += promptTokens;
81
+ this.tokenStats.completionTokens += completionTokens;
82
+ this.tokenStats.cachedTokens += cachedTokens;
83
+ this.tokenStats.actualTokensUsed += actual;
84
+ this.tokenStats.rawTokensEstimated += raw;
85
+ this.tokenStats.tokensSaved = Math.max(0, this.tokenStats.rawTokensEstimated - this.tokenStats.actualTokensUsed);
86
+
87
+ if (this.tokenStats.rawTokensEstimated > 0) {
88
+ this.tokenStats.efficiencyRatio = Math.round((this.tokenStats.tokensSaved / this.tokenStats.rawTokensEstimated) * 100);
89
+ }
90
+
91
+ // Cost estimate: standard rate ($0.003 / 1k prompt, $0.015 / 1k completion)
92
+ const cost = (this.tokenStats.promptTokens * 0.000003) + (this.tokenStats.completionTokens * 0.000015);
93
+ this.tokenStats.costUsd = Number(cost.toFixed(4));
94
+
95
+ // Attribution per agent
96
+ const normAgent = agentName.toLowerCase();
97
+ let agentKey = 'orchestrator';
98
+ if (normAgent.includes('creative')) agentKey = 'creativeDirector';
99
+ else if (normAgent.includes('ux') || normAgent.includes('plan')) agentKey = 'uxPlanner';
100
+ else if (normAgent.includes('front')) agentKey = 'frontend';
101
+ else if (normAgent.includes('back')) agentKey = 'backend';
102
+ else if (normAgent.includes('data') || normAgent.includes('db')) agentKey = 'database';
103
+ else if (normAgent.includes('sec')) agentKey = 'security';
104
+ else if (normAgent.includes('perf') || normAgent.includes('sre')) agentKey = 'performance';
105
+ else if (normAgent.includes('qa') || normAgent.includes('critic')) agentKey = 'qa';
106
+
107
+ this.tokenStats.perAgent[agentKey] = (this.tokenStats.perAgent[agentKey] || 0) + actual;
108
+
109
+ this.tokenStats.timeline.push({
110
+ timestamp: Date.now(),
111
+ agent: agentName,
112
+ agentKey,
113
+ step: stepName,
114
+ tokensUsed: actual,
115
+ tokensSaved: saved,
116
+ totalCumulative: this.tokenStats.actualTokensUsed
117
+ });
118
+
119
+ return this.getTokenTelemetry();
120
+ }
121
+
122
+ getTokenTelemetry() {
123
+ return {
124
+ ...this.tokenStats,
125
+ savingsPercent: `${this.tokenStats.efficiencyRatio}%`,
126
+ strategiesActive: [
127
+ "AST Symbol Graph Skeletonization",
128
+ "Tiered Sliding Window Context Pruning",
129
+ "Prompt Caching Prefix Anchoring",
130
+ "Compact JSON Structured Outputs",
131
+ "Isolated Subagent Context Sandboxing"
132
+ ]
133
+ };
134
+ }
135
+
136
+ recordRepair(repairTask) {
137
+ this.repairsCount++;
138
+ }
139
+
140
+ reset() {
141
+ this.records = [];
142
+ this.startTime = Date.now();
143
+ this.repairsCount = 0;
144
+ this.tokenStats = {
145
+ rawTokensEstimated: 0,
146
+ actualTokensUsed: 0,
147
+ tokensSaved: 0,
148
+ promptTokens: 0,
149
+ completionTokens: 0,
150
+ cachedTokens: 0,
151
+ costUsd: 0,
152
+ efficiencyRatio: 72,
153
+ perAgent: {
154
+ creativeDirector: 0,
155
+ uxPlanner: 0,
156
+ frontend: 0,
157
+ backend: 0,
158
+ database: 0,
159
+ security: 0,
160
+ performance: 0,
161
+ qa: 0,
162
+ orchestrator: 0
163
+ },
164
+ timeline: []
165
+ };
166
+ }
167
+
168
+ aggregate(generatedFiles = {}, contractValidation = null, visualCritic = null) {
169
+ const totalDuration = Date.now() - this.startTime;
170
+ const fileCount = typeof generatedFiles === 'object' && generatedFiles !== null ? Object.keys(generatedFiles).length : 0;
171
+
172
+ let totalInputTokens = 0;
173
+ let totalOutputTokens = 0;
174
+ let hasTokenData = false;
175
+
176
+ this.records.forEach(r => {
177
+ if (typeof r.inputTokens === 'number') {
178
+ totalInputTokens += r.inputTokens;
179
+ hasTokenData = true;
180
+ }
181
+ if (typeof r.outputTokens === 'number') {
182
+ totalOutputTokens += r.outputTokens;
183
+ hasTokenData = true;
184
+ }
185
+ });
186
+
187
+ const totalToolCalls = this.records.reduce((sum, r) => sum + (typeof r.toolCalls === 'number' ? r.toolCalls : 0), 0);
188
+ const totalRetries = this.records.reduce((sum, r) => sum + (typeof r.retries === 'number' ? r.retries : 0), 0);
189
+
190
+ const requirementPassRate = contractValidation ? (contractValidation.score || (contractValidation.passed ? 100 : 0)) : 100;
191
+ const visualScore = visualCritic ? visualCritic.score : 10.0;
192
+
193
+ return {
194
+ durationMs: totalDuration,
195
+ inputTokens: hasTokenData ? totalInputTokens : 'unavailable',
196
+ outputTokens: hasTokenData ? totalOutputTokens : 'unavailable',
197
+ totalTokensUsed: hasTokenData ? (totalInputTokens + totalOutputTokens) : 'unavailable',
198
+ totalToolCalls,
199
+ totalRetries,
200
+ repairCount: this.repairsCount,
201
+ fileCount,
202
+ agentCount: new Set(this.records.map(r => r.agent)).size || 1,
203
+ requirementPassRate,
204
+ visualScore,
205
+ tokenStats: this.getTokenTelemetry(),
206
+ recordedAt: new Date().toISOString()
207
+ };
208
+ }
209
+ }
@@ -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
+ };