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,394 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PIXEL CREW — Universal Software Ontology
|
|
3
|
+
*
|
|
4
|
+
* Defines the domain-agnostic primitives, grammatical contracts, and schemas of software architecture.
|
|
5
|
+
* The orchestrator owns the software synthesis process, NOT a catalog of application domains.
|
|
6
|
+
* The domain is runtime data.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export const UNIVERSAL_CAPABILITIES = [
|
|
10
|
+
'search',
|
|
11
|
+
'filter',
|
|
12
|
+
'sort',
|
|
13
|
+
'create',
|
|
14
|
+
'edit',
|
|
15
|
+
'delete',
|
|
16
|
+
'view',
|
|
17
|
+
'schedule',
|
|
18
|
+
'calculate',
|
|
19
|
+
'simulate',
|
|
20
|
+
'compare',
|
|
21
|
+
'upload',
|
|
22
|
+
'download',
|
|
23
|
+
'export',
|
|
24
|
+
'authenticate',
|
|
25
|
+
'authorize',
|
|
26
|
+
'approve',
|
|
27
|
+
'reject',
|
|
28
|
+
'assign',
|
|
29
|
+
'track',
|
|
30
|
+
'visualize',
|
|
31
|
+
'collaborate',
|
|
32
|
+
'notify',
|
|
33
|
+
'archive',
|
|
34
|
+
'restore'
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
export const LAYOUT_PRIMITIVES = {
|
|
38
|
+
STACK: 'stack',
|
|
39
|
+
SPLIT: 'split',
|
|
40
|
+
GRID: 'grid',
|
|
41
|
+
OVERLAY: 'overlay',
|
|
42
|
+
WORKSPACE: 'workspace',
|
|
43
|
+
SIDEBAR: 'sidebar',
|
|
44
|
+
INSPECTOR: 'inspector',
|
|
45
|
+
CANVAS: 'canvas',
|
|
46
|
+
TIMELINE: 'timeline',
|
|
47
|
+
SEQUENCE: 'sequence',
|
|
48
|
+
NESTED: 'nested',
|
|
49
|
+
FREEFORM: 'freeform'
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const UI_PRIMITIVES = {
|
|
53
|
+
COLLECTION: 'collection',
|
|
54
|
+
TABLE: 'table',
|
|
55
|
+
FORM: 'form',
|
|
56
|
+
TIMELINE: 'timeline',
|
|
57
|
+
CALENDAR: 'calendar',
|
|
58
|
+
BOARD: 'board',
|
|
59
|
+
CANVAS: 'canvas',
|
|
60
|
+
INSPECTOR: 'inspector',
|
|
61
|
+
WORKSPACE: 'workspace',
|
|
62
|
+
MODAL: 'modal',
|
|
63
|
+
DRAWER: 'drawer',
|
|
64
|
+
SEARCH: 'search',
|
|
65
|
+
FILTER: 'filter',
|
|
66
|
+
PAGINATION: 'pagination',
|
|
67
|
+
VISUALIZATION: 'visualization'
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const OPERATION_METHODS = {
|
|
71
|
+
GET: 'GET',
|
|
72
|
+
POST: 'POST',
|
|
73
|
+
PUT: 'PUT',
|
|
74
|
+
PATCH: 'PATCH',
|
|
75
|
+
DELETE: 'DELETE'
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const REQUIREMENT_CATEGORIES = {
|
|
79
|
+
WORKFLOW: 'workflow',
|
|
80
|
+
UI_COMPONENT: 'ui_component',
|
|
81
|
+
API_ENDPOINT: 'api_endpoint',
|
|
82
|
+
DATA_MODEL: 'data_model',
|
|
83
|
+
SECURITY: 'security',
|
|
84
|
+
PERFORMANCE: 'performance',
|
|
85
|
+
DESIGN_QUALITY: 'design_quality'
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export class UniversalSoftwareOntology {
|
|
89
|
+
/**
|
|
90
|
+
* Validate & Normalize Project Definition
|
|
91
|
+
*/
|
|
92
|
+
static validateProject(project) {
|
|
93
|
+
if (!project || typeof project !== 'object') {
|
|
94
|
+
throw new Error('Project definition must be a valid object.');
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
name: String(project.name || 'Universal Application').trim(),
|
|
98
|
+
description: String(project.description || 'Open-world synthesized software application').trim(),
|
|
99
|
+
domain: String(project.domain || 'general-software').toLowerCase().replace(/[^a-z0-9]+/g, '-'),
|
|
100
|
+
goals: Array.isArray(project.goals) ? project.goals.map(String) : []
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Validate & Normalize Actor Definition
|
|
106
|
+
*/
|
|
107
|
+
static validateActor(actor, index = 0) {
|
|
108
|
+
if (!actor || typeof actor !== 'object') {
|
|
109
|
+
return {
|
|
110
|
+
id: `actor-${index + 1}`,
|
|
111
|
+
name: 'User',
|
|
112
|
+
role: 'Primary Operator',
|
|
113
|
+
capabilities: ['view', 'create', 'search'],
|
|
114
|
+
permissions: ['read', 'write']
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
const name = String(actor.name || `Actor ${index + 1}`).trim();
|
|
118
|
+
const id = actor.id || `actor-${name.toLowerCase().replace(/[^a-z0-9]+/g, '-') || (index + 1)}`;
|
|
119
|
+
return {
|
|
120
|
+
id,
|
|
121
|
+
name,
|
|
122
|
+
role: String(actor.role || name).trim(),
|
|
123
|
+
capabilities: Array.isArray(actor.capabilities) ? actor.capabilities.map(String) : ['view', 'search'],
|
|
124
|
+
permissions: Array.isArray(actor.permissions) ? actor.permissions.map(String) : ['read']
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Validate & Normalize Entity Definition
|
|
130
|
+
*/
|
|
131
|
+
static validateEntity(entity, index = 0) {
|
|
132
|
+
if (!entity || typeof entity !== 'object' || !entity.name) {
|
|
133
|
+
throw new Error(`Entity at index ${index} must have a valid string name.`);
|
|
134
|
+
}
|
|
135
|
+
const cleanName = String(entity.name).replace(/[^a-zA-Z0-9]/g, '');
|
|
136
|
+
if (!cleanName) {
|
|
137
|
+
throw new Error(`Entity name '${entity.name}' contains no alphanumeric characters.`);
|
|
138
|
+
}
|
|
139
|
+
const id = entity.id || `entity-${cleanName.toLowerCase()}`;
|
|
140
|
+
const title = entity.title || cleanName;
|
|
141
|
+
const plural = String(entity.plural || `${cleanName}s`).trim();
|
|
142
|
+
const description = String(entity.description || `Domain entity representing ${cleanName}`).trim();
|
|
143
|
+
|
|
144
|
+
const fields = Array.isArray(entity.fields) && entity.fields.length > 0
|
|
145
|
+
? entity.fields.map((f, fi) => this.normalizeField(f, fi))
|
|
146
|
+
: [
|
|
147
|
+
{ name: 'id', type: 'string', required: true, label: 'ID', sampleValue: `${id}-001` },
|
|
148
|
+
{ name: 'name', type: 'string', required: true, label: 'Name', sampleValue: `Sample ${cleanName}` },
|
|
149
|
+
{ name: 'status', type: 'string', required: false, label: 'Status', sampleValue: 'Active' },
|
|
150
|
+
{ name: 'createdAt', type: 'datetime', required: true, label: 'Created At', sampleValue: '2026-08-31T00:00:00.000Z' }
|
|
151
|
+
];
|
|
152
|
+
|
|
153
|
+
const relationships = Array.isArray(entity.relationships)
|
|
154
|
+
? entity.relationships.map(r => this.normalizeRelationship(r, cleanName))
|
|
155
|
+
: [];
|
|
156
|
+
|
|
157
|
+
const constraints = Array.isArray(entity.constraints) ? entity.constraints.map(String) : [];
|
|
158
|
+
const seedData = Array.isArray(entity.seedData) ? entity.seedData : [];
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
id,
|
|
162
|
+
name: cleanName,
|
|
163
|
+
title,
|
|
164
|
+
plural,
|
|
165
|
+
description,
|
|
166
|
+
fields,
|
|
167
|
+
relationships,
|
|
168
|
+
constraints,
|
|
169
|
+
seedData
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Normalize an individual Field definition
|
|
175
|
+
*/
|
|
176
|
+
static normalizeField(field, index = 0) {
|
|
177
|
+
if (typeof field === 'string') {
|
|
178
|
+
const isNum = /(count|price|depth|size|age|rating|score|amount|total|latitude|longitude|index|duration|tokens|ms|speed)/i.test(field);
|
|
179
|
+
const isDate = /(date|time|at|created|updated|scheduled|timestamp)/i.test(field);
|
|
180
|
+
const isBool = /(is|has|enabled|active|completed|verified)/i.test(field);
|
|
181
|
+
const type = field === 'id' ? 'string' : (isNum ? 'number' : (isDate ? 'datetime' : (isBool ? 'boolean' : 'string')));
|
|
182
|
+
return {
|
|
183
|
+
name: field,
|
|
184
|
+
type,
|
|
185
|
+
required: field === 'id' || field === 'name',
|
|
186
|
+
label: field.charAt(0).toUpperCase() + field.slice(1).replace(/([A-Z])/g, ' $1'),
|
|
187
|
+
sampleValue: isNum ? 100 : (isDate ? '2026-08-31T12:00:00.000Z' : (isBool ? true : `Sample ${field}`))
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
const name = String(field.name || `field_${index + 1}`).trim();
|
|
191
|
+
const type = String(field.type || 'string').toLowerCase();
|
|
192
|
+
const required = Boolean(field.required ?? (name === 'id' || name === 'name'));
|
|
193
|
+
const label = String(field.label || name.charAt(0).toUpperCase() + name.slice(1)).trim();
|
|
194
|
+
let sampleValue = field.sampleValue;
|
|
195
|
+
if (sampleValue === undefined) {
|
|
196
|
+
if (type === 'number') sampleValue = 42;
|
|
197
|
+
else if (type === 'boolean') sampleValue = true;
|
|
198
|
+
else if (type === 'datetime') sampleValue = '2026-08-31T12:00:00.000Z';
|
|
199
|
+
else sampleValue = `Sample ${label}`;
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
name,
|
|
203
|
+
type,
|
|
204
|
+
required,
|
|
205
|
+
label,
|
|
206
|
+
sampleValue
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Normalize an Entity Relationship
|
|
212
|
+
*/
|
|
213
|
+
static normalizeRelationship(rel, sourceEntity) {
|
|
214
|
+
if (typeof rel === 'string') {
|
|
215
|
+
return {
|
|
216
|
+
type: 'belongsTo',
|
|
217
|
+
targetEntity: rel.replace(/[^a-zA-Z0-9]/g, ''),
|
|
218
|
+
foreignKey: `${rel.toLowerCase()}Id`
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
type: rel.type || 'hasMany',
|
|
223
|
+
targetEntity: String(rel.targetEntity || rel.target || 'Entity').replace(/[^a-zA-Z0-9]/g, ''),
|
|
224
|
+
foreignKey: rel.foreignKey || (rel.type === 'belongsTo' ? `${(rel.targetEntity || 'entity').toLowerCase()}Id` : undefined),
|
|
225
|
+
cardinality: rel.cardinality || (rel.type === 'hasMany' ? '1:N' : 'N:1')
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Validate & Normalize Workflow Definition
|
|
231
|
+
*/
|
|
232
|
+
static validateWorkflow(wf, index = 0) {
|
|
233
|
+
if (!wf || typeof wf !== 'object') {
|
|
234
|
+
return {
|
|
235
|
+
id: `workflow-${index + 1}`,
|
|
236
|
+
name: `Workflow ${index + 1}`,
|
|
237
|
+
actor: 'User',
|
|
238
|
+
trigger: 'Manual Action',
|
|
239
|
+
steps: ['Initiate', 'Process', 'Complete'],
|
|
240
|
+
outcome: 'Completed'
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
const name = String(wf.name || `Workflow ${index + 1}`).trim();
|
|
244
|
+
const id = wf.id || `workflow-${name.toLowerCase().replace(/[^a-z0-9]+/g, '-') || (index + 1)}`;
|
|
245
|
+
return {
|
|
246
|
+
id,
|
|
247
|
+
name,
|
|
248
|
+
actor: String(wf.actor || 'User').trim(),
|
|
249
|
+
trigger: String(wf.trigger || 'Action Triggered').trim(),
|
|
250
|
+
steps: Array.isArray(wf.steps) ? wf.steps.map(String) : ['Execute action', 'Record state'],
|
|
251
|
+
outcome: String(wf.outcome || 'Workflow completed').trim()
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Validate & Normalize View Definition
|
|
257
|
+
*/
|
|
258
|
+
static validateView(view, entities = [], index = 0) {
|
|
259
|
+
if (!view || typeof view !== 'object') {
|
|
260
|
+
const fallbackEntity = entities[0] ? entities[0].name : 'Item';
|
|
261
|
+
return {
|
|
262
|
+
id: `view-${index + 1}`,
|
|
263
|
+
componentName: `${fallbackEntity}Overview`,
|
|
264
|
+
title: `${fallbackEntity} Overview`,
|
|
265
|
+
purpose: `Browse and manage ${fallbackEntity} records`,
|
|
266
|
+
targetEntities: [fallbackEntity],
|
|
267
|
+
layout: { type: LAYOUT_PRIMITIVES.GRID, density: 'comfortable' },
|
|
268
|
+
regions: [
|
|
269
|
+
{ role: 'navigation', components: ['search', 'filter'] },
|
|
270
|
+
{ role: 'content', components: ['collection'] }
|
|
271
|
+
],
|
|
272
|
+
capabilities: ['search', 'filter', 'view']
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
const rawTitle = String(view.title || view.name || `View ${index + 1}`).trim();
|
|
276
|
+
const cleanComp = (view.componentName || rawTitle).replace(/[^a-zA-Z0-9]/g, '');
|
|
277
|
+
const componentName = cleanComp.charAt(0).toUpperCase() + cleanComp.slice(1) || `DynamicView${index + 1}`;
|
|
278
|
+
const id = view.id || `view-${componentName.toLowerCase()}`;
|
|
279
|
+
const targetEntities = Array.isArray(view.targetEntities) && view.targetEntities.length > 0
|
|
280
|
+
? view.targetEntities.map(e => String(e).replace(/[^a-zA-Z0-9]/g, ''))
|
|
281
|
+
: (view.targetEntity ? [String(view.targetEntity).replace(/[^a-zA-Z0-9]/g, '')] : (entities[0] ? [entities[0].name] : ['System']));
|
|
282
|
+
|
|
283
|
+
const layout = typeof view.layout === 'object' && view.layout !== null
|
|
284
|
+
? view.layout
|
|
285
|
+
: { type: LAYOUT_PRIMITIVES.GRID, density: 'comfortable' };
|
|
286
|
+
|
|
287
|
+
const regions = Array.isArray(view.regions) ? view.regions : [
|
|
288
|
+
{ role: 'navigation', components: ['search', 'filter'] },
|
|
289
|
+
{ role: 'content', components: ['collection'] }
|
|
290
|
+
];
|
|
291
|
+
|
|
292
|
+
const capabilities = Array.isArray(view.capabilities) ? view.capabilities.map(String) : ['view', 'search', 'filter'];
|
|
293
|
+
|
|
294
|
+
return {
|
|
295
|
+
id,
|
|
296
|
+
componentName,
|
|
297
|
+
title: rawTitle,
|
|
298
|
+
purpose: String(view.purpose || `Interactive interface for ${rawTitle}`).trim(),
|
|
299
|
+
targetEntities,
|
|
300
|
+
layout,
|
|
301
|
+
regions,
|
|
302
|
+
capabilities
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Validate & Normalize Operation Definition
|
|
308
|
+
*/
|
|
309
|
+
static validateOperation(op, entities = [], index = 0) {
|
|
310
|
+
if (!op || typeof op !== 'object') {
|
|
311
|
+
const ent = entities[0] ? entities[0].name : 'Resource';
|
|
312
|
+
return {
|
|
313
|
+
id: `operation-${index + 1}`,
|
|
314
|
+
path: `/api/${ent.toLowerCase()}s`,
|
|
315
|
+
method: OPERATION_METHODS.GET,
|
|
316
|
+
description: `List ${ent} records`,
|
|
317
|
+
targetEntity: ent,
|
|
318
|
+
requestFields: [],
|
|
319
|
+
responseFields: [],
|
|
320
|
+
authorization: 'none'
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
const path = String(op.path || '/api/resource').startsWith('/') ? String(op.path || '/api/resource') : `/${op.path}`;
|
|
324
|
+
const method = Object.values(OPERATION_METHODS).includes(String(op.method).toUpperCase())
|
|
325
|
+
? String(op.method).toUpperCase()
|
|
326
|
+
: OPERATION_METHODS.GET;
|
|
327
|
+
const targetEntity = String(op.targetEntity || (entities[0] ? entities[0].name : 'Entity')).replace(/[^a-zA-Z0-9]/g, '');
|
|
328
|
+
const id = op.id || `op-${method.toLowerCase()}-${path.replace(/[^a-zA-Z0-9]/g, '-')}`;
|
|
329
|
+
|
|
330
|
+
return {
|
|
331
|
+
id,
|
|
332
|
+
path,
|
|
333
|
+
method,
|
|
334
|
+
description: String(op.description || `Execute ${method} on ${path}`).trim(),
|
|
335
|
+
targetEntity,
|
|
336
|
+
requestFields: Array.isArray(op.requestFields) ? op.requestFields.map(String) : [],
|
|
337
|
+
responseFields: Array.isArray(op.responseFields) ? op.responseFields.map(String) : [],
|
|
338
|
+
authorization: String(op.authorization || 'none')
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Validate & Normalize Event Definition
|
|
344
|
+
*/
|
|
345
|
+
static validateEvent(evt, index = 0) {
|
|
346
|
+
if (!evt || typeof evt !== 'object') {
|
|
347
|
+
return {
|
|
348
|
+
id: `event-${index + 1}`,
|
|
349
|
+
name: `Event${index + 1}`,
|
|
350
|
+
source: 'System',
|
|
351
|
+
payload: { timestamp: 'datetime' },
|
|
352
|
+
consumers: ['AuditLogger']
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
const name = String(evt.name || `Event${index + 1}`).replace(/[^a-zA-Z0-9]/g, '');
|
|
356
|
+
return {
|
|
357
|
+
id: evt.id || `event-${name.toLowerCase()}`,
|
|
358
|
+
name,
|
|
359
|
+
source: String(evt.source || 'System').trim(),
|
|
360
|
+
payload: typeof evt.payload === 'object' && evt.payload !== null ? evt.payload : {},
|
|
361
|
+
consumers: Array.isArray(evt.consumers) ? evt.consumers.map(String) : []
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Validate & Normalize Requirement Definition
|
|
367
|
+
*/
|
|
368
|
+
static validateRequirement(req, index = 0) {
|
|
369
|
+
if (!req || typeof req !== 'object') {
|
|
370
|
+
return {
|
|
371
|
+
id: `REQ-${String(index + 1).padStart(3, '0')}`,
|
|
372
|
+
category: REQUIREMENT_CATEGORIES.WORKFLOW,
|
|
373
|
+
target: 'system',
|
|
374
|
+
description: 'System requirement',
|
|
375
|
+
acceptanceCriteria: ['Requirement fulfilled'],
|
|
376
|
+
priority: 'high'
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
const id = req.id || `REQ-${String(index + 1).padStart(3, '0')}`;
|
|
380
|
+
const category = Object.values(REQUIREMENT_CATEGORIES).includes(req.category)
|
|
381
|
+
? req.category
|
|
382
|
+
: REQUIREMENT_CATEGORIES.WORKFLOW;
|
|
383
|
+
return {
|
|
384
|
+
id,
|
|
385
|
+
category,
|
|
386
|
+
target: String(req.target || 'system').trim(),
|
|
387
|
+
description: String(req.description || `Requirement ${id}`).trim(),
|
|
388
|
+
acceptanceCriteria: Array.isArray(req.acceptanceCriteria) && req.acceptanceCriteria.length > 0
|
|
389
|
+
? req.acceptanceCriteria.map(String)
|
|
390
|
+
: ['Functionality implemented and verified'],
|
|
391
|
+
priority: ['critical', 'high', 'medium', 'low'].includes(req.priority) ? req.priority : 'high'
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
}
|