@baselineos/persona 0.1.0

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/dist/index.js ADDED
@@ -0,0 +1,2445 @@
1
+ // src/engine.ts
2
+ import { EventEmitter } from "events";
3
+ import { randomUUID } from "crypto";
4
+ var BaselinePersonaEngine = class extends EventEmitter {
5
+ personas;
6
+ activePersonas;
7
+ behaviorData;
8
+ adaptations;
9
+ config;
10
+ initialized;
11
+ constructor(config = {}) {
12
+ super();
13
+ this.personas = /* @__PURE__ */ new Map();
14
+ this.activePersonas = /* @__PURE__ */ new Map();
15
+ this.behaviorData = /* @__PURE__ */ new Map();
16
+ this.adaptations = [];
17
+ this.config = {
18
+ enableAutonomousLearning: config.enableAutonomousLearning ?? true,
19
+ enableBehavioralAnalysis: config.enableBehavioralAnalysis ?? true,
20
+ enablePredictiveCustomization: config.enablePredictiveCustomization ?? true,
21
+ enableCrossPersonaSharing: config.enableCrossPersonaSharing ?? false
22
+ };
23
+ this.initialized = false;
24
+ this.initializeCorePersonas();
25
+ this.initializeEventListeners();
26
+ this.initialized = true;
27
+ console.log("[BaselinePersonaEngine] Persona engine initialized with", this.personas.size, "core personas");
28
+ }
29
+ // ─── Persona Initialization ──────────────────────────────────────────────
30
+ initializeCorePersonas() {
31
+ const corePersonas = {
32
+ designer: {
33
+ name: "Designer",
34
+ description: "Visual and UX designer focused on creating beautiful, intuitive interfaces and experiences",
35
+ focus: ["visual-design", "ux-research", "prototyping", "design-systems", "accessibility"],
36
+ studio: {
37
+ interface: {
38
+ layout: "canvas-centric",
39
+ colorScheme: "creative-vibrant",
40
+ typography: "modern-sans",
41
+ visualElements: ["color-picker", "layer-panel", "asset-library", "component-inspector", "design-tokens"]
42
+ },
43
+ lexicon: {
44
+ terminology: ["wireframe", "mockup", "prototype", "design-system", "component-library", "style-guide", "user-flow", "information-architecture"],
45
+ language: "design-focused",
46
+ abbreviations: ["UX", "UI", "IA", "A11Y", "DS", "DT"]
47
+ },
48
+ frames: {
49
+ primary: ["canvas-frame", "component-library-frame", "prototype-frame"],
50
+ secondary: ["color-palette-frame", "typography-frame", "spacing-frame"],
51
+ utility: ["export-frame", "handoff-frame", "feedback-frame"]
52
+ },
53
+ templates: {
54
+ layouts: ["responsive-grid", "mobile-first", "desktop-canvas", "tablet-adaptive"],
55
+ components: ["button-system", "form-elements", "navigation-patterns", "card-layouts"],
56
+ pages: ["landing-page", "dashboard", "settings-page", "onboarding-flow"]
57
+ },
58
+ workflows: {
59
+ design: ["research-ideate-design-test", "sketch-wireframe-mockup-prototype"],
60
+ review: ["design-critique", "stakeholder-review", "usability-testing"],
61
+ handoff: ["spec-generation", "asset-export", "developer-handoff"]
62
+ },
63
+ aiModels: {
64
+ generation: ["layout-generator", "color-palette-ai", "icon-generator"],
65
+ analysis: ["design-consistency-checker", "accessibility-auditor", "visual-hierarchy-analyzer"],
66
+ suggestion: ["component-recommender", "layout-optimizer", "design-pattern-matcher"]
67
+ }
68
+ },
69
+ agilePM: {
70
+ sprints: {
71
+ methodology: "design-sprint",
72
+ cycles: ["understand", "diverge", "converge", "prototype", "test"],
73
+ duration: "1-week"
74
+ },
75
+ userStories: {
76
+ format: ["As a user, I want...", "Design requirement:", "Visual specification:"],
77
+ priorities: ["must-have", "should-have", "nice-to-have"],
78
+ categories: ["ux-improvement", "visual-design", "accessibility", "responsive"]
79
+ },
80
+ backlog: {
81
+ categories: ["design-tasks", "research-tasks", "prototype-tasks", "review-tasks"],
82
+ priorities: ["critical", "high", "medium", "low"],
83
+ estimations: ["story-points", "design-complexity", "research-hours"]
84
+ },
85
+ analytics: {
86
+ metrics: ["design-velocity", "iteration-count", "user-satisfaction", "accessibility-score"],
87
+ reports: ["sprint-design-report", "ux-metrics-dashboard", "design-debt-tracker"],
88
+ tracking: ["task-completion", "review-cycles", "design-quality"]
89
+ }
90
+ }
91
+ },
92
+ developer: {
93
+ name: "Developer",
94
+ description: "Software developer focused on building robust, scalable applications with clean code",
95
+ focus: ["coding", "architecture", "testing", "deployment", "performance"],
96
+ studio: {
97
+ interface: {
98
+ layout: "code-centric",
99
+ colorScheme: "dark-professional",
100
+ typography: "monospace-primary",
101
+ visualElements: ["code-editor", "terminal-panel", "file-explorer", "git-panel", "debugger"]
102
+ },
103
+ lexicon: {
104
+ terminology: ["refactor", "deploy", "CI/CD", "microservice", "API", "SDK", "middleware", "ORM"],
105
+ language: "technical",
106
+ abbreviations: ["API", "SDK", "CI", "CD", "PR", "MR", "TDD", "BDD"]
107
+ },
108
+ frames: {
109
+ primary: ["code-editor-frame", "terminal-frame", "debug-frame"],
110
+ secondary: ["git-history-frame", "dependency-frame", "test-runner-frame"],
111
+ utility: ["documentation-frame", "api-explorer-frame", "performance-frame"]
112
+ },
113
+ templates: {
114
+ code: ["microservice-template", "api-gateway", "worker-service", "cli-tool"],
115
+ testing: ["unit-test-suite", "integration-test", "e2e-test", "load-test"],
116
+ deployment: ["docker-compose", "kubernetes-manifest", "serverless-config", "ci-pipeline"]
117
+ },
118
+ workflows: {
119
+ development: ["branch-develop-test-merge", "trunk-based-development"],
120
+ review: ["code-review", "pair-programming", "mob-programming"],
121
+ deployment: ["blue-green", "canary", "rolling-update", "feature-flags"]
122
+ },
123
+ aiModels: {
124
+ generation: ["code-generator", "test-generator", "documentation-generator"],
125
+ analysis: ["code-quality-analyzer", "security-scanner", "performance-profiler"],
126
+ suggestion: ["refactoring-advisor", "architecture-recommender", "dependency-checker"]
127
+ }
128
+ },
129
+ agilePM: {
130
+ sprints: {
131
+ methodology: "scrum",
132
+ cycles: ["planning", "daily-standup", "development", "review", "retrospective"],
133
+ duration: "2-weeks"
134
+ },
135
+ userStories: {
136
+ format: ["As a developer, I want...", "Technical requirement:", "Bug fix:"],
137
+ priorities: ["blocker", "critical", "major", "minor"],
138
+ categories: ["feature", "bug-fix", "tech-debt", "infrastructure"]
139
+ },
140
+ backlog: {
141
+ categories: ["features", "bugs", "tech-debt", "infrastructure", "documentation"],
142
+ priorities: ["critical", "high", "medium", "low"],
143
+ estimations: ["story-points", "fibonacci", "t-shirt-sizing"]
144
+ },
145
+ analytics: {
146
+ metrics: ["velocity", "bug-rate", "code-coverage", "deployment-frequency"],
147
+ reports: ["sprint-burndown", "velocity-chart", "cumulative-flow", "defect-density"],
148
+ tracking: ["task-hours", "story-completion", "sprint-goal-achievement"]
149
+ }
150
+ }
151
+ },
152
+ business_analyst: {
153
+ name: "Business Analyst",
154
+ description: "Business analyst focused on requirements gathering, process optimization, and stakeholder management",
155
+ focus: ["requirements", "process-analysis", "stakeholder-management", "data-analysis", "documentation"],
156
+ studio: {
157
+ interface: {
158
+ layout: "document-centric",
159
+ colorScheme: "professional-neutral",
160
+ typography: "serif-readable",
161
+ visualElements: ["document-editor", "diagram-tool", "spreadsheet", "stakeholder-map", "process-modeler"]
162
+ },
163
+ lexicon: {
164
+ terminology: ["requirement", "stakeholder", "process-flow", "use-case", "acceptance-criteria", "business-rule", "gap-analysis", "feasibility"],
165
+ language: "business-professional",
166
+ abbreviations: ["BA", "BRD", "SRS", "UAT", "KPI", "ROI", "SWOT"]
167
+ },
168
+ frames: {
169
+ primary: ["requirements-frame", "process-modeler-frame", "stakeholder-frame"],
170
+ secondary: ["data-analysis-frame", "reporting-frame", "documentation-frame"],
171
+ utility: ["meeting-notes-frame", "decision-log-frame", "risk-register-frame"]
172
+ },
173
+ templates: {
174
+ documents: ["business-requirements-doc", "functional-spec", "use-case-doc", "process-map"],
175
+ analysis: ["gap-analysis-template", "swot-analysis", "cost-benefit-analysis", "feasibility-study"],
176
+ presentations: ["stakeholder-presentation", "project-proposal", "status-report", "executive-summary"]
177
+ },
178
+ workflows: {
179
+ requirements: ["elicit-analyze-validate-manage", "interview-workshop-prototype-review"],
180
+ analysis: ["as-is-to-be-gap-recommendation", "data-collection-analysis-insight"],
181
+ management: ["stakeholder-identification-analysis-engagement", "change-impact-assessment"]
182
+ },
183
+ aiModels: {
184
+ generation: ["requirements-generator", "process-flow-generator", "report-generator"],
185
+ analysis: ["requirements-conflict-detector", "process-bottleneck-analyzer", "stakeholder-sentiment-analyzer"],
186
+ suggestion: ["requirement-prioritizer", "process-optimizer", "risk-identifier"]
187
+ }
188
+ },
189
+ agilePM: {
190
+ sprints: {
191
+ methodology: "kanban",
192
+ cycles: ["intake", "analysis", "validation", "documentation", "handoff"],
193
+ duration: "continuous"
194
+ },
195
+ userStories: {
196
+ format: ["As a business user, I want...", "Business requirement:", "Process improvement:"],
197
+ priorities: ["business-critical", "high-value", "medium-value", "low-value"],
198
+ categories: ["new-requirement", "change-request", "process-improvement", "compliance"]
199
+ },
200
+ backlog: {
201
+ categories: ["requirements", "analysis-tasks", "documentation", "reviews", "meetings"],
202
+ priorities: ["urgent", "high", "medium", "low"],
203
+ estimations: ["effort-hours", "complexity-rating", "business-value-score"]
204
+ },
205
+ analytics: {
206
+ metrics: ["requirements-throughput", "stakeholder-satisfaction", "defect-leakage", "requirement-stability"],
207
+ reports: ["requirements-status", "stakeholder-engagement", "process-efficiency", "change-impact"],
208
+ tracking: ["requirement-lifecycle", "approval-cycle-time", "rework-rate"]
209
+ }
210
+ }
211
+ },
212
+ data_scientist: {
213
+ name: "Data Scientist",
214
+ description: "Data scientist focused on extracting insights from data through analysis, modeling, and visualization",
215
+ focus: ["data-analysis", "machine-learning", "statistical-modeling", "data-visualization", "feature-engineering"],
216
+ studio: {
217
+ interface: {
218
+ layout: "notebook-centric",
219
+ colorScheme: "data-analytical",
220
+ typography: "technical-readable",
221
+ visualElements: ["notebook-editor", "data-explorer", "chart-builder", "model-inspector", "pipeline-viewer"]
222
+ },
223
+ lexicon: {
224
+ terminology: ["feature-engineering", "model-training", "hyperparameter", "cross-validation", "dimensionality-reduction", "ensemble", "gradient-descent", "overfitting"],
225
+ language: "scientific-technical",
226
+ abbreviations: ["ML", "DL", "NLP", "CNN", "RNN", "GAN", "PCA", "AUC"]
227
+ },
228
+ frames: {
229
+ primary: ["notebook-frame", "data-explorer-frame", "visualization-frame"],
230
+ secondary: ["model-training-frame", "experiment-tracker-frame", "pipeline-frame"],
231
+ utility: ["dataset-catalog-frame", "feature-store-frame", "model-registry-frame"]
232
+ },
233
+ templates: {
234
+ notebooks: ["eda-notebook", "model-training-notebook", "feature-engineering-notebook", "evaluation-notebook"],
235
+ pipelines: ["data-ingestion-pipeline", "feature-pipeline", "training-pipeline", "inference-pipeline"],
236
+ reports: ["analysis-report", "model-performance-report", "data-quality-report", "experiment-summary"]
237
+ },
238
+ workflows: {
239
+ analysis: ["collect-clean-explore-model-evaluate", "hypothesis-experiment-analyze-report"],
240
+ modeling: ["feature-select-train-validate-deploy", "experiment-track-compare-select"],
241
+ deployment: ["model-package-test-deploy-monitor", "ab-test-evaluate-rollout"]
242
+ },
243
+ aiModels: {
244
+ generation: ["feature-generator", "model-architecture-generator", "data-augmentation"],
245
+ analysis: ["data-quality-analyzer", "model-explainer", "drift-detector"],
246
+ suggestion: ["algorithm-recommender", "hyperparameter-tuner", "feature-importance-ranker"]
247
+ }
248
+ },
249
+ agilePM: {
250
+ sprints: {
251
+ methodology: "crisp-dm",
252
+ cycles: ["business-understanding", "data-understanding", "data-preparation", "modeling", "evaluation", "deployment"],
253
+ duration: "3-weeks"
254
+ },
255
+ userStories: {
256
+ format: ["As a data scientist, I want...", "Analysis requirement:", "Model specification:"],
257
+ priorities: ["high-impact", "medium-impact", "low-impact", "experimental"],
258
+ categories: ["data-exploration", "feature-engineering", "model-development", "deployment"]
259
+ },
260
+ backlog: {
261
+ categories: ["data-tasks", "modeling-tasks", "evaluation-tasks", "deployment-tasks", "research"],
262
+ priorities: ["critical", "high", "medium", "low"],
263
+ estimations: ["complexity-points", "computation-hours", "research-days"]
264
+ },
265
+ analytics: {
266
+ metrics: ["model-accuracy", "experiment-throughput", "data-pipeline-reliability", "model-latency"],
267
+ reports: ["experiment-dashboard", "model-comparison", "data-quality-dashboard", "pipeline-health"],
268
+ tracking: ["experiment-progress", "model-performance-over-time", "data-freshness"]
269
+ }
270
+ }
271
+ },
272
+ product_manager: {
273
+ name: "Product Manager",
274
+ description: "Product manager focused on strategy, roadmapping, and delivering value to users and the business",
275
+ focus: ["product-strategy", "roadmapping", "user-research", "prioritization", "go-to-market"],
276
+ studio: {
277
+ interface: {
278
+ layout: "strategic-overview",
279
+ colorScheme: "executive-clean",
280
+ typography: "professional-modern",
281
+ visualElements: ["roadmap-board", "metrics-dashboard", "user-feedback-panel", "competitive-landscape", "okr-tracker"]
282
+ },
283
+ lexicon: {
284
+ terminology: ["product-market-fit", "north-star-metric", "user-persona", "value-proposition", "product-backlog", "release-train", "feature-flag", "a-b-test"],
285
+ language: "product-strategic",
286
+ abbreviations: ["PM", "PRD", "OKR", "KPI", "MRR", "ARR", "NPS", "DAU", "MAU"]
287
+ },
288
+ frames: {
289
+ primary: ["roadmap-frame", "metrics-frame", "feedback-frame"],
290
+ secondary: ["competitive-analysis-frame", "user-research-frame", "release-frame"],
291
+ utility: ["stakeholder-frame", "experiment-frame", "documentation-frame"]
292
+ },
293
+ templates: {
294
+ documents: ["product-requirements-doc", "product-brief", "go-to-market-plan", "competitive-analysis"],
295
+ planning: ["quarterly-roadmap", "release-plan", "experiment-plan", "launch-checklist"],
296
+ communication: ["stakeholder-update", "sprint-review-deck", "product-newsletter", "feature-announcement"]
297
+ },
298
+ workflows: {
299
+ discovery: ["research-ideate-validate-build", "opportunity-solution-tree"],
300
+ delivery: ["define-design-develop-deliver", "dual-track-agile"],
301
+ analysis: ["measure-analyze-learn-iterate", "hypothesis-driven-development"]
302
+ },
303
+ aiModels: {
304
+ generation: ["prd-generator", "roadmap-generator", "release-notes-generator"],
305
+ analysis: ["user-feedback-analyzer", "competitive-intelligence", "churn-predictor"],
306
+ suggestion: ["feature-prioritizer", "experiment-recommender", "pricing-optimizer"]
307
+ }
308
+ },
309
+ agilePM: {
310
+ sprints: {
311
+ methodology: "dual-track-agile",
312
+ cycles: ["discovery", "definition", "delivery", "measurement", "iteration"],
313
+ duration: "2-weeks"
314
+ },
315
+ userStories: {
316
+ format: ["As a product user, I want...", "Product requirement:", "Feature specification:"],
317
+ priorities: ["must-have", "should-have", "could-have", "wont-have"],
318
+ categories: ["new-feature", "enhancement", "experiment", "tech-enabler"]
319
+ },
320
+ backlog: {
321
+ categories: ["features", "experiments", "tech-enablers", "bugs", "improvements"],
322
+ priorities: ["p0-critical", "p1-high", "p2-medium", "p3-low"],
323
+ estimations: ["impact-effort-matrix", "rice-score", "weighted-scoring"]
324
+ },
325
+ analytics: {
326
+ metrics: ["feature-adoption", "time-to-value", "customer-satisfaction", "revenue-impact"],
327
+ reports: ["product-health-dashboard", "feature-performance", "okr-progress", "release-metrics"],
328
+ tracking: ["feature-usage", "experiment-results", "customer-feedback-trends"]
329
+ }
330
+ }
331
+ }
332
+ };
333
+ for (const [id, config] of Object.entries(corePersonas)) {
334
+ const persona = {
335
+ ...config,
336
+ id,
337
+ createdAt: /* @__PURE__ */ new Date(),
338
+ lastModified: /* @__PURE__ */ new Date(),
339
+ usageCount: 0,
340
+ adaptationScore: 0,
341
+ customizations: /* @__PURE__ */ new Map()
342
+ };
343
+ this.personas.set(id, persona);
344
+ }
345
+ }
346
+ // ─── Event Listeners ──────────────────────────────────────────────────────
347
+ initializeEventListeners() {
348
+ this.on("persona:activated", (data) => {
349
+ console.log(`[BaselinePersonaEngine] Persona activated: ${data.personaId} for user ${data.userId}`);
350
+ });
351
+ this.on("persona:switched", (data) => {
352
+ console.log(`[BaselinePersonaEngine] Persona switched from ${data.fromPersonaId} to ${data.toPersonaId} for user ${data.userId}`);
353
+ });
354
+ this.on("persona:customized", (data) => {
355
+ console.log(`[BaselinePersonaEngine] Persona customized: ${data.personaId} for user ${data.userId}`);
356
+ });
357
+ this.on("behavior:recorded", (data) => {
358
+ if (this.config.enableBehavioralAnalysis) {
359
+ const patterns = this.analyzeBehaviorPatterns(data.userId);
360
+ if (patterns.length > 0 && this.config.enableAutonomousLearning) {
361
+ this.adaptPersonaAutonomously(data.userId, patterns);
362
+ }
363
+ }
364
+ });
365
+ this.on("adaptation:applied", (data) => {
366
+ console.log(`[BaselinePersonaEngine] Adaptation applied: ${data.type} to persona ${data.personaId} for user ${data.userId}`);
367
+ });
368
+ }
369
+ // ─── Persona Management ───────────────────────────────────────────────────
370
+ addPersona(id, config) {
371
+ if (this.personas.has(id)) {
372
+ throw new Error(`Persona with id '${id}' already exists`);
373
+ }
374
+ const persona = {
375
+ ...config,
376
+ id,
377
+ createdAt: /* @__PURE__ */ new Date(),
378
+ lastModified: /* @__PURE__ */ new Date(),
379
+ usageCount: 0,
380
+ adaptationScore: 0,
381
+ customizations: /* @__PURE__ */ new Map()
382
+ };
383
+ this.personas.set(id, persona);
384
+ this.emit("persona:added", { personaId: id });
385
+ console.log(`[BaselinePersonaEngine] Persona added: ${id}`);
386
+ return persona;
387
+ }
388
+ setActivePersona(personaId, userId) {
389
+ const persona = this.personas.get(personaId);
390
+ if (!persona) {
391
+ throw new Error(`Persona '${personaId}' not found`);
392
+ }
393
+ const activePersona = {
394
+ ...persona,
395
+ userId,
396
+ activatedAt: /* @__PURE__ */ new Date(),
397
+ sessionId: randomUUID()
398
+ };
399
+ persona.usageCount++;
400
+ persona.lastModified = /* @__PURE__ */ new Date();
401
+ this.activePersonas.set(userId, activePersona);
402
+ this.emit("persona:activated", { personaId, userId });
403
+ return activePersona;
404
+ }
405
+ getActivePersona(userId) {
406
+ return this.activePersonas.get(userId);
407
+ }
408
+ getStudioConfig(userId) {
409
+ const activePersona = this.activePersonas.get(userId);
410
+ if (!activePersona) {
411
+ return null;
412
+ }
413
+ return activePersona.studio;
414
+ }
415
+ getAgilePMConfig(userId) {
416
+ const activePersona = this.activePersonas.get(userId);
417
+ if (!activePersona) {
418
+ return null;
419
+ }
420
+ return activePersona.agilePM;
421
+ }
422
+ customizePersona(personaId, userId, customizations) {
423
+ const persona = this.personas.get(personaId);
424
+ if (!persona) {
425
+ throw new Error(`Persona '${personaId}' not found`);
426
+ }
427
+ persona.customizations.set(userId, {
428
+ ...persona.customizations.get(userId) || {},
429
+ ...customizations
430
+ });
431
+ persona.lastModified = /* @__PURE__ */ new Date();
432
+ const activePersona = this.activePersonas.get(userId);
433
+ if (activePersona && activePersona.id === personaId) {
434
+ Object.assign(activePersona, this.deepMerge(activePersona, customizations));
435
+ }
436
+ this.emit("persona:customized", { personaId, userId, customizations });
437
+ return persona;
438
+ }
439
+ getPersonalizedPersona(personaId, userId) {
440
+ const persona = this.personas.get(personaId);
441
+ if (!persona) {
442
+ return null;
443
+ }
444
+ const userCustomizations = persona.customizations.get(userId);
445
+ if (!userCustomizations) {
446
+ return persona;
447
+ }
448
+ return this.deepMerge({ ...persona }, userCustomizations);
449
+ }
450
+ switchPersona(userId, newPersonaId) {
451
+ const currentPersona = this.activePersonas.get(userId);
452
+ const fromPersonaId = currentPersona ? currentPersona.id : "none";
453
+ const newActivePersona = this.setActivePersona(newPersonaId, userId);
454
+ this.emit("persona:switched", { fromPersonaId, toPersonaId: newPersonaId, userId });
455
+ return newActivePersona;
456
+ }
457
+ // ─── Behavioral Learning ──────────────────────────────────────────────────
458
+ learnFromBehavior(userId, behavior) {
459
+ if (!this.behaviorData.has(userId)) {
460
+ this.behaviorData.set(userId, []);
461
+ }
462
+ const entry = {
463
+ ...behavior,
464
+ timestamp: behavior.timestamp || /* @__PURE__ */ new Date()
465
+ };
466
+ this.behaviorData.get(userId).push(entry);
467
+ this.emit("behavior:recorded", { userId, type: behavior.type });
468
+ }
469
+ analyzeBehaviorPatterns(userId) {
470
+ const data = this.behaviorData.get(userId);
471
+ if (!data || data.length < 3) {
472
+ return [];
473
+ }
474
+ const patterns = [];
475
+ const workflowPattern = this.identifyWorkflowPattern(data);
476
+ if (workflowPattern) {
477
+ patterns.push(workflowPattern);
478
+ }
479
+ const toolPattern = this.identifyToolPreferencePattern(data);
480
+ if (toolPattern) {
481
+ patterns.push(toolPattern);
482
+ }
483
+ const timePattern = this.identifyTimePattern(data);
484
+ if (timePattern) {
485
+ patterns.push(timePattern);
486
+ }
487
+ const collaborationPattern = this.identifyCollaborationPattern(data);
488
+ if (collaborationPattern) {
489
+ patterns.push(collaborationPattern);
490
+ }
491
+ return patterns;
492
+ }
493
+ identifyPattern(data, type) {
494
+ const relevantData = data.filter((d) => d.type === type);
495
+ if (relevantData.length < 2) {
496
+ return null;
497
+ }
498
+ const confidence = Math.min(relevantData.length / 10, 1);
499
+ return {
500
+ type,
501
+ confidence,
502
+ data: relevantData
503
+ };
504
+ }
505
+ identifyWorkflowPattern(data) {
506
+ const workflowData = data.filter(
507
+ (d) => d.type === "workflow_start" || d.type === "workflow_complete" || d.type === "workflow_step"
508
+ );
509
+ if (workflowData.length < 3) {
510
+ return null;
511
+ }
512
+ const workflowTypes = /* @__PURE__ */ new Map();
513
+ for (const d of workflowData) {
514
+ const wType = d.workflowType || "unknown";
515
+ workflowTypes.set(wType, (workflowTypes.get(wType) || 0) + 1);
516
+ }
517
+ const confidence = Math.min(workflowData.length / 15, 1);
518
+ return {
519
+ type: "workflow_preference",
520
+ confidence,
521
+ data: workflowData
522
+ };
523
+ }
524
+ identifyToolPreferencePattern(data) {
525
+ const toolData = data.filter(
526
+ (d) => d.type === "tool_used" || d.type === "tool_selected" || d.type === "tool_configured"
527
+ );
528
+ if (toolData.length < 2) {
529
+ return null;
530
+ }
531
+ const confidence = Math.min(toolData.length / 10, 1);
532
+ return {
533
+ type: "tool_preference",
534
+ confidence,
535
+ data: toolData
536
+ };
537
+ }
538
+ identifyTimePattern(data) {
539
+ const timedData = data.filter((d) => d.timestamp instanceof Date);
540
+ if (timedData.length < 5) {
541
+ return null;
542
+ }
543
+ const hours = timedData.map((d) => d.timestamp.getHours());
544
+ const avgHour = hours.reduce((a, b) => a + b, 0) / hours.length;
545
+ const variance = hours.reduce((sum, h) => sum + Math.pow(h - avgHour, 2), 0) / hours.length;
546
+ if (variance < 16) {
547
+ return {
548
+ type: "time_preference",
549
+ confidence: Math.min(1 - variance / 16, 1),
550
+ data: timedData
551
+ };
552
+ }
553
+ return null;
554
+ }
555
+ identifyCollaborationPattern(data) {
556
+ const collabData = data.filter(
557
+ (d) => d.type === "collaboration" || d.type === "shared" || d.type === "commented" || d.type === "reviewed"
558
+ );
559
+ if (collabData.length < 2) {
560
+ return null;
561
+ }
562
+ const confidence = Math.min(collabData.length / 8, 1);
563
+ return {
564
+ type: "collaboration_preference",
565
+ confidence,
566
+ data: collabData
567
+ };
568
+ }
569
+ // ─── Autonomous Adaptation ────────────────────────────────────────────────
570
+ adaptPersonaAutonomously(userId, patterns) {
571
+ const activePersona = this.activePersonas.get(userId);
572
+ if (!activePersona) {
573
+ return;
574
+ }
575
+ for (const pattern of patterns) {
576
+ if (pattern.confidence < 0.5) {
577
+ continue;
578
+ }
579
+ const adaptation = this.generateAdaptation(activePersona.id, userId, pattern);
580
+ if (adaptation) {
581
+ this.applyPersonaAdaptation(adaptation);
582
+ }
583
+ }
584
+ }
585
+ generateAdaptation(personaId, userId, pattern) {
586
+ let changes = {};
587
+ switch (pattern.type) {
588
+ case "workflow_preference":
589
+ changes = this.generateWorkflowAdaptation(pattern);
590
+ break;
591
+ case "tool_preference":
592
+ changes = this.generateToolAdaptation(pattern);
593
+ break;
594
+ case "time_preference":
595
+ changes = this.generateTimeAdaptation(pattern);
596
+ break;
597
+ case "collaboration_preference":
598
+ changes = this.generateCollaborationAdaptation(pattern);
599
+ break;
600
+ default:
601
+ return null;
602
+ }
603
+ if (Object.keys(changes).length === 0) {
604
+ return null;
605
+ }
606
+ return {
607
+ id: randomUUID(),
608
+ personaId,
609
+ userId,
610
+ type: pattern.type,
611
+ changes,
612
+ confidence: pattern.confidence,
613
+ appliedAt: /* @__PURE__ */ new Date(),
614
+ source: "autonomous-learning"
615
+ };
616
+ }
617
+ generateWorkflowAdaptation(pattern) {
618
+ const workflowCounts = /* @__PURE__ */ new Map();
619
+ for (const d of pattern.data) {
620
+ const wType = d.workflowType || "default";
621
+ workflowCounts.set(wType, (workflowCounts.get(wType) || 0) + 1);
622
+ }
623
+ let preferredWorkflow = "default";
624
+ let maxCount = 0;
625
+ for (const [wType, count] of workflowCounts) {
626
+ if (count > maxCount) {
627
+ maxCount = count;
628
+ preferredWorkflow = wType;
629
+ }
630
+ }
631
+ return {
632
+ studio: {
633
+ workflows: {
634
+ preferred: preferredWorkflow,
635
+ frequencyMap: Object.fromEntries(workflowCounts)
636
+ }
637
+ }
638
+ };
639
+ }
640
+ generateToolAdaptation(pattern) {
641
+ const toolCounts = /* @__PURE__ */ new Map();
642
+ for (const d of pattern.data) {
643
+ const tool = d.tool || d.toolName || "unknown";
644
+ toolCounts.set(tool, (toolCounts.get(tool) || 0) + 1);
645
+ }
646
+ const preferredTools = [];
647
+ for (const [tool, count] of toolCounts) {
648
+ if (count >= 2) {
649
+ preferredTools.push(tool);
650
+ }
651
+ }
652
+ return {
653
+ studio: {
654
+ interface: {
655
+ preferredTools,
656
+ toolUsageMap: Object.fromEntries(toolCounts)
657
+ }
658
+ }
659
+ };
660
+ }
661
+ generateTimeAdaptation(pattern) {
662
+ const hours = pattern.data.filter((d) => d.timestamp instanceof Date).map((d) => d.timestamp.getHours());
663
+ if (hours.length === 0) {
664
+ return {};
665
+ }
666
+ const avgHour = Math.round(hours.reduce((a, b) => a + b, 0) / hours.length);
667
+ let timePreference = "flexible";
668
+ if (avgHour >= 5 && avgHour < 12) {
669
+ timePreference = "morning";
670
+ } else if (avgHour >= 12 && avgHour < 17) {
671
+ timePreference = "afternoon";
672
+ } else if (avgHour >= 17 && avgHour < 21) {
673
+ timePreference = "evening";
674
+ } else {
675
+ timePreference = "night";
676
+ }
677
+ return {
678
+ preferences: {
679
+ activeHours: { average: avgHour, preference: timePreference }
680
+ }
681
+ };
682
+ }
683
+ generateCollaborationAdaptation(pattern) {
684
+ const collabTypes = /* @__PURE__ */ new Map();
685
+ for (const d of pattern.data) {
686
+ collabTypes.set(d.type, (collabTypes.get(d.type) || 0) + 1);
687
+ }
688
+ const collaborators = /* @__PURE__ */ new Set();
689
+ for (const d of pattern.data) {
690
+ if (d.collaborator) {
691
+ collaborators.add(d.collaborator);
692
+ }
693
+ if (d.reviewer) {
694
+ collaborators.add(d.reviewer);
695
+ }
696
+ }
697
+ return {
698
+ preferences: {
699
+ collaboration: {
700
+ style: collabTypes.size > 2 ? "highly-collaborative" : "selective",
701
+ frequentCollaborators: Array.from(collaborators),
702
+ preferredMethods: Object.fromEntries(collabTypes)
703
+ }
704
+ }
705
+ };
706
+ }
707
+ applyPersonaAdaptation(adaptation) {
708
+ const persona = this.personas.get(adaptation.personaId);
709
+ if (!persona) {
710
+ return;
711
+ }
712
+ const existingCustomizations = persona.customizations.get(adaptation.userId) || {};
713
+ persona.customizations.set(
714
+ adaptation.userId,
715
+ this.deepMerge(existingCustomizations, adaptation.changes)
716
+ );
717
+ persona.adaptationScore = Math.min(persona.adaptationScore + adaptation.confidence * 0.1, 1);
718
+ persona.lastModified = /* @__PURE__ */ new Date();
719
+ const activePersona = this.activePersonas.get(adaptation.userId);
720
+ if (activePersona && activePersona.id === adaptation.personaId) {
721
+ Object.assign(activePersona, this.deepMerge(activePersona, adaptation.changes));
722
+ activePersona.adaptationScore = persona.adaptationScore;
723
+ }
724
+ this.adaptations.push(adaptation);
725
+ this.emit("adaptation:applied", {
726
+ personaId: adaptation.personaId,
727
+ userId: adaptation.userId,
728
+ type: adaptation.type,
729
+ confidence: adaptation.confidence
730
+ });
731
+ }
732
+ // ─── Recommendations ──────────────────────────────────────────────────────
733
+ getPersonaRecommendations(userId, context = {}) {
734
+ const behaviors = this.behaviorData.get(userId) || [];
735
+ const patterns = this.analyzeBehaviorPatterns(userId);
736
+ const recommendations = [];
737
+ for (const [personaId, persona] of this.personas) {
738
+ const patternScore = this.calculatePatternFitScore(persona, patterns);
739
+ const contextScore = this.calculateContextFitScore(persona, context);
740
+ const personaScore = this.calculatePersonaFitScore(persona, behaviors);
741
+ const totalScore = patternScore * 0.4 + contextScore * 0.3 + personaScore * 0.3;
742
+ recommendations.push({
743
+ personaId,
744
+ score: Math.round(totalScore * 100) / 100,
745
+ reasoning: this.generateRecommendationReasoning(persona, patternScore, contextScore, personaScore),
746
+ fitScores: {
747
+ pattern: Math.round(patternScore * 100) / 100,
748
+ context: Math.round(contextScore * 100) / 100,
749
+ persona: Math.round(personaScore * 100) / 100
750
+ }
751
+ });
752
+ }
753
+ recommendations.sort((a, b) => b.score - a.score);
754
+ return recommendations;
755
+ }
756
+ calculatePersonaFitScore(persona, behaviors) {
757
+ if (behaviors.length === 0) {
758
+ return 0.5;
759
+ }
760
+ let score = 0;
761
+ const focusAreas = persona.focus;
762
+ for (const behavior of behaviors) {
763
+ const behaviorType = behavior.type.toLowerCase();
764
+ for (const focus of focusAreas) {
765
+ if (behaviorType.includes(focus) || focus.includes(behaviorType)) {
766
+ score += this.getPatternWeight(behavior.type);
767
+ }
768
+ }
769
+ }
770
+ return Math.min(score / behaviors.length, 1);
771
+ }
772
+ calculatePatternFitScore(persona, patterns) {
773
+ if (patterns.length === 0) {
774
+ return 0.5;
775
+ }
776
+ let totalScore = 0;
777
+ for (const pattern of patterns) {
778
+ const weight = this.getPatternWeight(pattern.type);
779
+ totalScore += pattern.confidence * weight;
780
+ }
781
+ return Math.min(totalScore / patterns.length, 1);
782
+ }
783
+ calculateContextFitScore(persona, context) {
784
+ if (Object.keys(context).length === 0) {
785
+ return 0.5;
786
+ }
787
+ let matchCount = 0;
788
+ let totalChecks = 0;
789
+ const contextData = this.extractContextData(context);
790
+ const focusAreas = persona.focus;
791
+ for (const item of contextData) {
792
+ totalChecks++;
793
+ for (const focus of focusAreas) {
794
+ if (item.toLowerCase().includes(focus) || focus.includes(item.toLowerCase())) {
795
+ matchCount++;
796
+ break;
797
+ }
798
+ }
799
+ }
800
+ return totalChecks > 0 ? matchCount / totalChecks : 0.5;
801
+ }
802
+ generateRecommendationReasoning(persona, patternScore, contextScore, personaScore) {
803
+ const reasons = [];
804
+ if (patternScore > 0.7) {
805
+ reasons.push(`Strong behavioral pattern match with ${persona.name} workflows`);
806
+ } else if (patternScore > 0.4) {
807
+ reasons.push(`Moderate behavioral alignment with ${persona.name} focus areas`);
808
+ }
809
+ if (contextScore > 0.7) {
810
+ reasons.push(`Current context strongly aligns with ${persona.name} capabilities`);
811
+ } else if (contextScore > 0.4) {
812
+ reasons.push(`Some contextual relevance to ${persona.name} tools and processes`);
813
+ }
814
+ if (personaScore > 0.7) {
815
+ reasons.push(`Historical usage patterns strongly favor ${persona.name} persona`);
816
+ } else if (personaScore > 0.4) {
817
+ reasons.push(`Some historical affinity with ${persona.name} persona`);
818
+ }
819
+ if (reasons.length === 0) {
820
+ reasons.push(`${persona.name} is available as a general-purpose persona option`);
821
+ }
822
+ return reasons.join(". ") + ".";
823
+ }
824
+ // ─── Utility Methods ──────────────────────────────────────────────────────
825
+ deepMerge(target, source) {
826
+ const output = { ...target };
827
+ for (const key of Object.keys(source)) {
828
+ if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key]) && !(source[key] instanceof Date) && !(source[key] instanceof Map) && !(source[key] instanceof Set)) {
829
+ if (target[key] && typeof target[key] === "object" && !Array.isArray(target[key])) {
830
+ output[key] = this.deepMerge(target[key], source[key]);
831
+ } else {
832
+ output[key] = { ...source[key] };
833
+ }
834
+ } else {
835
+ output[key] = source[key];
836
+ }
837
+ }
838
+ return output;
839
+ }
840
+ calculateCustomizationLevel(persona) {
841
+ let level = 0;
842
+ for (const [, customizations] of persona.customizations) {
843
+ level += Object.keys(customizations).length;
844
+ }
845
+ return Math.min(level / 10, 1);
846
+ }
847
+ extractContextData(context) {
848
+ const data = [];
849
+ for (const [key, value] of Object.entries(context)) {
850
+ data.push(key);
851
+ if (typeof value === "string") {
852
+ data.push(value);
853
+ } else if (Array.isArray(value)) {
854
+ for (const item of value) {
855
+ if (typeof item === "string") {
856
+ data.push(item);
857
+ }
858
+ }
859
+ }
860
+ }
861
+ return data;
862
+ }
863
+ getPatternWeight(type) {
864
+ const weights = {
865
+ workflow_preference: 0.9,
866
+ tool_preference: 0.8,
867
+ time_preference: 0.3,
868
+ collaboration_preference: 0.7,
869
+ workflow_start: 0.6,
870
+ workflow_complete: 0.8,
871
+ workflow_step: 0.4,
872
+ tool_used: 0.7,
873
+ tool_selected: 0.5,
874
+ tool_configured: 0.6,
875
+ collaboration: 0.5,
876
+ shared: 0.4,
877
+ commented: 0.3,
878
+ reviewed: 0.6
879
+ };
880
+ return weights[type] || 0.5;
881
+ }
882
+ // ─── Analytics & Status ────────────────────────────────────────────────────
883
+ getStatus() {
884
+ return {
885
+ initialized: this.initialized,
886
+ totalPersonas: this.personas.size,
887
+ activePersonas: this.activePersonas.size,
888
+ behaviorDataPoints: this.countBehaviorTypes(),
889
+ adaptationsApplied: this.adaptations.length,
890
+ config: { ...this.config }
891
+ };
892
+ }
893
+ getAnalytics() {
894
+ const behaviorsByType = {};
895
+ for (const [, behaviors] of this.behaviorData) {
896
+ for (const b of behaviors) {
897
+ behaviorsByType[b.type] = (behaviorsByType[b.type] || 0) + 1;
898
+ }
899
+ }
900
+ let totalAdaptationScore = 0;
901
+ let personaCount = 0;
902
+ for (const [, persona] of this.personas) {
903
+ totalAdaptationScore += persona.adaptationScore;
904
+ personaCount++;
905
+ }
906
+ return {
907
+ totalPersonas: this.personas.size,
908
+ activePersonas: this.activePersonas.size,
909
+ totalBehaviors: this.countBehaviorTypes(),
910
+ behaviorsByType,
911
+ totalAdaptations: this.adaptations.length,
912
+ adaptationsByPersona: this.groupAdaptationsByPersona(),
913
+ adaptationsByUser: this.groupAdaptationsByUser(),
914
+ averageAdaptationScore: personaCount > 0 ? totalAdaptationScore / personaCount : 0
915
+ };
916
+ }
917
+ countBehaviorTypes() {
918
+ let total = 0;
919
+ for (const [, behaviors] of this.behaviorData) {
920
+ total += behaviors.length;
921
+ }
922
+ return total;
923
+ }
924
+ groupAdaptationsByPersona() {
925
+ const groups = {};
926
+ for (const adaptation of this.adaptations) {
927
+ groups[adaptation.personaId] = (groups[adaptation.personaId] || 0) + 1;
928
+ }
929
+ return groups;
930
+ }
931
+ groupAdaptationsByUser() {
932
+ const groups = {};
933
+ for (const adaptation of this.adaptations) {
934
+ groups[adaptation.userId] = (groups[adaptation.userId] || 0) + 1;
935
+ }
936
+ return groups;
937
+ }
938
+ };
939
+
940
+ // src/ui.ts
941
+ import { EventEmitter as EventEmitter2 } from "events";
942
+ import { randomUUID as randomUUID2 } from "crypto";
943
+ var PersonaUISystem = class extends EventEmitter2 {
944
+ engine;
945
+ components;
946
+ selectorState;
947
+ studioState;
948
+ workflows;
949
+ progressStates;
950
+ resultDisplays;
951
+ config;
952
+ initialized;
953
+ constructor(engine, config = {}) {
954
+ super();
955
+ this.engine = engine;
956
+ this.components = /* @__PURE__ */ new Map();
957
+ this.workflows = /* @__PURE__ */ new Map();
958
+ this.progressStates = /* @__PURE__ */ new Map();
959
+ this.resultDisplays = /* @__PURE__ */ new Map();
960
+ this.config = {
961
+ defaultLayout: config.defaultLayout || "responsive",
962
+ defaultTheme: config.defaultTheme || "system",
963
+ enableAnimations: config.enableAnimations ?? true,
964
+ enableTransitions: config.enableTransitions ?? true,
965
+ selectorPosition: config.selectorPosition || "top-right",
966
+ maxWorkflows: config.maxWorkflows || 10,
967
+ progressUpdateInterval: config.progressUpdateInterval || 1e3
968
+ };
969
+ this.selectorState = {
970
+ isOpen: false,
971
+ selectedPersonaId: null,
972
+ hoveredPersonaId: null,
973
+ searchQuery: "",
974
+ filteredOptions: []
975
+ };
976
+ this.studioState = {
977
+ activeFrames: [],
978
+ layout: this.config.defaultLayout,
979
+ theme: this.config.defaultTheme,
980
+ panels: [],
981
+ toolbars: []
982
+ };
983
+ this.initialized = false;
984
+ this.initializeComponents();
985
+ this.initializeEventListeners();
986
+ this.initialized = true;
987
+ console.log("[PersonaUISystem] UI system initialized");
988
+ }
989
+ // ─── Component Initialization ─────────────────────────────────────────────
990
+ initializeComponents() {
991
+ this.registerComponent({
992
+ id: "persona-selector",
993
+ type: "selector",
994
+ visible: true,
995
+ position: { x: 0, y: 0 },
996
+ size: { width: 320, height: 480 },
997
+ config: {
998
+ position: this.config.selectorPosition,
999
+ showSearch: true,
1000
+ showDescriptions: true,
1001
+ showFocusAreas: true,
1002
+ animateTransitions: this.config.enableAnimations
1003
+ },
1004
+ state: {}
1005
+ });
1006
+ this.registerComponent({
1007
+ id: "studio-interface",
1008
+ type: "studio",
1009
+ visible: false,
1010
+ position: { x: 0, y: 0 },
1011
+ size: { width: 1920, height: 1080 },
1012
+ config: {
1013
+ layout: this.config.defaultLayout,
1014
+ theme: this.config.defaultTheme,
1015
+ enableDragDrop: true,
1016
+ enableResize: true,
1017
+ enablePanelCollapse: true
1018
+ },
1019
+ state: {}
1020
+ });
1021
+ this.registerComponent({
1022
+ id: "workflow-engine",
1023
+ type: "workflow",
1024
+ visible: false,
1025
+ position: { x: 0, y: 0 },
1026
+ size: { width: 800, height: 600 },
1027
+ config: {
1028
+ maxConcurrent: this.config.maxWorkflows,
1029
+ showProgress: true,
1030
+ enableCancel: true,
1031
+ enablePause: false
1032
+ },
1033
+ state: {}
1034
+ });
1035
+ this.registerComponent({
1036
+ id: "result-display",
1037
+ type: "display",
1038
+ visible: false,
1039
+ position: { x: 0, y: 0 },
1040
+ size: { width: 800, height: 600 },
1041
+ config: {
1042
+ formats: ["table", "chart", "json", "markdown", "html"],
1043
+ defaultFormat: "table",
1044
+ enableExport: true,
1045
+ enableShare: true
1046
+ },
1047
+ state: {}
1048
+ });
1049
+ this.registerComponent({
1050
+ id: "progress-tracker",
1051
+ type: "tracker",
1052
+ visible: false,
1053
+ position: { x: 0, y: 0 },
1054
+ size: { width: 400, height: 200 },
1055
+ config: {
1056
+ updateInterval: this.config.progressUpdateInterval,
1057
+ showEstimatedTime: true,
1058
+ showStepDetails: true,
1059
+ position: "bottom-right"
1060
+ },
1061
+ state: {}
1062
+ });
1063
+ }
1064
+ initializeEventListeners() {
1065
+ this.on("selector:opened", () => {
1066
+ this.selectorState.isOpen = true;
1067
+ this.updateComponent("persona-selector", { state: { isOpen: true } });
1068
+ console.log("[PersonaUISystem] Persona selector opened");
1069
+ });
1070
+ this.on("selector:closed", () => {
1071
+ this.selectorState.isOpen = false;
1072
+ this.selectorState.hoveredPersonaId = null;
1073
+ this.updateComponent("persona-selector", { state: { isOpen: false } });
1074
+ console.log("[PersonaUISystem] Persona selector closed");
1075
+ });
1076
+ this.on("persona:selected", (data) => {
1077
+ this.handlePersonaSelection(data.personaId, data.userId);
1078
+ });
1079
+ this.on("workflow:started", (data) => {
1080
+ this.showComponent("progress-tracker");
1081
+ console.log(`[PersonaUISystem] Workflow started: ${data.workflowId}`);
1082
+ });
1083
+ this.on("workflow:completed", (data) => {
1084
+ this.showComponent("result-display");
1085
+ console.log(`[PersonaUISystem] Workflow completed: ${data.workflowId}`);
1086
+ });
1087
+ this.on("workflow:failed", (data) => {
1088
+ console.log(`[PersonaUISystem] Workflow failed: ${data.workflowId} - ${data.error}`);
1089
+ });
1090
+ }
1091
+ // ─── Component Management ─────────────────────────────────────────────────
1092
+ registerComponent(component) {
1093
+ this.components.set(component.id, component);
1094
+ this.emit("component:registered", { componentId: component.id, type: component.type });
1095
+ }
1096
+ getComponent(id) {
1097
+ return this.components.get(id);
1098
+ }
1099
+ updateComponent(id, updates) {
1100
+ const component = this.components.get(id);
1101
+ if (!component) {
1102
+ return null;
1103
+ }
1104
+ if (updates.config) {
1105
+ component.config = { ...component.config, ...updates.config };
1106
+ }
1107
+ if (updates.state) {
1108
+ component.state = { ...component.state, ...updates.state };
1109
+ }
1110
+ if (updates.position) {
1111
+ component.position = updates.position;
1112
+ }
1113
+ if (updates.size) {
1114
+ component.size = updates.size;
1115
+ }
1116
+ if (updates.visible !== void 0) {
1117
+ component.visible = updates.visible;
1118
+ }
1119
+ this.emit("component:updated", { componentId: id, updates });
1120
+ return component;
1121
+ }
1122
+ showComponent(id) {
1123
+ this.updateComponent(id, { visible: true });
1124
+ this.emit("component:shown", { componentId: id });
1125
+ }
1126
+ hideComponent(id) {
1127
+ this.updateComponent(id, { visible: false });
1128
+ this.emit("component:hidden", { componentId: id });
1129
+ }
1130
+ removeComponent(id) {
1131
+ const removed = this.components.delete(id);
1132
+ if (removed) {
1133
+ this.emit("component:removed", { componentId: id });
1134
+ }
1135
+ return removed;
1136
+ }
1137
+ getAllComponents() {
1138
+ return Array.from(this.components.values());
1139
+ }
1140
+ getVisibleComponents() {
1141
+ return Array.from(this.components.values()).filter((c) => c.visible);
1142
+ }
1143
+ // ─── Persona Selector ─────────────────────────────────────────────────────
1144
+ openSelector() {
1145
+ this.emit("selector:opened");
1146
+ }
1147
+ closeSelector() {
1148
+ this.emit("selector:closed");
1149
+ }
1150
+ toggleSelector() {
1151
+ if (this.selectorState.isOpen) {
1152
+ this.closeSelector();
1153
+ } else {
1154
+ this.openSelector();
1155
+ }
1156
+ }
1157
+ setSearchQuery(query) {
1158
+ this.selectorState.searchQuery = query;
1159
+ const filtered = this.filterPersonaOptions(query);
1160
+ this.selectorState.filteredOptions = filtered;
1161
+ this.emit("selector:filtered", { query, count: filtered.length });
1162
+ return filtered;
1163
+ }
1164
+ filterPersonaOptions(query) {
1165
+ const allOptions = this.getPersonaOptions();
1166
+ if (!query || query.trim() === "") {
1167
+ return allOptions;
1168
+ }
1169
+ const lowerQuery = query.toLowerCase();
1170
+ return allOptions.filter(
1171
+ (option) => option.name.toLowerCase().includes(lowerQuery) || option.description.toLowerCase().includes(lowerQuery) || option.focus.some((f) => f.toLowerCase().includes(lowerQuery))
1172
+ );
1173
+ }
1174
+ getPersonaOptions() {
1175
+ const options = [];
1176
+ const personaColors = {
1177
+ designer: "#FF6B6B",
1178
+ developer: "#4ECDC4",
1179
+ business_analyst: "#45B7D1",
1180
+ data_scientist: "#96CEB4",
1181
+ product_manager: "#FFEAA7"
1182
+ };
1183
+ const personaIcons = {
1184
+ designer: "palette",
1185
+ developer: "code",
1186
+ business_analyst: "briefcase",
1187
+ data_scientist: "chart",
1188
+ product_manager: "target"
1189
+ };
1190
+ const corePersonaIds = ["designer", "developer", "business_analyst", "data_scientist", "product_manager"];
1191
+ for (const id of corePersonaIds) {
1192
+ const persona = this.engine.getActivePersona(id);
1193
+ if (persona) {
1194
+ options.push({
1195
+ id: persona.id,
1196
+ name: persona.name,
1197
+ description: persona.description,
1198
+ focus: persona.focus,
1199
+ icon: personaIcons[id],
1200
+ color: personaColors[id]
1201
+ });
1202
+ } else {
1203
+ options.push(this.getDefaultPersonaOption(id, personaIcons[id], personaColors[id]));
1204
+ }
1205
+ }
1206
+ if (options.length === 0) {
1207
+ for (const id of corePersonaIds) {
1208
+ options.push(this.getDefaultPersonaOption(id, personaIcons[id], personaColors[id]));
1209
+ }
1210
+ }
1211
+ return options;
1212
+ }
1213
+ getDefaultPersonaOption(id, icon, color) {
1214
+ const defaults = {
1215
+ designer: {
1216
+ id: "designer",
1217
+ name: "Designer",
1218
+ description: "Visual and UX designer focused on creating beautiful, intuitive interfaces",
1219
+ focus: ["visual-design", "ux-research", "prototyping", "design-systems", "accessibility"],
1220
+ icon: icon || "palette",
1221
+ color: color || "#FF6B6B"
1222
+ },
1223
+ developer: {
1224
+ id: "developer",
1225
+ name: "Developer",
1226
+ description: "Software developer focused on building robust, scalable applications",
1227
+ focus: ["coding", "architecture", "testing", "deployment", "performance"],
1228
+ icon: icon || "code",
1229
+ color: color || "#4ECDC4"
1230
+ },
1231
+ business_analyst: {
1232
+ id: "business_analyst",
1233
+ name: "Business Analyst",
1234
+ description: "Business analyst focused on requirements gathering and process optimization",
1235
+ focus: ["requirements", "process-analysis", "stakeholder-management", "data-analysis"],
1236
+ icon: icon || "briefcase",
1237
+ color: color || "#45B7D1"
1238
+ },
1239
+ data_scientist: {
1240
+ id: "data_scientist",
1241
+ name: "Data Scientist",
1242
+ description: "Data scientist focused on extracting insights through analysis and modeling",
1243
+ focus: ["data-analysis", "machine-learning", "statistical-modeling", "data-visualization"],
1244
+ icon: icon || "chart",
1245
+ color: color || "#96CEB4"
1246
+ },
1247
+ product_manager: {
1248
+ id: "product_manager",
1249
+ name: "Product Manager",
1250
+ description: "Product manager focused on strategy, roadmapping, and delivering value",
1251
+ focus: ["product-strategy", "roadmapping", "user-research", "prioritization"],
1252
+ icon: icon || "target",
1253
+ color: color || "#FFEAA7"
1254
+ }
1255
+ };
1256
+ return defaults[id] || {
1257
+ id,
1258
+ name: id.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()),
1259
+ description: `Persona: ${id}`,
1260
+ focus: [],
1261
+ icon: icon || "user",
1262
+ color: color || "#CCCCCC"
1263
+ };
1264
+ }
1265
+ hoverPersona(personaId) {
1266
+ this.selectorState.hoveredPersonaId = personaId;
1267
+ this.emit("selector:hovered", { personaId });
1268
+ }
1269
+ selectPersona(personaId, userId) {
1270
+ this.selectorState.selectedPersonaId = personaId;
1271
+ this.emit("persona:selected", { personaId, userId });
1272
+ this.closeSelector();
1273
+ }
1274
+ getSelectorState() {
1275
+ return { ...this.selectorState };
1276
+ }
1277
+ // ─── Persona Selection Handling ────────────────────────────────────────────
1278
+ handlePersonaSelection(personaId, userId) {
1279
+ try {
1280
+ const activePersona = this.engine.setActivePersona(personaId, userId);
1281
+ this.applyPersonaToStudio(activePersona);
1282
+ this.engine.learnFromBehavior(userId, {
1283
+ type: "persona_selected",
1284
+ personaId,
1285
+ timestamp: /* @__PURE__ */ new Date()
1286
+ });
1287
+ console.log(`[PersonaUISystem] Persona applied: ${personaId} for user ${userId}`);
1288
+ } catch (error) {
1289
+ const message = error instanceof Error ? error.message : String(error);
1290
+ console.log(`[PersonaUISystem] Failed to apply persona: ${message}`);
1291
+ this.emit("error", { type: "persona_selection_failed", personaId, userId, error: message });
1292
+ }
1293
+ }
1294
+ applyPersonaToStudio(persona) {
1295
+ const studioConfig = persona.studio;
1296
+ this.studioState.layout = studioConfig.interface.layout;
1297
+ this.studioState.theme = studioConfig.interface.colorScheme;
1298
+ this.studioState.activeFrames = [
1299
+ ...studioConfig.frames.primary || [],
1300
+ ...studioConfig.frames.secondary || []
1301
+ ];
1302
+ this.updateComponent("studio-interface", {
1303
+ visible: true,
1304
+ config: {
1305
+ layout: studioConfig.interface.layout,
1306
+ theme: studioConfig.interface.colorScheme,
1307
+ typography: studioConfig.interface.typography,
1308
+ visualElements: studioConfig.interface.visualElements
1309
+ },
1310
+ state: {
1311
+ activePersonaId: persona.id,
1312
+ activeFrames: this.studioState.activeFrames
1313
+ }
1314
+ });
1315
+ this.studioState.panels = this.generatePanels(studioConfig);
1316
+ this.studioState.toolbars = this.generateToolbars(studioConfig);
1317
+ this.emit("studio:configured", {
1318
+ personaId: persona.id,
1319
+ layout: studioConfig.interface.layout,
1320
+ frameCount: this.studioState.activeFrames.length
1321
+ });
1322
+ }
1323
+ generatePanels(studioConfig) {
1324
+ const panels = [];
1325
+ const visualElements = studioConfig.interface.visualElements || [];
1326
+ for (let i = 0; i < visualElements.length; i++) {
1327
+ panels.push({
1328
+ id: `panel-${visualElements[i]}`,
1329
+ type: "panel",
1330
+ visible: true,
1331
+ position: { x: 0, y: i * 200 },
1332
+ size: { width: 300, height: 200 },
1333
+ config: {
1334
+ title: visualElements[i].replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()),
1335
+ collapsible: true,
1336
+ draggable: true
1337
+ },
1338
+ state: {}
1339
+ });
1340
+ }
1341
+ return panels;
1342
+ }
1343
+ generateToolbars(studioConfig) {
1344
+ const toolbars = [];
1345
+ const workflows = studioConfig.workflows || {};
1346
+ for (const [category, items] of Object.entries(workflows)) {
1347
+ toolbars.push({
1348
+ id: `toolbar-${category}`,
1349
+ type: "toolbar",
1350
+ visible: true,
1351
+ position: { x: 0, y: 0 },
1352
+ size: { width: 600, height: 48 },
1353
+ config: {
1354
+ category,
1355
+ items,
1356
+ orientation: "horizontal"
1357
+ },
1358
+ state: {}
1359
+ });
1360
+ }
1361
+ return toolbars;
1362
+ }
1363
+ getStudioState() {
1364
+ return { ...this.studioState };
1365
+ }
1366
+ // ─── Workflow Engine ──────────────────────────────────────────────────────
1367
+ startWorkflow(type, personaId, userId, parameters = {}) {
1368
+ if (this.workflows.size >= this.config.maxWorkflows) {
1369
+ throw new Error(`Maximum concurrent workflows (${this.config.maxWorkflows}) reached`);
1370
+ }
1371
+ const steps = this.generateWorkflowSteps(type, personaId);
1372
+ const workflow = {
1373
+ id: randomUUID2(),
1374
+ type,
1375
+ personaId,
1376
+ userId,
1377
+ parameters,
1378
+ startTime: /* @__PURE__ */ new Date(),
1379
+ status: "pending",
1380
+ progress: 0,
1381
+ steps,
1382
+ results: {}
1383
+ };
1384
+ this.workflows.set(workflow.id, workflow);
1385
+ const progressState = {
1386
+ workflowId: workflow.id,
1387
+ phase: "initialization",
1388
+ percentage: 0,
1389
+ currentStep: steps.length > 0 ? steps[0].name : "unknown",
1390
+ stepsCompleted: 0,
1391
+ totalSteps: steps.length,
1392
+ startedAt: /* @__PURE__ */ new Date()
1393
+ };
1394
+ this.progressStates.set(workflow.id, progressState);
1395
+ this.emit("workflow:started", { workflowId: workflow.id, type, personaId, userId });
1396
+ this.engine.learnFromBehavior(userId, {
1397
+ type: "workflow_start",
1398
+ workflowType: type,
1399
+ personaId,
1400
+ timestamp: /* @__PURE__ */ new Date()
1401
+ });
1402
+ this.runWorkflow(workflow.id);
1403
+ return workflow;
1404
+ }
1405
+ generateWorkflowSteps(type, _personaId) {
1406
+ const defaultSteps = {
1407
+ design: ["Research", "Ideation", "Wireframing", "Mockup", "Prototype", "Testing", "Iteration"],
1408
+ development: ["Planning", "Architecture", "Implementation", "Testing", "Code Review", "Deployment"],
1409
+ analysis: ["Data Collection", "Data Cleaning", "Exploration", "Analysis", "Visualization", "Reporting"],
1410
+ "product-planning": ["Research", "Strategy", "Requirements", "Prioritization", "Roadmap", "Communication"],
1411
+ "sprint-planning": ["Backlog Review", "Capacity Planning", "Story Selection", "Task Breakdown", "Commitment"],
1412
+ default: ["Initialize", "Process", "Validate", "Complete"]
1413
+ };
1414
+ const stepNames = defaultSteps[type] || defaultSteps["default"];
1415
+ return stepNames.map((name, index) => ({
1416
+ id: randomUUID2(),
1417
+ name,
1418
+ description: `${name} phase of ${type} workflow`,
1419
+ status: index === 0 ? "active" : "pending",
1420
+ data: {}
1421
+ }));
1422
+ }
1423
+ async runWorkflow(workflowId) {
1424
+ const workflow = this.workflows.get(workflowId);
1425
+ if (!workflow) {
1426
+ return;
1427
+ }
1428
+ workflow.status = "running";
1429
+ for (let i = 0; i < workflow.steps.length; i++) {
1430
+ const step = workflow.steps[i];
1431
+ if (workflow.status === "cancelled") {
1432
+ step.status = "skipped";
1433
+ continue;
1434
+ }
1435
+ step.status = "active";
1436
+ step.startedAt = /* @__PURE__ */ new Date();
1437
+ this.updateProgress(workflowId, {
1438
+ phase: step.name.toLowerCase(),
1439
+ currentStep: step.name,
1440
+ stepsCompleted: i,
1441
+ percentage: Math.round(i / workflow.steps.length * 100)
1442
+ });
1443
+ this.emit("workflow:step", { workflowId, stepId: step.id, stepName: step.name, stepIndex: i });
1444
+ try {
1445
+ await this.executeWorkflowStep(workflow, step);
1446
+ step.status = "completed";
1447
+ step.completedAt = /* @__PURE__ */ new Date();
1448
+ } catch (error) {
1449
+ const message = error instanceof Error ? error.message : String(error);
1450
+ step.status = "failed";
1451
+ workflow.status = "failed";
1452
+ workflow.error = message;
1453
+ workflow.endTime = /* @__PURE__ */ new Date();
1454
+ this.emit("workflow:failed", { workflowId, error: message, failedStep: step.name });
1455
+ return;
1456
+ }
1457
+ }
1458
+ workflow.status = "completed";
1459
+ workflow.progress = 100;
1460
+ workflow.endTime = /* @__PURE__ */ new Date();
1461
+ this.updateProgress(workflowId, {
1462
+ phase: "complete",
1463
+ currentStep: "Done",
1464
+ stepsCompleted: workflow.steps.length,
1465
+ percentage: 100
1466
+ });
1467
+ this.generateResults(workflow);
1468
+ this.emit("workflow:completed", { workflowId, results: workflow.results });
1469
+ this.engine.learnFromBehavior(workflow.userId, {
1470
+ type: "workflow_complete",
1471
+ workflowType: workflow.type,
1472
+ personaId: workflow.personaId,
1473
+ duration: workflow.endTime.getTime() - workflow.startTime.getTime(),
1474
+ timestamp: /* @__PURE__ */ new Date()
1475
+ });
1476
+ }
1477
+ async executeWorkflowStep(workflow, step) {
1478
+ const duration = 50 + Math.random() * 150;
1479
+ await new Promise((resolve) => setTimeout(resolve, duration));
1480
+ step.data = {
1481
+ executedAt: /* @__PURE__ */ new Date(),
1482
+ duration,
1483
+ workflowType: workflow.type,
1484
+ personaId: workflow.personaId
1485
+ };
1486
+ }
1487
+ generateResults(workflow) {
1488
+ const completedSteps = workflow.steps.filter((s) => s.status === "completed");
1489
+ const failedSteps = workflow.steps.filter((s) => s.status === "failed");
1490
+ const totalDuration = workflow.endTime ? workflow.endTime.getTime() - workflow.startTime.getTime() : 0;
1491
+ workflow.results = {
1492
+ summary: {
1493
+ workflowType: workflow.type,
1494
+ personaId: workflow.personaId,
1495
+ totalSteps: workflow.steps.length,
1496
+ completedSteps: completedSteps.length,
1497
+ failedSteps: failedSteps.length,
1498
+ totalDuration,
1499
+ averageStepDuration: completedSteps.length > 0 ? totalDuration / completedSteps.length : 0
1500
+ },
1501
+ steps: workflow.steps.map((s) => ({
1502
+ name: s.name,
1503
+ status: s.status,
1504
+ duration: s.completedAt && s.startedAt ? s.completedAt.getTime() - s.startedAt.getTime() : null,
1505
+ data: s.data
1506
+ })),
1507
+ artifacts: this.generateArtifacts(workflow)
1508
+ };
1509
+ }
1510
+ generateArtifacts(workflow) {
1511
+ const artifacts = [];
1512
+ switch (workflow.type) {
1513
+ case "design":
1514
+ artifacts.push(
1515
+ { type: "wireframe", name: "Initial Wireframes", format: "svg" },
1516
+ { type: "mockup", name: "High-Fidelity Mockups", format: "png" },
1517
+ { type: "prototype", name: "Interactive Prototype", format: "html" }
1518
+ );
1519
+ break;
1520
+ case "development":
1521
+ artifacts.push(
1522
+ { type: "code", name: "Source Code", format: "typescript" },
1523
+ { type: "tests", name: "Test Suite", format: "typescript" },
1524
+ { type: "documentation", name: "API Documentation", format: "markdown" }
1525
+ );
1526
+ break;
1527
+ case "analysis":
1528
+ artifacts.push(
1529
+ { type: "dataset", name: "Processed Dataset", format: "csv" },
1530
+ { type: "visualization", name: "Data Visualizations", format: "svg" },
1531
+ { type: "report", name: "Analysis Report", format: "markdown" }
1532
+ );
1533
+ break;
1534
+ case "product-planning":
1535
+ artifacts.push(
1536
+ { type: "roadmap", name: "Product Roadmap", format: "json" },
1537
+ { type: "requirements", name: "Requirements Document", format: "markdown" },
1538
+ { type: "metrics", name: "Success Metrics", format: "json" }
1539
+ );
1540
+ break;
1541
+ default:
1542
+ artifacts.push(
1543
+ { type: "output", name: "Workflow Output", format: "json" }
1544
+ );
1545
+ }
1546
+ return artifacts;
1547
+ }
1548
+ cancelWorkflow(workflowId) {
1549
+ const workflow = this.workflows.get(workflowId);
1550
+ if (!workflow || workflow.status !== "running") {
1551
+ return false;
1552
+ }
1553
+ workflow.status = "cancelled";
1554
+ workflow.endTime = /* @__PURE__ */ new Date();
1555
+ this.emit("workflow:cancelled", { workflowId });
1556
+ return true;
1557
+ }
1558
+ getWorkflow(workflowId) {
1559
+ return this.workflows.get(workflowId);
1560
+ }
1561
+ getActiveWorkflows() {
1562
+ return Array.from(this.workflows.values()).filter(
1563
+ (w) => w.status === "running" || w.status === "pending"
1564
+ );
1565
+ }
1566
+ getCompletedWorkflows() {
1567
+ return Array.from(this.workflows.values()).filter(
1568
+ (w) => w.status === "completed"
1569
+ );
1570
+ }
1571
+ getAllWorkflows() {
1572
+ return Array.from(this.workflows.values());
1573
+ }
1574
+ // ─── Progress Tracking ────────────────────────────────────────────────────
1575
+ updateProgress(workflowId, updates) {
1576
+ const state = this.progressStates.get(workflowId);
1577
+ if (!state) {
1578
+ return;
1579
+ }
1580
+ Object.assign(state, updates);
1581
+ if (state.percentage < 100 && state.stepsCompleted > 0) {
1582
+ const elapsed = Date.now() - state.startedAt.getTime();
1583
+ const avgStepTime = elapsed / state.stepsCompleted;
1584
+ const remainingSteps = state.totalSteps - state.stepsCompleted;
1585
+ state.estimatedTimeRemaining = Math.round(avgStepTime * remainingSteps);
1586
+ }
1587
+ this.emit("progress:updated", { workflowId, progress: { ...state } });
1588
+ }
1589
+ getProgress(workflowId) {
1590
+ return this.progressStates.get(workflowId);
1591
+ }
1592
+ getAllProgress() {
1593
+ return Array.from(this.progressStates.values());
1594
+ }
1595
+ getActiveProgress() {
1596
+ return Array.from(this.progressStates.values()).filter((p) => p.percentage < 100);
1597
+ }
1598
+ // ─── Result Display ───────────────────────────────────────────────────────
1599
+ createResultDisplay(workflowId, type, title, data, format = "table") {
1600
+ const result = {
1601
+ id: randomUUID2(),
1602
+ workflowId,
1603
+ type,
1604
+ title,
1605
+ data,
1606
+ format,
1607
+ createdAt: /* @__PURE__ */ new Date()
1608
+ };
1609
+ this.resultDisplays.set(result.id, result);
1610
+ this.showComponent("result-display");
1611
+ this.emit("result:created", { resultId: result.id, workflowId, type });
1612
+ return result;
1613
+ }
1614
+ getResultDisplay(resultId) {
1615
+ return this.resultDisplays.get(resultId);
1616
+ }
1617
+ getResultsForWorkflow(workflowId) {
1618
+ return Array.from(this.resultDisplays.values()).filter(
1619
+ (r) => r.workflowId === workflowId
1620
+ );
1621
+ }
1622
+ getAllResults() {
1623
+ return Array.from(this.resultDisplays.values());
1624
+ }
1625
+ removeResultDisplay(resultId) {
1626
+ return this.resultDisplays.delete(resultId);
1627
+ }
1628
+ clearResults() {
1629
+ this.resultDisplays.clear();
1630
+ this.emit("results:cleared");
1631
+ }
1632
+ // ─── Layout & Theme ───────────────────────────────────────────────────────
1633
+ setLayout(layout) {
1634
+ this.studioState.layout = layout;
1635
+ this.updateComponent("studio-interface", {
1636
+ config: { layout }
1637
+ });
1638
+ this.emit("layout:changed", { layout });
1639
+ }
1640
+ setTheme(theme) {
1641
+ this.studioState.theme = theme;
1642
+ this.updateComponent("studio-interface", {
1643
+ config: { theme }
1644
+ });
1645
+ this.emit("theme:changed", { theme });
1646
+ }
1647
+ getLayout() {
1648
+ return this.studioState.layout;
1649
+ }
1650
+ getTheme() {
1651
+ return this.studioState.theme;
1652
+ }
1653
+ // ─── Frame Management ─────────────────────────────────────────────────────
1654
+ activateFrame(frameId) {
1655
+ if (!this.studioState.activeFrames.includes(frameId)) {
1656
+ this.studioState.activeFrames.push(frameId);
1657
+ this.emit("frame:activated", { frameId });
1658
+ }
1659
+ }
1660
+ deactivateFrame(frameId) {
1661
+ const index = this.studioState.activeFrames.indexOf(frameId);
1662
+ if (index > -1) {
1663
+ this.studioState.activeFrames.splice(index, 1);
1664
+ this.emit("frame:deactivated", { frameId });
1665
+ }
1666
+ }
1667
+ getActiveFrames() {
1668
+ return [...this.studioState.activeFrames];
1669
+ }
1670
+ setActiveFrames(frameIds) {
1671
+ this.studioState.activeFrames = [...frameIds];
1672
+ this.emit("frames:updated", { frameIds });
1673
+ }
1674
+ // ─── Status & Analytics ───────────────────────────────────────────────────
1675
+ getStatus() {
1676
+ return {
1677
+ initialized: this.initialized,
1678
+ components: this.components.size,
1679
+ visibleComponents: this.getVisibleComponents().length,
1680
+ activeWorkflows: this.getActiveWorkflows().length,
1681
+ completedWorkflows: this.getCompletedWorkflows().length,
1682
+ totalResults: this.resultDisplays.size,
1683
+ selectorState: {
1684
+ isOpen: this.selectorState.isOpen,
1685
+ selectedPersonaId: this.selectorState.selectedPersonaId
1686
+ },
1687
+ studioState: {
1688
+ layout: this.studioState.layout,
1689
+ theme: this.studioState.theme,
1690
+ activeFrames: this.studioState.activeFrames.length,
1691
+ panels: this.studioState.panels.length,
1692
+ toolbars: this.studioState.toolbars.length
1693
+ },
1694
+ config: { ...this.config }
1695
+ };
1696
+ }
1697
+ getUIAnalytics() {
1698
+ const workflows = Array.from(this.workflows.values());
1699
+ const completed = workflows.filter((w) => w.status === "completed");
1700
+ const failed = workflows.filter((w) => w.status === "failed");
1701
+ const totalDuration = completed.reduce((sum, w) => {
1702
+ if (w.endTime) {
1703
+ return sum + (w.endTime.getTime() - w.startTime.getTime());
1704
+ }
1705
+ return sum;
1706
+ }, 0);
1707
+ const workflowsByType = {};
1708
+ for (const w of workflows) {
1709
+ workflowsByType[w.type] = (workflowsByType[w.type] || 0) + 1;
1710
+ }
1711
+ const workflowsByPersona = {};
1712
+ for (const w of workflows) {
1713
+ workflowsByPersona[w.personaId] = (workflowsByPersona[w.personaId] || 0) + 1;
1714
+ }
1715
+ return {
1716
+ totalWorkflows: workflows.length,
1717
+ completedWorkflows: completed.length,
1718
+ failedWorkflows: failed.length,
1719
+ averageDuration: completed.length > 0 ? totalDuration / completed.length : 0,
1720
+ workflowsByType,
1721
+ workflowsByPersona,
1722
+ totalResults: this.resultDisplays.size,
1723
+ componentCount: this.components.size
1724
+ };
1725
+ }
1726
+ // ─── Cleanup ──────────────────────────────────────────────────────────────
1727
+ dispose() {
1728
+ this.removeAllListeners();
1729
+ this.components.clear();
1730
+ this.workflows.clear();
1731
+ this.progressStates.clear();
1732
+ this.resultDisplays.clear();
1733
+ this.initialized = false;
1734
+ console.log("[PersonaUISystem] UI system disposed");
1735
+ }
1736
+ };
1737
+
1738
+ // src/personas/agile-pm.ts
1739
+ import { EventEmitter as EventEmitter3 } from "events";
1740
+ import { randomUUID as randomUUID3 } from "crypto";
1741
+ import { readFile, writeFile } from "fs/promises";
1742
+ var AgileProductManagerPersona = class extends EventEmitter3 {
1743
+ sprints;
1744
+ backlog;
1745
+ velocityHistory;
1746
+ workspacePath;
1747
+ constructor(workspacePath = "./workspace") {
1748
+ super();
1749
+ this.sprints = /* @__PURE__ */ new Map();
1750
+ this.backlog = [];
1751
+ this.velocityHistory = [];
1752
+ this.workspacePath = workspacePath;
1753
+ console.log("[AgileProductManagerPersona] Persona initialized");
1754
+ }
1755
+ // ─── Sprint Management ────────────────────────────────────────────────────
1756
+ createSprint(name, startDate, duration, goals, team) {
1757
+ const endDate = this.calculateEndDate(startDate, duration);
1758
+ const sprint = {
1759
+ id: randomUUID3(),
1760
+ name,
1761
+ startDate,
1762
+ endDate,
1763
+ goals,
1764
+ stories: [],
1765
+ team,
1766
+ status: "planning"
1767
+ };
1768
+ this.sprints.set(sprint.id, sprint);
1769
+ this.emit("sprint:created", { sprintId: sprint.id, name });
1770
+ console.log(`[AgileProductManagerPersona] Sprint created: ${name} (${startDate} - ${endDate})`);
1771
+ return sprint;
1772
+ }
1773
+ addStoryToSprint(sprintId, story) {
1774
+ const sprint = this.sprints.get(sprintId);
1775
+ if (!sprint) {
1776
+ throw new Error(`Sprint '${sprintId}' not found`);
1777
+ }
1778
+ const fullStory = {
1779
+ ...story,
1780
+ id: randomUUID3(),
1781
+ status: "todo",
1782
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1783
+ };
1784
+ sprint.stories.push(fullStory);
1785
+ this.emit("story:added", { sprintId, storyId: fullStory.id, title: fullStory.title });
1786
+ console.log(`[AgileProductManagerPersona] Story added to sprint ${sprint.name}: ${fullStory.title}`);
1787
+ return fullStory;
1788
+ }
1789
+ updateStoryStatus(sprintId, storyId, newStatus) {
1790
+ const sprint = this.sprints.get(sprintId);
1791
+ if (!sprint) {
1792
+ throw new Error(`Sprint '${sprintId}' not found`);
1793
+ }
1794
+ const story = sprint.stories.find((s) => s.id === storyId);
1795
+ if (!story) {
1796
+ throw new Error(`Story '${storyId}' not found in sprint '${sprintId}'`);
1797
+ }
1798
+ const oldStatus = story.status;
1799
+ story.status = newStatus;
1800
+ story.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1801
+ if (newStatus === "done") {
1802
+ story.completedAt = (/* @__PURE__ */ new Date()).toISOString();
1803
+ }
1804
+ this.emit("story:statusChanged", { sprintId, storyId, oldStatus, newStatus });
1805
+ console.log(`[AgileProductManagerPersona] Story ${story.title}: ${oldStatus} -> ${newStatus}`);
1806
+ return story;
1807
+ }
1808
+ // ─── Backlog Management ───────────────────────────────────────────────────
1809
+ addToBacklog(item) {
1810
+ const fullItem = {
1811
+ ...item,
1812
+ id: randomUUID3(),
1813
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
1814
+ };
1815
+ this.backlog.push(fullItem);
1816
+ this.emit("backlog:itemAdded", { itemId: fullItem.id, title: fullItem.title });
1817
+ console.log(`[AgileProductManagerPersona] Backlog item added: ${fullItem.title}`);
1818
+ return fullItem;
1819
+ }
1820
+ prioritizeBacklog(criteria = "priority") {
1821
+ const priorityOrder = {
1822
+ critical: 0,
1823
+ high: 1,
1824
+ medium: 2,
1825
+ low: 3
1826
+ };
1827
+ switch (criteria) {
1828
+ case "priority":
1829
+ this.backlog.sort((a, b) => {
1830
+ const aPriority = priorityOrder[a.priority] ?? 4;
1831
+ const bPriority = priorityOrder[b.priority] ?? 4;
1832
+ return aPriority - bPriority;
1833
+ });
1834
+ break;
1835
+ case "points":
1836
+ this.backlog.sort((a, b) => b.points - a.points);
1837
+ break;
1838
+ case "created":
1839
+ this.backlog.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
1840
+ break;
1841
+ case "type":
1842
+ this.backlog.sort((a, b) => a.type.localeCompare(b.type));
1843
+ break;
1844
+ default:
1845
+ this.backlog.sort((a, b) => {
1846
+ const aPriority = priorityOrder[a.priority] ?? 4;
1847
+ const bPriority = priorityOrder[b.priority] ?? 4;
1848
+ return aPriority - bPriority;
1849
+ });
1850
+ }
1851
+ this.emit("backlog:prioritized", { criteria, itemCount: this.backlog.length });
1852
+ console.log(`[AgileProductManagerPersona] Backlog prioritized by ${criteria}: ${this.backlog.length} items`);
1853
+ return [...this.backlog];
1854
+ }
1855
+ // ─── Velocity & Metrics ───────────────────────────────────────────────────
1856
+ calculateVelocity(sprintId) {
1857
+ const sprint = this.sprints.get(sprintId);
1858
+ if (!sprint) {
1859
+ throw new Error(`Sprint '${sprintId}' not found`);
1860
+ }
1861
+ const totalPoints = sprint.stories.reduce((sum, s) => sum + s.points, 0);
1862
+ const completedPoints = sprint.stories.filter((s) => s.status === "done").reduce((sum, s) => sum + s.points, 0);
1863
+ const velocityData = {
1864
+ sprintId: sprint.id,
1865
+ sprintName: sprint.name,
1866
+ plannedPoints: totalPoints,
1867
+ completedPoints,
1868
+ velocity: completedPoints
1869
+ };
1870
+ this.velocityHistory.push(velocityData);
1871
+ this.emit("velocity:calculated", { sprintId, velocity: completedPoints });
1872
+ return velocityData;
1873
+ }
1874
+ // ─── Reporting ────────────────────────────────────────────────────────────
1875
+ generateSprintReport(sprintId) {
1876
+ const sprint = this.sprints.get(sprintId);
1877
+ if (!sprint) {
1878
+ throw new Error(`Sprint '${sprintId}' not found`);
1879
+ }
1880
+ const totalStories = sprint.stories.length;
1881
+ const completedStories = sprint.stories.filter((s) => s.status === "done").length;
1882
+ const totalPoints = sprint.stories.reduce((sum, s) => sum + s.points, 0);
1883
+ const completedPoints = sprint.stories.filter((s) => s.status === "done").reduce((sum, s) => sum + s.points, 0);
1884
+ const storiesByStatus = {};
1885
+ for (const story of sprint.stories) {
1886
+ storiesByStatus[story.status] = (storiesByStatus[story.status] || 0) + 1;
1887
+ }
1888
+ const storiesByPriority = {};
1889
+ for (const story of sprint.stories) {
1890
+ storiesByPriority[story.priority] = (storiesByPriority[story.priority] || 0) + 1;
1891
+ }
1892
+ const report = {
1893
+ sprint,
1894
+ totalStories,
1895
+ completedStories,
1896
+ totalPoints,
1897
+ completedPoints,
1898
+ completionRate: totalStories > 0 ? completedStories / totalStories * 100 : 0,
1899
+ velocity: completedPoints,
1900
+ storiesByStatus,
1901
+ storiesByPriority
1902
+ };
1903
+ this.emit("report:generated", { sprintId, type: "sprint" });
1904
+ console.log(`[AgileProductManagerPersona] Sprint report generated for: ${sprint.name}`);
1905
+ return report;
1906
+ }
1907
+ generateBurndownData(sprintId) {
1908
+ const sprint = this.sprints.get(sprintId);
1909
+ if (!sprint) {
1910
+ throw new Error(`Sprint '${sprintId}' not found`);
1911
+ }
1912
+ const totalPoints = sprint.stories.reduce((sum, s) => sum + s.points, 0);
1913
+ const startDate = new Date(sprint.startDate);
1914
+ const endDate = new Date(sprint.endDate);
1915
+ const totalDays = Math.ceil((endDate.getTime() - startDate.getTime()) / (1e3 * 60 * 60 * 24));
1916
+ const dailyIdealBurn = totalPoints / totalDays;
1917
+ const burndownData = [];
1918
+ let actualRemaining = totalPoints;
1919
+ for (let day = 0; day <= totalDays; day++) {
1920
+ const currentDate = new Date(startDate);
1921
+ currentDate.setDate(currentDate.getDate() + day);
1922
+ const dateStr = currentDate.toISOString().split("T")[0];
1923
+ const storiesCompletedByDate = sprint.stories.filter((s) => {
1924
+ if (!s.completedAt) return false;
1925
+ return new Date(s.completedAt) <= currentDate;
1926
+ });
1927
+ const completedPoints = storiesCompletedByDate.reduce((sum, s) => sum + s.points, 0);
1928
+ actualRemaining = totalPoints - completedPoints;
1929
+ burndownData.push({
1930
+ day,
1931
+ date: dateStr,
1932
+ idealRemaining: Math.max(0, totalPoints - dailyIdealBurn * day),
1933
+ actualRemaining
1934
+ });
1935
+ }
1936
+ this.emit("burndown:generated", { sprintId, dataPoints: burndownData.length });
1937
+ return burndownData;
1938
+ }
1939
+ // ─── Utility Methods ──────────────────────────────────────────────────────
1940
+ calculateEndDate(startDate, durationDays) {
1941
+ const date = new Date(startDate);
1942
+ date.setDate(date.getDate() + durationDays);
1943
+ return date.toISOString().split("T")[0];
1944
+ }
1945
+ async loadWorkspaceData() {
1946
+ try {
1947
+ const filePath = `${this.workspacePath}/agile-pm-data.json`;
1948
+ const data = await readFile(filePath, "utf-8");
1949
+ const parsed = JSON.parse(data);
1950
+ for (const sprint of parsed.sprints) {
1951
+ this.sprints.set(sprint.id, sprint);
1952
+ }
1953
+ this.backlog = parsed.backlog || [];
1954
+ console.log(`[AgileProductManagerPersona] Workspace data loaded: ${this.sprints.size} sprints, ${this.backlog.length} backlog items`);
1955
+ return parsed;
1956
+ } catch (error) {
1957
+ const message = error instanceof Error ? error.message : String(error);
1958
+ console.log(`[AgileProductManagerPersona] No existing workspace data found: ${message}`);
1959
+ return null;
1960
+ }
1961
+ }
1962
+ async saveWorkspaceData() {
1963
+ try {
1964
+ const data = {
1965
+ sprints: Array.from(this.sprints.values()),
1966
+ backlog: this.backlog,
1967
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
1968
+ };
1969
+ const filePath = `${this.workspacePath}/agile-pm-data.json`;
1970
+ await writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
1971
+ console.log("[AgileProductManagerPersona] Workspace data saved");
1972
+ } catch (error) {
1973
+ const message = error instanceof Error ? error.message : String(error);
1974
+ console.log(`[AgileProductManagerPersona] Failed to save workspace data: ${message}`);
1975
+ }
1976
+ }
1977
+ getPersonaStatus() {
1978
+ const activeSprints = Array.from(this.sprints.values()).filter(
1979
+ (s) => s.status === "active" || s.status === "planning"
1980
+ );
1981
+ const completedSprints = Array.from(this.sprints.values()).filter(
1982
+ (s) => s.status === "completed"
1983
+ );
1984
+ let totalStories = 0;
1985
+ for (const sprint of this.sprints.values()) {
1986
+ totalStories += sprint.stories.length;
1987
+ }
1988
+ const avgVelocity = this.velocityHistory.length > 0 ? this.velocityHistory.reduce((sum, v) => sum + v.velocity, 0) / this.velocityHistory.length : 0;
1989
+ return {
1990
+ persona: "Agile Product Manager",
1991
+ activeSprints: activeSprints.length,
1992
+ totalStories,
1993
+ backlogSize: this.backlog.length,
1994
+ averageVelocity: Math.round(avgVelocity * 100) / 100,
1995
+ completedSprints: completedSprints.length
1996
+ };
1997
+ }
1998
+ };
1999
+
2000
+ // src/personas/dev-lead.ts
2001
+ import { EventEmitter as EventEmitter4 } from "events";
2002
+ import { randomUUID as randomUUID4 } from "crypto";
2003
+ import { exec } from "child_process";
2004
+ import { promisify } from "util";
2005
+ import { readFile as readFile2, writeFile as writeFile2, access } from "fs/promises";
2006
+ import { constants as fsConstants } from "fs";
2007
+ var execAsync = promisify(exec);
2008
+ var SoftwareDevelopmentLeadPersona = class extends EventEmitter4 {
2009
+ team;
2010
+ reviews;
2011
+ techDebt;
2012
+ builds;
2013
+ tests;
2014
+ workspacePath;
2015
+ constructor(workspacePath = "./workspace") {
2016
+ super();
2017
+ this.team = /* @__PURE__ */ new Map();
2018
+ this.reviews = /* @__PURE__ */ new Map();
2019
+ this.techDebt = [];
2020
+ this.builds = [];
2021
+ this.tests = [];
2022
+ this.workspacePath = workspacePath;
2023
+ console.log("[SoftwareDevelopmentLeadPersona] Persona initialized");
2024
+ }
2025
+ // ─── Team Management ──────────────────────────────────────────────────────
2026
+ addTeamMember(name, role, skills, capacity = 40) {
2027
+ const member = {
2028
+ id: randomUUID4(),
2029
+ name,
2030
+ role,
2031
+ skills,
2032
+ capacity,
2033
+ currentTasks: [],
2034
+ performance: {
2035
+ velocity: 1,
2036
+ quality: 1,
2037
+ collaboration: 1
2038
+ },
2039
+ joinedAt: (/* @__PURE__ */ new Date()).toISOString()
2040
+ };
2041
+ this.team.set(member.id, member);
2042
+ this.emit("team:memberAdded", { memberId: member.id, name });
2043
+ console.log(`[SoftwareDevelopmentLeadPersona] Team member added: ${name} (${role})`);
2044
+ return member;
2045
+ }
2046
+ assignTask(memberId, taskData) {
2047
+ const member = this.team.get(memberId);
2048
+ if (!member) {
2049
+ throw new Error(`Team member '${memberId}' not found`);
2050
+ }
2051
+ const currentLoad = member.currentTasks.reduce((sum, t) => sum + t.estimatedHours, 0);
2052
+ if (currentLoad + taskData.estimatedHours > member.capacity) {
2053
+ console.log(`[SoftwareDevelopmentLeadPersona] Warning: ${member.name} may be over capacity (${currentLoad + taskData.estimatedHours}/${member.capacity}h)`);
2054
+ }
2055
+ const task = {
2056
+ ...taskData,
2057
+ id: randomUUID4(),
2058
+ assignedAt: (/* @__PURE__ */ new Date()).toISOString(),
2059
+ status: "assigned"
2060
+ };
2061
+ member.currentTasks.push(task);
2062
+ this.emit("task:assigned", { memberId, taskId: task.id, title: task.title });
2063
+ console.log(`[SoftwareDevelopmentLeadPersona] Task assigned to ${member.name}: ${task.title}`);
2064
+ return task;
2065
+ }
2066
+ // ─── Code Reviews ────────────────────────────────────────────────────────
2067
+ initiateCodeReview(title, description, files, author, reviewer) {
2068
+ const review = {
2069
+ id: randomUUID4(),
2070
+ title,
2071
+ description,
2072
+ files,
2073
+ reviewer,
2074
+ author,
2075
+ status: "pending",
2076
+ comments: [],
2077
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
2078
+ };
2079
+ this.reviews.set(review.id, review);
2080
+ this.emit("review:created", { reviewId: review.id, title });
2081
+ console.log(`[SoftwareDevelopmentLeadPersona] Code review initiated: ${title}`);
2082
+ return review;
2083
+ }
2084
+ addReviewComment(reviewId, author, content, options = {}) {
2085
+ const review = this.reviews.get(reviewId);
2086
+ if (!review) {
2087
+ throw new Error(`Code review '${reviewId}' not found`);
2088
+ }
2089
+ const comment = {
2090
+ id: randomUUID4(),
2091
+ author,
2092
+ content,
2093
+ line: options.line,
2094
+ file: options.file,
2095
+ type: options.type || "comment",
2096
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
2097
+ };
2098
+ review.comments.push(comment);
2099
+ if (review.status === "pending") {
2100
+ review.status = "in-review";
2101
+ }
2102
+ this.emit("review:commented", { reviewId, commentId: comment.id, author });
2103
+ console.log(`[SoftwareDevelopmentLeadPersona] Review comment added by ${author} on ${review.title}`);
2104
+ return comment;
2105
+ }
2106
+ approveCodeReview(reviewId, approver) {
2107
+ const review = this.reviews.get(reviewId);
2108
+ if (!review) {
2109
+ throw new Error(`Code review '${reviewId}' not found`);
2110
+ }
2111
+ review.status = "approved";
2112
+ review.approvedAt = (/* @__PURE__ */ new Date()).toISOString();
2113
+ review.approver = approver;
2114
+ this.emit("review:approved", { reviewId, approver });
2115
+ console.log(`[SoftwareDevelopmentLeadPersona] Code review approved: ${review.title} by ${approver}`);
2116
+ return review;
2117
+ }
2118
+ // ─── Technical Debt ───────────────────────────────────────────────────────
2119
+ identifyTechnicalDebt(title, description, category, severity, estimatedEffort, impact, options = {}) {
2120
+ const item = {
2121
+ id: randomUUID4(),
2122
+ title,
2123
+ description,
2124
+ category,
2125
+ severity,
2126
+ estimatedEffort,
2127
+ impact,
2128
+ file: options.file,
2129
+ line: options.line,
2130
+ identifiedAt: (/* @__PURE__ */ new Date()).toISOString(),
2131
+ status: "identified"
2132
+ };
2133
+ this.techDebt.push(item);
2134
+ this.emit("techDebt:identified", { itemId: item.id, title, severity });
2135
+ console.log(`[SoftwareDevelopmentLeadPersona] Tech debt identified: ${title} (${severity})`);
2136
+ return item;
2137
+ }
2138
+ prioritizeTechnicalDebt(criteria = "severity") {
2139
+ const severityOrder = {
2140
+ critical: 0,
2141
+ high: 1,
2142
+ medium: 2,
2143
+ low: 3
2144
+ };
2145
+ switch (criteria) {
2146
+ case "severity":
2147
+ this.techDebt.sort((a, b) => {
2148
+ const aOrder = severityOrder[a.severity] ?? 4;
2149
+ const bOrder = severityOrder[b.severity] ?? 4;
2150
+ return aOrder - bOrder;
2151
+ });
2152
+ break;
2153
+ case "effort":
2154
+ this.techDebt.sort((a, b) => a.estimatedEffort - b.estimatedEffort);
2155
+ break;
2156
+ case "impact": {
2157
+ const impactOrder = { critical: 0, high: 1, medium: 2, low: 3 };
2158
+ this.techDebt.sort((a, b) => {
2159
+ const aOrder = impactOrder[a.impact] ?? 4;
2160
+ const bOrder = impactOrder[b.impact] ?? 4;
2161
+ return aOrder - bOrder;
2162
+ });
2163
+ break;
2164
+ }
2165
+ case "category":
2166
+ this.techDebt.sort((a, b) => a.category.localeCompare(b.category));
2167
+ break;
2168
+ default:
2169
+ this.techDebt.sort((a, b) => {
2170
+ const aOrder = severityOrder[a.severity] ?? 4;
2171
+ const bOrder = severityOrder[b.severity] ?? 4;
2172
+ return aOrder - bOrder;
2173
+ });
2174
+ }
2175
+ this.emit("techDebt:prioritized", { criteria, itemCount: this.techDebt.length });
2176
+ console.log(`[SoftwareDevelopmentLeadPersona] Tech debt prioritized by ${criteria}: ${this.techDebt.length} items`);
2177
+ return [...this.techDebt];
2178
+ }
2179
+ // ─── Codebase Analysis ────────────────────────────────────────────────────
2180
+ async analyzeCodebase(directory) {
2181
+ console.log(`[SoftwareDevelopmentLeadPersona] Analyzing codebase: ${directory}`);
2182
+ const filesByType = await this.countFilesByType(directory);
2183
+ const filesByExtension = await this.countFilesByExtension(directory);
2184
+ const totalFiles = Object.values(filesByExtension).reduce((sum, count) => sum + count, 0);
2185
+ const codeQualityScore = this.calculateCodeQualityScore();
2186
+ const techDebtCount = this.techDebt.filter((item) => item.status !== "resolved").length;
2187
+ const analysis = {
2188
+ totalFiles,
2189
+ filesByType,
2190
+ filesByExtension,
2191
+ codeQualityScore,
2192
+ techDebtItems: techDebtCount,
2193
+ analyzedAt: (/* @__PURE__ */ new Date()).toISOString()
2194
+ };
2195
+ this.emit("codebase:analyzed", { directory, totalFiles, codeQualityScore });
2196
+ console.log(`[SoftwareDevelopmentLeadPersona] Codebase analysis complete: ${totalFiles} files, quality score: ${codeQualityScore}`);
2197
+ return analysis;
2198
+ }
2199
+ async countFilesByType(directory) {
2200
+ const filesByType = {
2201
+ source: 0,
2202
+ test: 0,
2203
+ config: 0,
2204
+ documentation: 0,
2205
+ asset: 0,
2206
+ other: 0
2207
+ };
2208
+ try {
2209
+ const { stdout } = await execAsync(`find "${directory}" -type f -not -path "*/node_modules/*" -not -path "*/.git/*" 2>/dev/null | head -5000`);
2210
+ const files = stdout.trim().split("\n").filter(Boolean);
2211
+ for (const file of files) {
2212
+ const lower = file.toLowerCase();
2213
+ if (lower.match(/\.(test|spec)\.(ts|js|tsx|jsx)$/)) {
2214
+ filesByType["test"]++;
2215
+ } else if (lower.match(/\.(ts|js|tsx|jsx|py|rb|go|rs|java|c|cpp|h)$/)) {
2216
+ filesByType["source"]++;
2217
+ } else if (lower.match(/\.(json|yaml|yml|toml|ini|env|conf|cfg)$/)) {
2218
+ filesByType["config"]++;
2219
+ } else if (lower.match(/\.(md|txt|rst|doc|docx|pdf)$/)) {
2220
+ filesByType["documentation"]++;
2221
+ } else if (lower.match(/\.(png|jpg|jpeg|gif|svg|ico|mp4|mp3|woff|ttf)$/)) {
2222
+ filesByType["asset"]++;
2223
+ } else {
2224
+ filesByType["other"]++;
2225
+ }
2226
+ }
2227
+ } catch (error) {
2228
+ const message = error instanceof Error ? error.message : String(error);
2229
+ console.log(`[SoftwareDevelopmentLeadPersona] Error counting files by type: ${message}`);
2230
+ }
2231
+ return filesByType;
2232
+ }
2233
+ async countFilesByExtension(directory) {
2234
+ const filesByExtension = {};
2235
+ try {
2236
+ const { stdout } = await execAsync(`find "${directory}" -type f -not -path "*/node_modules/*" -not -path "*/.git/*" 2>/dev/null | head -5000`);
2237
+ const files = stdout.trim().split("\n").filter(Boolean);
2238
+ for (const file of files) {
2239
+ const parts = file.split(".");
2240
+ const ext = parts.length > 1 ? `.${parts[parts.length - 1]}` : "no-extension";
2241
+ filesByExtension[ext] = (filesByExtension[ext] || 0) + 1;
2242
+ }
2243
+ } catch (error) {
2244
+ const message = error instanceof Error ? error.message : String(error);
2245
+ console.log(`[SoftwareDevelopmentLeadPersona] Error counting files by extension: ${message}`);
2246
+ }
2247
+ return filesByExtension;
2248
+ }
2249
+ async scanCodebase(directory, pattern) {
2250
+ try {
2251
+ const { stdout } = await execAsync(`grep -rl "${pattern}" "${directory}" --include="*.ts" --include="*.js" 2>/dev/null | head -100`);
2252
+ return stdout.trim().split("\n").filter(Boolean);
2253
+ } catch {
2254
+ return [];
2255
+ }
2256
+ }
2257
+ calculateCodeQualityScore() {
2258
+ let score = 100;
2259
+ const unresolvedDebt = this.techDebt.filter((item) => item.status !== "resolved");
2260
+ for (const item of unresolvedDebt) {
2261
+ switch (item.severity) {
2262
+ case "critical":
2263
+ score -= 15;
2264
+ break;
2265
+ case "high":
2266
+ score -= 10;
2267
+ break;
2268
+ case "medium":
2269
+ score -= 5;
2270
+ break;
2271
+ case "low":
2272
+ score -= 2;
2273
+ break;
2274
+ }
2275
+ }
2276
+ const pendingReviews = Array.from(this.reviews.values()).filter(
2277
+ (r) => r.status === "pending" || r.status === "in-review"
2278
+ );
2279
+ score -= pendingReviews.length * 3;
2280
+ return Math.max(0, Math.min(100, Math.round(score)));
2281
+ }
2282
+ // ─── Build & Test ─────────────────────────────────────────────────────────
2283
+ async runBuild(command = "npm run build") {
2284
+ const build = {
2285
+ id: randomUUID4(),
2286
+ status: "running",
2287
+ command,
2288
+ startTime: (/* @__PURE__ */ new Date()).toISOString(),
2289
+ output: "",
2290
+ errors: []
2291
+ };
2292
+ console.log(`[SoftwareDevelopmentLeadPersona] Running build: ${command}`);
2293
+ try {
2294
+ const { stdout, stderr } = await execAsync(command, {
2295
+ cwd: this.workspacePath,
2296
+ timeout: 3e5
2297
+ });
2298
+ build.status = "success";
2299
+ build.output = stdout;
2300
+ if (stderr) {
2301
+ build.errors = stderr.split("\n").filter(Boolean);
2302
+ }
2303
+ } catch (error) {
2304
+ build.status = "failed";
2305
+ if (error instanceof Error) {
2306
+ build.output = error.stdout || "";
2307
+ build.errors = [error.stderr || error.message];
2308
+ } else {
2309
+ build.errors = [String(error)];
2310
+ }
2311
+ }
2312
+ build.endTime = (/* @__PURE__ */ new Date()).toISOString();
2313
+ build.duration = new Date(build.endTime).getTime() - new Date(build.startTime).getTime();
2314
+ this.builds.push(build);
2315
+ this.emit("build:completed", { buildId: build.id, status: build.status });
2316
+ console.log(`[SoftwareDevelopmentLeadPersona] Build ${build.status}: ${command} (${build.duration}ms)`);
2317
+ return build;
2318
+ }
2319
+ async runTests(command = "npm test") {
2320
+ const testResult = {
2321
+ id: randomUUID4(),
2322
+ status: "running",
2323
+ command,
2324
+ startTime: (/* @__PURE__ */ new Date()).toISOString(),
2325
+ passed: 0,
2326
+ failed: 0,
2327
+ skipped: 0,
2328
+ output: ""
2329
+ };
2330
+ console.log(`[SoftwareDevelopmentLeadPersona] Running tests: ${command}`);
2331
+ try {
2332
+ const { stdout, stderr } = await execAsync(command, {
2333
+ cwd: this.workspacePath,
2334
+ timeout: 6e5
2335
+ });
2336
+ testResult.output = stdout + (stderr ? "\n" + stderr : "");
2337
+ testResult.status = "passed";
2338
+ const passedMatch = stdout.match(/(\d+)\s*(passing|passed|pass)/i);
2339
+ const failedMatch = stdout.match(/(\d+)\s*(failing|failed|fail)/i);
2340
+ const skippedMatch = stdout.match(/(\d+)\s*(pending|skipped|skip)/i);
2341
+ testResult.passed = passedMatch ? parseInt(passedMatch[1], 10) : 0;
2342
+ testResult.failed = failedMatch ? parseInt(failedMatch[1], 10) : 0;
2343
+ testResult.skipped = skippedMatch ? parseInt(skippedMatch[1], 10) : 0;
2344
+ if (testResult.failed > 0) {
2345
+ testResult.status = "failed";
2346
+ }
2347
+ } catch (error) {
2348
+ testResult.status = "failed";
2349
+ if (error instanceof Error) {
2350
+ testResult.output = error.stdout || error.message;
2351
+ } else {
2352
+ testResult.output = String(error);
2353
+ }
2354
+ }
2355
+ testResult.endTime = (/* @__PURE__ */ new Date()).toISOString();
2356
+ testResult.duration = new Date(testResult.endTime).getTime() - new Date(testResult.startTime).getTime();
2357
+ this.tests.push(testResult);
2358
+ this.emit("tests:completed", {
2359
+ testId: testResult.id,
2360
+ status: testResult.status,
2361
+ passed: testResult.passed,
2362
+ failed: testResult.failed
2363
+ });
2364
+ console.log(`[SoftwareDevelopmentLeadPersona] Tests ${testResult.status}: ${testResult.passed} passed, ${testResult.failed} failed, ${testResult.skipped} skipped (${testResult.duration}ms)`);
2365
+ return testResult;
2366
+ }
2367
+ // ─── File Utilities ───────────────────────────────────────────────────────
2368
+ async fileExists(filePath) {
2369
+ try {
2370
+ await access(filePath, fsConstants.F_OK);
2371
+ return true;
2372
+ } catch {
2373
+ return false;
2374
+ }
2375
+ }
2376
+ // ─── Workspace Persistence ────────────────────────────────────────────────
2377
+ async loadWorkspaceData() {
2378
+ try {
2379
+ const filePath = `${this.workspacePath}/dev-lead-data.json`;
2380
+ const data = await readFile2(filePath, "utf-8");
2381
+ const parsed = JSON.parse(data);
2382
+ for (const member of parsed.team) {
2383
+ this.team.set(member.id, member);
2384
+ }
2385
+ for (const review of parsed.reviews) {
2386
+ this.reviews.set(review.id, review);
2387
+ }
2388
+ this.techDebt = parsed.techDebt || [];
2389
+ console.log(`[SoftwareDevelopmentLeadPersona] Workspace data loaded: ${this.team.size} members, ${this.reviews.size} reviews, ${this.techDebt.length} debt items`);
2390
+ return parsed;
2391
+ } catch (error) {
2392
+ const message = error instanceof Error ? error.message : String(error);
2393
+ console.log(`[SoftwareDevelopmentLeadPersona] No existing workspace data found: ${message}`);
2394
+ return null;
2395
+ }
2396
+ }
2397
+ async saveWorkspaceData() {
2398
+ try {
2399
+ const data = {
2400
+ team: Array.from(this.team.values()),
2401
+ reviews: Array.from(this.reviews.values()),
2402
+ techDebt: this.techDebt,
2403
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
2404
+ };
2405
+ const filePath = `${this.workspacePath}/dev-lead-data.json`;
2406
+ await writeFile2(filePath, JSON.stringify(data, null, 2), "utf-8");
2407
+ console.log("[SoftwareDevelopmentLeadPersona] Workspace data saved");
2408
+ } catch (error) {
2409
+ const message = error instanceof Error ? error.message : String(error);
2410
+ console.log(`[SoftwareDevelopmentLeadPersona] Failed to save workspace data: ${message}`);
2411
+ }
2412
+ }
2413
+ // ─── Status ───────────────────────────────────────────────────────────────
2414
+ getPersonaStatus() {
2415
+ const activeReviews = Array.from(this.reviews.values()).filter(
2416
+ (r) => r.status === "pending" || r.status === "in-review"
2417
+ );
2418
+ let openTasks = 0;
2419
+ let totalCapacity = 0;
2420
+ let totalQuality = 0;
2421
+ let memberCount = 0;
2422
+ for (const member of this.team.values()) {
2423
+ openTasks += member.currentTasks.filter((t) => t.status !== "completed" && t.status !== "cancelled").length;
2424
+ totalCapacity += member.capacity - member.currentTasks.reduce((sum, t) => sum + t.estimatedHours, 0);
2425
+ totalQuality += member.performance.quality;
2426
+ memberCount++;
2427
+ }
2428
+ const unresolvedDebt = this.techDebt.filter((item) => item.status !== "resolved");
2429
+ return {
2430
+ persona: "Software Development Lead",
2431
+ teamSize: this.team.size,
2432
+ activeReviews: activeReviews.length,
2433
+ techDebtItems: unresolvedDebt.length,
2434
+ openTasks,
2435
+ teamCapacity: Math.max(0, totalCapacity),
2436
+ averageQuality: memberCount > 0 ? Math.round(totalQuality / memberCount * 100) / 100 : 0
2437
+ };
2438
+ }
2439
+ };
2440
+ export {
2441
+ AgileProductManagerPersona,
2442
+ BaselinePersonaEngine,
2443
+ PersonaUISystem,
2444
+ SoftwareDevelopmentLeadPersona
2445
+ };