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.
Files changed (171) 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 +632 -780
  136. package/src/orchestrator/design-engine.js +203 -0
  137. package/src/orchestrator/engine.js +307 -38
  138. package/src/orchestrator/oneshot.js +367 -380
  139. package/src/orchestrator/ontology.js +394 -0
  140. package/src/orchestrator/planner.js +231 -258
  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/task-planner.js +111 -0
  147. package/src/orchestrator/telemetry.js +209 -0
  148. package/src/orchestrator/ui-synthesizer.js +245 -0
  149. package/src/orchestrator/visual-critic.js +106 -0
  150. package/src/policies/architecture/layering.policy.js +14 -0
  151. package/src/policies/performance/indexing.policy.js +13 -0
  152. package/src/policies/reliability/resilience.policy.js +13 -0
  153. package/src/policies/security/auth.policy.js +31 -0
  154. package/src/protocol/agent.js +124 -0
  155. package/src/protocol/event.js +78 -0
  156. package/src/protocol/index.js +8 -0
  157. package/src/protocol/skill.js +54 -0
  158. package/src/protocol/task.js +100 -0
  159. package/src/scaffold/claude-generator.js +60 -0
  160. package/src/scaffold/commands-catalog.js +321 -0
  161. package/src/scaffold/cursor-generator.js +74 -0
  162. package/src/scaffold/ide-rules.js +133 -0
  163. package/src/scaffold/init.js +415 -91
  164. package/src/scaffold/installer.js +571 -0
  165. package/src/scaffold/kiro-generator.js +86 -0
  166. package/src/scaffold/skills-bundle.js +520 -0
  167. package/src/scaffold/templates.js +57 -4
  168. package/src/scaffold/workstations.js +364 -0
  169. package/src/server/server.js +283 -40
  170. package/src/utils/fs-safe.js +168 -0
  171. package/src/utils/markdown-report.js +175 -0
@@ -0,0 +1,134 @@
1
+ /**
2
+ * PIXEL CREW — Kiro Adapter
3
+ *
4
+ * Execution adapter for Kiro coding agent runtime.
5
+ */
6
+
7
+ import fs from 'node:fs/promises';
8
+ import path from 'node:path';
9
+ import os from 'node:os';
10
+ import { spawn } from 'node:child_process';
11
+ import { AgentAdapter } from './adapter.interface.js';
12
+
13
+ export class KiroAdapter extends AgentAdapter {
14
+ constructor(options = {}) {
15
+ super('kiro', 'Kiro', {
16
+ icon: '🗡️',
17
+ description: 'Kiro autonomous agent and multi-agent runtime',
18
+ capabilities: {
19
+ fileAccess: true,
20
+ terminalAccess: true,
21
+ subagents: true,
22
+ backgroundTasks: true,
23
+ streaming: true,
24
+ toolCalls: true
25
+ },
26
+ ...options
27
+ });
28
+ }
29
+
30
+ async detectScore(targetDir = process.cwd()) {
31
+ let score = 0;
32
+
33
+ // 1. Environment variables (Active Kiro session/agent environment) (+1000 points)
34
+ if (
35
+ process.env.KIRO ||
36
+ process.env.KIRO_AGENT ||
37
+ process.env.KIRO_SESSION ||
38
+ process.env.KIRO_WORKSPACE ||
39
+ process.env.KIRO_APP_DIR ||
40
+ process.env.KIRO_CONFIG_DIR ||
41
+ process.env.KIRO_PATH
42
+ ) {
43
+ score += 1000;
44
+ }
45
+
46
+ // 2. Target Workspace files/folders (.kiro, .kirorules, kiro.json, .kiro.json) (+200 points)
47
+ const indicators = ['.kiro', '.kirorules', 'kiro.json', '.kiro.json'];
48
+ for (const item of indicators) {
49
+ try {
50
+ await fs.access(path.join(targetDir, item));
51
+ score += 200;
52
+ break;
53
+ } catch {}
54
+ }
55
+
56
+ // 3. User Home Directory (~/.kiro, ~/.config/kiro) (+50 points)
57
+ try {
58
+ const home = os.homedir();
59
+ if (home) {
60
+ try {
61
+ await fs.access(path.join(home, '.kiro'));
62
+ score += 50;
63
+ } catch {}
64
+ try {
65
+ await fs.access(path.join(home, '.config', 'kiro'));
66
+ score += 50;
67
+ } catch {}
68
+ }
69
+ } catch {}
70
+
71
+ // 4. macOS Application bundle detection (+30 points)
72
+ if (process.platform === 'darwin') {
73
+ const macApps = [
74
+ '/Applications/Kiro.app',
75
+ path.join(os.homedir() || '', 'Applications', 'Kiro.app'),
76
+ '/Applications/Kiro IDE.app'
77
+ ];
78
+ for (const appPath of macApps) {
79
+ try {
80
+ await fs.access(appPath);
81
+ score += 30;
82
+ break;
83
+ } catch {}
84
+ }
85
+ }
86
+
87
+ // 5. Binary CLI in PATH (kiro, kiro-cli, kiro-agent, kiro-ai) (+30 points)
88
+ const binaries = ['kiro', 'kiro-cli', 'kiro-agent', 'kiro-ai'];
89
+ for (const bin of binaries) {
90
+ const isFound = await new Promise((resolve) => {
91
+ try {
92
+ const cmd = process.platform === 'win32' ? 'where' : 'which';
93
+ const proc = spawn(cmd, [bin], { stdio: 'ignore' });
94
+ proc.on('close', (code) => resolve(code === 0));
95
+ proc.on('error', () => resolve(false));
96
+ } catch {
97
+ resolve(false);
98
+ }
99
+ });
100
+ if (isFound) {
101
+ score += 30;
102
+ break;
103
+ }
104
+ }
105
+
106
+ return score;
107
+ }
108
+
109
+ async detect(targetDir = process.cwd()) {
110
+ const score = await this.detectScore(targetDir);
111
+ return score > 0;
112
+ }
113
+
114
+ async execute(task, context = {}) {
115
+ const { emit = () => {}, signal } = context;
116
+
117
+ if (signal?.aborted) {
118
+ throw new Error(`Task ${task.id} cancelled before start`);
119
+ }
120
+
121
+ await emit('tool.invoked', `Kiro agent executing task: ${task.title}`);
122
+
123
+ if (context.executeTaskHandler) {
124
+ return await context.executeTaskHandler(task, emit);
125
+ }
126
+
127
+ await new Promise(r => setTimeout(r, 200));
128
+ return {
129
+ success: true,
130
+ provider: this.id,
131
+ taskId: task.id
132
+ };
133
+ }
134
+ }
@@ -0,0 +1,150 @@
1
+ /**
2
+ * PIXEL CREW — Provider Registry & Dynamic Strategy Engine
3
+ *
4
+ * Manages coding agent providers, executes environment scans, and resolves
5
+ * the optimal adapter based on task requirements and selected runtime strategies.
6
+ */
7
+
8
+ import { GenericAdapter } from './generic.js';
9
+ import { ClaudeCodeAdapter } from './claude-code.js';
10
+ import { CodexAdapter } from './codex.js';
11
+ import { CursorAdapter } from './cursor.js';
12
+ import { KiroAdapter } from './kiro.js';
13
+ import { AntigravityAdapter } from './antigravity.js';
14
+
15
+ export class ProviderRegistry {
16
+ constructor() {
17
+ this.adapters = new Map();
18
+ this.detectedCache = new Map();
19
+ this.lastScanTime = 0;
20
+
21
+ // Register built-in providers
22
+ this.registerAdapter(new GenericAdapter());
23
+ this.registerAdapter(new ClaudeCodeAdapter());
24
+ this.registerAdapter(new CodexAdapter());
25
+ this.registerAdapter(new CursorAdapter());
26
+ this.registerAdapter(new KiroAdapter());
27
+ this.registerAdapter(new AntigravityAdapter());
28
+ }
29
+
30
+ registerAdapter(adapter) {
31
+ if (!adapter?.id) {
32
+ throw new Error('Adapter must have a unique id');
33
+ }
34
+ this.adapters.set(adapter.id, adapter);
35
+ }
36
+
37
+ getAdapter(id) {
38
+ return this.adapters.get(id) || null;
39
+ }
40
+
41
+ getAllAdapters() {
42
+ return Array.from(this.adapters.values());
43
+ }
44
+
45
+ /**
46
+ * Scans system to detect available providers and determine the active runtime
47
+ * @param {boolean} forceRefresh
48
+ * @param {string} targetDir
49
+ * @returns {Promise<{ activeProvider: string, activeProviderName: string, activeProviderIcon: string, activeProviderDescription: string, available: import('./adapter.interface.js').AgentAdapter[], missing: import('./adapter.interface.js').AgentAdapter[] }>}
50
+ */
51
+ async scanEnvironment(forceRefresh = false, targetDir = process.cwd()) {
52
+ const now = Date.now();
53
+ if (!forceRefresh && now - this.lastScanTime < 4000 && this.detectedCache.size > 0 && this.lastScanResult) {
54
+ return this.lastScanResult;
55
+ }
56
+
57
+ const availableWithScores = [];
58
+ const missing = [];
59
+
60
+ for (const adapter of this.adapters.values()) {
61
+ try {
62
+ const score = typeof adapter.detectScore === 'function'
63
+ ? await adapter.detectScore(targetDir)
64
+ : ((await adapter.detect(targetDir)) ? 100 : 0);
65
+
66
+ this.detectedCache.set(adapter.id, score > 0);
67
+ if (score > 0) {
68
+ availableWithScores.push({ adapter, score });
69
+ } else {
70
+ missing.push(adapter);
71
+ }
72
+ } catch {
73
+ this.detectedCache.set(adapter.id, false);
74
+ missing.push(adapter);
75
+ }
76
+ }
77
+
78
+ // Sort available adapters by confidence score descending
79
+ availableWithScores.sort((a, b) => {
80
+ // Prioritize higher score
81
+ if (b.score !== a.score) return b.score - a.score;
82
+ // If score is equal, prioritize Antigravity / Kiro / Claude over generic
83
+ if (a.adapter.id === 'generic') return 1;
84
+ if (b.adapter.id === 'generic') return -1;
85
+ return 0;
86
+ });
87
+
88
+ const available = availableWithScores.map(item => item.adapter);
89
+ const top = available.find(a => a.id !== 'generic') || available[0] || this.getAdapter('generic');
90
+
91
+ this.lastScanTime = now;
92
+ this.lastScanResult = {
93
+ activeProvider: top?.id || 'generic',
94
+ activeProviderName: top?.name || 'Generic CLI Runner',
95
+ activeProviderIcon: top?.icon || '💻',
96
+ activeProviderDescription: top?.description || '',
97
+ available,
98
+ missing
99
+ };
100
+
101
+ return this.lastScanResult;
102
+ }
103
+
104
+ /**
105
+ * Selects the best adapter for a given task based on strategy
106
+ * @param {import('../protocol/task.js').AgentTask} task
107
+ * @param {string} strategy - 'auto' | 'hybrid' | specific provider id
108
+ */
109
+ async getBestAgent(task, strategy = 'auto') {
110
+ // If specific adapter explicitly requested
111
+ if (strategy && strategy !== 'auto' && strategy !== 'hybrid') {
112
+ const explicit = this.getAdapter(strategy);
113
+ if (explicit) return explicit;
114
+ }
115
+
116
+ // Check if task itself specifies an assigned provider
117
+ if (task?.assignedProvider) {
118
+ const assigned = this.getAdapter(task.assignedProvider);
119
+ if (assigned) return assigned;
120
+ }
121
+
122
+ const { activeProvider, available } = await this.scanEnvironment();
123
+
124
+ if (strategy === 'hybrid') {
125
+ // Hybrid crew strategy:
126
+ // - Design / Frontend -> Claude Code / Cursor / Antigravity
127
+ // - Backend / Data -> Codex / Antigravity / Kiro
128
+ // - QA / Review -> Claude Code / Generic / Antigravity
129
+ if (task.agent === 'frontend' || task.agent === 'creativeDirector') {
130
+ const preferred = available.find(a => a.id === 'claude-code' || a.id === 'cursor' || a.id === 'antigravity');
131
+ if (preferred) return preferred;
132
+ } else if (task.agent === 'backend' || task.agent === 'database') {
133
+ const preferred = available.find(a => a.id === 'codex' || a.id === 'antigravity' || a.id === 'kiro');
134
+ if (preferred) return preferred;
135
+ }
136
+ }
137
+
138
+ // In 'auto' mode: Use the top-scored active provider
139
+ if (activeProvider) {
140
+ const activeAdapter = this.getAdapter(activeProvider);
141
+ if (activeAdapter) return activeAdapter;
142
+ }
143
+
144
+ if (available.length > 0) {
145
+ return available[0];
146
+ }
147
+
148
+ return this.getAdapter('generic');
149
+ }
150
+ }
@@ -0,0 +1,104 @@
1
+ /**
2
+ * PIXEL CREW — Architecture Complexity Analyzer
3
+ *
4
+ * Computes multi-dimensional complexity scores and prevents over-engineering
5
+ * by ensuring architectural choices match actual application constraints.
6
+ */
7
+
8
+ export class ComplexityAnalyzer {
9
+ /**
10
+ * Calculate complexity score across 6 architectural dimensions
11
+ * @param {object} requirements - SystemRequirementsModel
12
+ * @param {object} ast - Semantic Project AST
13
+ * @returns {object} Complexity Assessment
14
+ */
15
+ static analyze(requirements = {}, ast = {}) {
16
+ const app = requirements.application || {};
17
+ const users = requirements.users || {};
18
+ const data = requirements.data || {};
19
+ const api = requirements.api || {};
20
+ const security = requirements.security || {};
21
+ const performance = requirements.performance || {};
22
+ const jobs = requirements.backgroundJobs || {};
23
+
24
+ const entities = ast.entities || [];
25
+ const workflows = ast.workflows || [];
26
+ const operations = ast.operations || [];
27
+
28
+ // 1. Domain Complexity (0–25)
29
+ let domainScore = 5;
30
+ if (entities.length > 5) domainScore += 5;
31
+ if (entities.length > 10) domainScore += 5;
32
+ if (workflows.length > 3) domainScore += 5;
33
+ if (users.roles && users.organizations) domainScore += 5;
34
+
35
+ // 2. Traffic & Concurrency Complexity (0–20)
36
+ let trafficScore = 3;
37
+ if (app.expectedScale === 'medium') trafficScore += 5;
38
+ if (app.expectedScale === 'high') trafficScore += 12;
39
+ if (performance.realTime) trafficScore += 5;
40
+
41
+ // 3. Data & Storage Complexity (0–20)
42
+ let dataScore = 4;
43
+ if (data.transactions) dataScore += 5;
44
+ if (data.search) dataScore += 3;
45
+ if (data.auditLog) dataScore += 3;
46
+ if (security.tenantIsolation) dataScore += 5;
47
+
48
+ // 4. Integration & Background Processing (0–15)
49
+ let integrationScore = 2;
50
+ if (jobs.required) integrationScore += 5;
51
+ if (jobs.tasks && jobs.tasks.length > 2) integrationScore += 4;
52
+ if (api.public) integrationScore += 4;
53
+
54
+ // 5. Reliability & Availability Requirements (0–10)
55
+ let reliabilityScore = 2;
56
+ if (app.availability === '99.9%') reliabilityScore += 3;
57
+ if (app.availability === '99.99%') reliabilityScore += 6;
58
+ if (data.transactions) reliabilityScore += 2;
59
+
60
+ // 6. Security Complexity (0–10)
61
+ let securityScore = 2;
62
+ if (security.tenantIsolation) securityScore += 3;
63
+ if (security.sensitiveData) securityScore += 3;
64
+ if (security.auditLogging) securityScore += 2;
65
+
66
+ const totalScore = domainScore + trafficScore + dataScore + integrationScore + reliabilityScore + securityScore;
67
+
68
+ // Determine Tier
69
+ let tier = 'low';
70
+ let recommendedStyle = 'modular-monolith';
71
+ let allowedInfrastructure = ['postgresql', 'sqlite', 'in-memory-cache'];
72
+ let disallowedInfrastructure = ['microservices', 'kubernetes', 'kafka', 'service-mesh'];
73
+
74
+ if (totalScore >= 60) {
75
+ tier = 'high';
76
+ recommendedStyle = 'distributed-modular-services';
77
+ allowedInfrastructure.push('redis', 'bullmq', 'cdn-edge', 'worker-cluster');
78
+ if (totalScore > 80) {
79
+ disallowedInfrastructure = []; // Complex requirements may justify advanced distributed infra
80
+ }
81
+ } else if (totalScore >= 35) {
82
+ tier = 'medium';
83
+ recommendedStyle = 'modular-monolith-with-workers';
84
+ allowedInfrastructure.push('redis', 'bullmq');
85
+ }
86
+
87
+ return {
88
+ totalScore,
89
+ tier, // 'low' | 'medium' | 'high'
90
+ recommendedStyle,
91
+ dimensions: {
92
+ domain: domainScore,
93
+ traffic: trafficScore,
94
+ data: dataScore,
95
+ integration: integrationScore,
96
+ reliability: reliabilityScore,
97
+ security: securityScore
98
+ },
99
+ allowedInfrastructure,
100
+ disallowedInfrastructure,
101
+ summary: `Complexity score ${totalScore}/100 (${tier} complexity). Recommended architecture: ${recommendedStyle}.`
102
+ };
103
+ }
104
+ }
@@ -0,0 +1,213 @@
1
+ /**
2
+ * PIXEL CREW — System Requirement Analyzer
3
+ *
4
+ * Analyzes natural language intent and project AST to extract a structured,
5
+ * machine-verifiable SystemRequirementsModel without domain hardcoding.
6
+ */
7
+
8
+ export class RequirementAnalyzer {
9
+ /**
10
+ * Extract comprehensive backend requirements from prompt & AST
11
+ * @param {string} prompt
12
+ * @param {object} ast
13
+ * @returns {object} SystemRequirementsModel
14
+ */
15
+ static analyze(prompt = '', ast = {}) {
16
+ const rawPrompt = String(prompt).toLowerCase();
17
+ const domain = (ast.domain || '').toLowerCase();
18
+ const entities = ast.entities || [];
19
+ const workflows = ast.workflows || [];
20
+ const operations = ast.operations || [];
21
+
22
+ // 1. Application Scale & Multi-tenancy Inferences
23
+ const isMultiTenant = Boolean(
24
+ rawPrompt.includes('tenant') ||
25
+ rawPrompt.includes('organization') ||
26
+ rawPrompt.includes('workspace') ||
27
+ rawPrompt.includes('b2b') ||
28
+ rawPrompt.includes('team') ||
29
+ entities.some(e => ['Organization', 'Workspace', 'Tenant', 'Team', 'Account'].includes(e.name))
30
+ );
31
+
32
+ const isHighScale = Boolean(
33
+ rawPrompt.includes('high throughput') ||
34
+ rawPrompt.includes('streaming') ||
35
+ rawPrompt.includes('million') ||
36
+ rawPrompt.includes('distributed') ||
37
+ rawPrompt.includes('large scale') ||
38
+ rawPrompt.includes('real-time analytics')
39
+ );
40
+
41
+ const scale = isHighScale ? 'high' : (isMultiTenant ? 'medium' : 'low');
42
+
43
+ // 2. User & Authentication Inferences
44
+ const hasAuth = Boolean(
45
+ rawPrompt.includes('login') ||
46
+ rawPrompt.includes('auth') ||
47
+ rawPrompt.includes('user') ||
48
+ rawPrompt.includes('account') ||
49
+ rawPrompt.includes('sign in') ||
50
+ rawPrompt.includes('permission') ||
51
+ rawPrompt.includes('role') ||
52
+ isMultiTenant ||
53
+ (ast.actors && ast.actors.length > 1)
54
+ );
55
+
56
+ const hasRoles = Boolean(
57
+ rawPrompt.includes('role') ||
58
+ rawPrompt.includes('admin') ||
59
+ rawPrompt.includes('rbac') ||
60
+ rawPrompt.includes('permission') ||
61
+ (ast.actors && ast.actors.length > 1)
62
+ );
63
+
64
+ // 3. Data Inferences
65
+ const hasTransactions = Boolean(
66
+ rawPrompt.includes('payment') ||
67
+ rawPrompt.includes('checkout') ||
68
+ rawPrompt.includes('transfer') ||
69
+ rawPrompt.includes('order') ||
70
+ rawPrompt.includes('booking') ||
71
+ rawPrompt.includes('reservation') ||
72
+ rawPrompt.includes('inventory') ||
73
+ rawPrompt.includes('financial') ||
74
+ rawPrompt.includes('ledger') ||
75
+ rawPrompt.includes('atomic') ||
76
+ workflows.some(w => /pay|order|book|reserve|transfer|transact/i.test(w.name || ''))
77
+ );
78
+
79
+ const hasSearch = Boolean(
80
+ rawPrompt.includes('search') ||
81
+ rawPrompt.includes('filter') ||
82
+ rawPrompt.includes('catalog') ||
83
+ rawPrompt.includes('browse') ||
84
+ operations.some(op => (op.path || '').includes('search'))
85
+ );
86
+
87
+ // 4. API Inferences
88
+ const isPublicAPI = Boolean(
89
+ rawPrompt.includes('public api') ||
90
+ rawPrompt.includes('webhook') ||
91
+ rawPrompt.includes('developer platform') ||
92
+ rawPrompt.includes('sdk')
93
+ );
94
+
95
+ const rateLimiting = Boolean(
96
+ hasAuth ||
97
+ isPublicAPI ||
98
+ rawPrompt.includes('rate limit') ||
99
+ isMultiTenant
100
+ );
101
+
102
+ // 5. Security Inferences
103
+ const hasSensitiveData = Boolean(
104
+ rawPrompt.includes('health') ||
105
+ rawPrompt.includes('patient') ||
106
+ rawPrompt.includes('emr') ||
107
+ rawPrompt.includes('payment') ||
108
+ rawPrompt.includes('credit card') ||
109
+ rawPrompt.includes('pii') ||
110
+ rawPrompt.includes('contract') ||
111
+ rawPrompt.includes('legal') ||
112
+ rawPrompt.includes('secret') ||
113
+ rawPrompt.includes('password')
114
+ );
115
+
116
+ const auditLogging = Boolean(
117
+ isMultiTenant ||
118
+ hasSensitiveData ||
119
+ hasTransactions ||
120
+ rawPrompt.includes('audit') ||
121
+ rawPrompt.includes('compliance')
122
+ );
123
+
124
+ // 6. Performance & Asynchronous Jobs Inferences
125
+ const isReadHeavy = !rawPrompt.includes('write intensive') && !rawPrompt.includes('ingest');
126
+ const isRealTime = Boolean(
127
+ rawPrompt.includes('realtime') ||
128
+ rawPrompt.includes('real-time') ||
129
+ rawPrompt.includes('websocket') ||
130
+ rawPrompt.includes('live') ||
131
+ rawPrompt.includes('chat') ||
132
+ rawPrompt.includes('collaboration')
133
+ );
134
+
135
+ const backgroundJobs = Boolean(
136
+ rawPrompt.includes('job') ||
137
+ rawPrompt.includes('queue') ||
138
+ rawPrompt.includes('worker') ||
139
+ rawPrompt.includes('email') ||
140
+ rawPrompt.includes('export') ||
141
+ rawPrompt.includes('import') ||
142
+ rawPrompt.includes('report') ||
143
+ rawPrompt.includes('video') ||
144
+ rawPrompt.includes('transcription') ||
145
+ rawPrompt.includes('render') ||
146
+ rawPrompt.includes('batch') ||
147
+ rawPrompt.includes('notification')
148
+ );
149
+
150
+ return {
151
+ application: {
152
+ name: ast.appName || 'Application',
153
+ domain: domain || 'general',
154
+ type: isMultiTenant ? 'multi-tenant SaaS' : (isHighScale ? 'high-throughput system' : 'modular application'),
155
+ expectedScale: scale,
156
+ availability: isHighScale ? '99.99%' : (isMultiTenant ? '99.9%' : '99.5%')
157
+ },
158
+ users: {
159
+ authentication: hasAuth,
160
+ strategy: hasAuth ? (isMultiTenant ? 'session' : 'session') : 'none',
161
+ roles: hasRoles,
162
+ organizations: isMultiTenant
163
+ },
164
+ data: {
165
+ relational: true,
166
+ transactions: hasTransactions,
167
+ search: hasSearch,
168
+ softDelete: isMultiTenant || hasSensitiveData,
169
+ auditLog: auditLogging
170
+ },
171
+ api: {
172
+ style: 'REST',
173
+ versioning: true,
174
+ public: isPublicAPI,
175
+ rateLimiting,
176
+ errorFormat: 'RFC-7807'
177
+ },
178
+ security: {
179
+ sensitiveData: hasSensitiveData,
180
+ tenantIsolation: isMultiTenant,
181
+ auditLogging,
182
+ strictValidation: true,
183
+ denyByDefault: true
184
+ },
185
+ performance: {
186
+ readHeavy: isReadHeavy,
187
+ realTime: isRealTime,
188
+ caching: hasSearch || isReadHeavy || isMultiTenant,
189
+ paginationStrategy: (isHighScale || hasSearch) ? 'cursor' : 'offset'
190
+ },
191
+ backgroundJobs: {
192
+ required: backgroundJobs,
193
+ tasks: this.extractJobTasks(rawPrompt)
194
+ }
195
+ };
196
+ }
197
+
198
+ /**
199
+ * Helper: Extracts discrete background job types
200
+ */
201
+ static extractJobTasks(prompt) {
202
+ const tasks = [];
203
+ if (prompt.includes('email') || prompt.includes('notification')) tasks.push('send-notifications');
204
+ if (prompt.includes('export') || prompt.includes('report')) tasks.push('generate-reports');
205
+ if (prompt.includes('import') || prompt.includes('csv')) tasks.push('batch-import');
206
+ if (prompt.includes('video') || prompt.includes('image') || prompt.includes('transcription')) tasks.push('media-processing');
207
+ if (prompt.includes('webhook')) tasks.push('webhook-dispatch');
208
+ if (tasks.length === 0 && (prompt.includes('worker') || prompt.includes('queue'))) {
209
+ tasks.push('async-task-worker');
210
+ }
211
+ return tasks;
212
+ }
213
+ }