cmp-standards 2.7.0 → 2.8.0-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/README.md +633 -633
  2. package/dist/cache/EmbeddingCache.d.ts +109 -0
  3. package/dist/cache/EmbeddingCache.d.ts.map +1 -0
  4. package/dist/cache/EmbeddingCache.js +239 -0
  5. package/dist/cache/EmbeddingCache.js.map +1 -0
  6. package/dist/cache/index.d.ts +6 -0
  7. package/dist/cache/index.d.ts.map +1 -0
  8. package/dist/cache/index.js +6 -0
  9. package/dist/cache/index.js.map +1 -0
  10. package/dist/cli/index.js +0 -0
  11. package/dist/db/turso-client.js +11 -11
  12. package/dist/eslint/rules/no-async-useeffect.js +6 -6
  13. package/dist/events/EventBus.d.ts +87 -0
  14. package/dist/events/EventBus.d.ts.map +1 -0
  15. package/dist/events/EventBus.js +200 -0
  16. package/dist/events/EventBus.js.map +1 -0
  17. package/dist/events/index.d.ts +7 -0
  18. package/dist/events/index.d.ts.map +1 -0
  19. package/dist/events/index.js +9 -0
  20. package/dist/events/index.js.map +1 -0
  21. package/dist/events/types.d.ts +989 -0
  22. package/dist/events/types.d.ts.map +1 -0
  23. package/dist/events/types.js +136 -0
  24. package/dist/events/types.js.map +1 -0
  25. package/dist/experts/ConsensusEngine.d.ts +57 -0
  26. package/dist/experts/ConsensusEngine.d.ts.map +1 -0
  27. package/dist/experts/ConsensusEngine.js +146 -0
  28. package/dist/experts/ConsensusEngine.js.map +1 -0
  29. package/dist/experts/ExpertPanelService.d.ts +84 -0
  30. package/dist/experts/ExpertPanelService.d.ts.map +1 -0
  31. package/dist/experts/ExpertPanelService.js +204 -0
  32. package/dist/experts/ExpertPanelService.js.map +1 -0
  33. package/dist/experts/ExpertRouter.d.ts +68 -0
  34. package/dist/experts/ExpertRouter.d.ts.map +1 -0
  35. package/dist/experts/ExpertRouter.js +374 -0
  36. package/dist/experts/ExpertRouter.js.map +1 -0
  37. package/dist/experts/VoteCollector.d.ts +58 -0
  38. package/dist/experts/VoteCollector.d.ts.map +1 -0
  39. package/dist/experts/VoteCollector.js +146 -0
  40. package/dist/experts/VoteCollector.js.map +1 -0
  41. package/dist/experts/index.d.ts +9 -0
  42. package/dist/experts/index.d.ts.map +1 -0
  43. package/dist/experts/index.js +13 -0
  44. package/dist/experts/index.js.map +1 -0
  45. package/dist/hooks/cloud-pre-tool-use.js +20 -20
  46. package/dist/hooks/expert-review.d.ts +74 -0
  47. package/dist/hooks/expert-review.d.ts.map +1 -0
  48. package/dist/hooks/expert-review.js +220 -0
  49. package/dist/hooks/expert-review.js.map +1 -0
  50. package/dist/hooks/index.d.ts +1 -0
  51. package/dist/hooks/index.d.ts.map +1 -1
  52. package/dist/hooks/index.js +2 -0
  53. package/dist/hooks/index.js.map +1 -1
  54. package/dist/index.d.ts +13 -0
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +22 -0
  57. package/dist/index.js.map +1 -1
  58. package/dist/performance/Debouncer.d.ts +91 -0
  59. package/dist/performance/Debouncer.d.ts.map +1 -0
  60. package/dist/performance/Debouncer.js +198 -0
  61. package/dist/performance/Debouncer.js.map +1 -0
  62. package/dist/performance/MemoryDecay.d.ts +82 -0
  63. package/dist/performance/MemoryDecay.d.ts.map +1 -0
  64. package/dist/performance/MemoryDecay.js +153 -0
  65. package/dist/performance/MemoryDecay.js.map +1 -0
  66. package/dist/performance/index.d.ts +7 -0
  67. package/dist/performance/index.d.ts.map +1 -0
  68. package/dist/performance/index.js +9 -0
  69. package/dist/performance/index.js.map +1 -0
  70. package/dist/schema/expert-types.d.ts +395 -0
  71. package/dist/schema/expert-types.d.ts.map +1 -0
  72. package/dist/schema/expert-types.js +250 -0
  73. package/dist/schema/expert-types.js.map +1 -0
  74. package/dist/services/ContextGenerator.js +7 -7
  75. package/dist/services/ProjectScaffold.js +76 -76
  76. package/dist/services/memory-router.js +35 -35
  77. package/dist/services/pattern-tracker.js +90 -90
  78. package/dist/services/semantic-search.js +2 -2
  79. package/package.json +105 -104
  80. package/standards/README.md +50 -50
  81. package/standards/experts/expert-routing.md +215 -215
  82. package/standards/general/code-quality.md +86 -86
  83. package/standards/general/memory-usage.md +205 -205
  84. package/standards/general/sync-workflow.md +235 -235
  85. package/standards/general/workflow.md +82 -82
  86. package/standards/hooks/mandatory-tracking.md +446 -446
  87. package/standards/infrastructure/cloud-database.md +287 -287
  88. package/standards/mcp/server-design.md +243 -243
  89. package/standards/mcp/tool-patterns.md +354 -354
  90. package/standards/skills/skill-structure.md +286 -286
  91. package/standards/skills/workflow-design.md +323 -323
  92. package/standards/tools/tool-design.md +297 -297
  93. package/templates/agents/architecture-expert.md +61 -61
  94. package/templates/agents/database-expert.md +62 -62
  95. package/templates/agents/documentation-expert.md +57 -57
  96. package/templates/agents/memory-expert.md +88 -88
  97. package/templates/agents/performance-expert.md +61 -61
  98. package/templates/agents/security-expert.md +59 -59
  99. package/templates/agents/ux-expert.md +63 -63
  100. package/templates/agents/worker.md +75 -75
  101. package/templates/ai-skills/SKILL_TEMPLATE.md +55 -55
  102. package/templates/claude-settings.json +72 -72
  103. package/templates/commands/experts.md +138 -138
  104. package/templates/hooks/README.md +158 -158
  105. package/templates/hooks/project.config.json.template +77 -77
  106. package/templates/hooks/settings.local.json.template +57 -57
  107. package/templates/memory-config.json +56 -56
  108. package/templates/memory-config.schema.json +212 -212
  109. package/templates/settings.json +58 -58
  110. package/templates/skills/continue.md +205 -205
  111. package/templates/workflows/business-improvement.md +264 -264
  112. package/templates/workflows/expert-review.md +153 -153
  113. package/templates/workflows/internal-app.md +245 -245
  114. package/templates/workflows/sync-docs.md +187 -187
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/events/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * @file Event Type Definitions for cmp-standards v2.8
3
+ * @description Type-safe event system for expert panel orchestration
4
+ */
5
+ import { z } from 'zod';
6
+ // =============================================================================
7
+ // Event Base Schema
8
+ // =============================================================================
9
+ export const EventMetadataSchema = z.object({
10
+ eventId: z.string(),
11
+ timestamp: z.string(),
12
+ source: z.string(),
13
+ correlationId: z.string().optional(),
14
+ });
15
+ // =============================================================================
16
+ // Task Events
17
+ // =============================================================================
18
+ export const TaskNeedsReviewEventSchema = z.object({
19
+ type: z.literal('task.needs_review'),
20
+ taskId: z.string(),
21
+ files: z.array(z.string()),
22
+ criticality: z.enum(['critical', 'normal']),
23
+ domain: z.string().optional(),
24
+ metadata: EventMetadataSchema,
25
+ });
26
+ export const TaskReviewedEventSchema = z.object({
27
+ type: z.literal('task.reviewed'),
28
+ taskId: z.string(),
29
+ decision: z.enum(['APPROVED', 'REJECTED', 'NEEDS_REVIEW']),
30
+ metadata: EventMetadataSchema,
31
+ });
32
+ export const TaskCompletedEventSchema = z.object({
33
+ type: z.literal('task.completed'),
34
+ taskId: z.string(),
35
+ result: z.enum(['success', 'partial', 'failed']),
36
+ metadata: EventMetadataSchema,
37
+ });
38
+ // =============================================================================
39
+ // Expert Events
40
+ // =============================================================================
41
+ export const ExpertVoteSubmittedEventSchema = z.object({
42
+ type: z.literal('expert.vote_submitted'),
43
+ expertId: z.string(),
44
+ taskId: z.string(),
45
+ vote: z.enum(['APPROVE', 'REJECT', 'WARN', 'ABSTAIN']),
46
+ confidence: z.number().min(0).max(1),
47
+ issues: z.array(z.object({
48
+ severity: z.enum(['critical', 'high', 'medium', 'low']),
49
+ message: z.string(),
50
+ file: z.string().optional(),
51
+ line: z.number().optional(),
52
+ })),
53
+ reasoning: z.string().optional(),
54
+ metadata: EventMetadataSchema,
55
+ });
56
+ export const ExpertRecommendationEventSchema = z.object({
57
+ type: z.literal('expert.recommendation'),
58
+ expertId: z.string(),
59
+ taskId: z.string(),
60
+ recommendation: z.object({
61
+ title: z.string(),
62
+ description: z.string(),
63
+ priority: z.enum(['critical', 'high', 'medium', 'low']),
64
+ effort: z.enum(['trivial', 'small', 'medium', 'large']),
65
+ }),
66
+ metadata: EventMetadataSchema,
67
+ });
68
+ // =============================================================================
69
+ // Consensus Events
70
+ // =============================================================================
71
+ export const ConsensusReachedEventSchema = z.object({
72
+ type: z.literal('consensus.reached'),
73
+ taskId: z.string(),
74
+ decision: z.enum(['APPROVED', 'REJECTED', 'NEEDS_REVIEW']),
75
+ threshold: z.enum(['UNANIMITY', 'MAJORITY']),
76
+ votes: z.object({
77
+ approve: z.number(),
78
+ reject: z.number(),
79
+ abstain: z.number(),
80
+ }),
81
+ metadata: EventMetadataSchema,
82
+ });
83
+ // =============================================================================
84
+ // Pattern Events
85
+ // =============================================================================
86
+ export const PatternDetectedEventSchema = z.object({
87
+ type: z.literal('pattern.detected'),
88
+ patternId: z.string(),
89
+ occurrences: z.number(),
90
+ files: z.array(z.string()),
91
+ severity: z.enum(['critical', 'high', 'medium', 'low']),
92
+ autoImprove: z.boolean(),
93
+ metadata: EventMetadataSchema,
94
+ });
95
+ // =============================================================================
96
+ // Memory Events
97
+ // =============================================================================
98
+ export const MemoryCreatedEventSchema = z.object({
99
+ type: z.literal('memory.created'),
100
+ memoryId: z.string(),
101
+ domain: z.string(),
102
+ title: z.string(),
103
+ metadata: EventMetadataSchema,
104
+ });
105
+ export const MemoryAccessedEventSchema = z.object({
106
+ type: z.literal('memory.accessed'),
107
+ memoryId: z.string(),
108
+ context: z.string().optional(),
109
+ metadata: EventMetadataSchema,
110
+ });
111
+ // =============================================================================
112
+ // Union Types
113
+ // =============================================================================
114
+ export const EventSchema = z.discriminatedUnion('type', [
115
+ TaskNeedsReviewEventSchema,
116
+ TaskReviewedEventSchema,
117
+ TaskCompletedEventSchema,
118
+ ExpertVoteSubmittedEventSchema,
119
+ ExpertRecommendationEventSchema,
120
+ ConsensusReachedEventSchema,
121
+ PatternDetectedEventSchema,
122
+ MemoryCreatedEventSchema,
123
+ MemoryAccessedEventSchema,
124
+ ]);
125
+ // =============================================================================
126
+ // Event Factory Helpers
127
+ // =============================================================================
128
+ export function createEventMetadata(source, correlationId) {
129
+ return {
130
+ eventId: `evt_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
131
+ timestamp: new Date().toISOString(),
132
+ source,
133
+ correlationId,
134
+ };
135
+ }
136
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/events/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @file ConsensusEngine - Voting logic for expert panel
3
+ * @description Calculates consensus from expert votes with configurable thresholds
4
+ */
5
+ import { z } from 'zod';
6
+ import { ExpertVote, ConsensusDecisionSchema, ConsensusThresholdSchema } from '../schema/expert-types.js';
7
+ export type ConsensusDecision = z.infer<typeof ConsensusDecisionSchema>;
8
+ export type ConsensusThreshold = z.infer<typeof ConsensusThresholdSchema>;
9
+ export interface VoteRecord {
10
+ expertId: string;
11
+ vote: ExpertVote;
12
+ confidence: number;
13
+ decisionId?: string;
14
+ }
15
+ export interface ConsensusInput {
16
+ taskId: string;
17
+ votes: VoteRecord[];
18
+ threshold: ConsensusThreshold;
19
+ startTime: number;
20
+ }
21
+ export interface ConsensusResult {
22
+ decision: ConsensusDecision;
23
+ threshold: ConsensusThreshold;
24
+ metThreshold: boolean;
25
+ votes: {
26
+ approve: number;
27
+ reject: number;
28
+ warn: number;
29
+ abstain: number;
30
+ };
31
+ avgConfidence: number;
32
+ expertDecisionIds: string[];
33
+ panelDurationMs: number;
34
+ }
35
+ export declare class ConsensusEngine {
36
+ /**
37
+ * Calculate consensus from votes
38
+ */
39
+ calculate(input: ConsensusInput): ConsensusResult;
40
+ /**
41
+ * Determine the final decision based on vote counts and threshold
42
+ */
43
+ private determineDecision;
44
+ /**
45
+ * Check if a single vote would change the outcome
46
+ */
47
+ wouldChangeOutcome(currentResult: ConsensusResult, newVote: ExpertVote): boolean;
48
+ /**
49
+ * Get votes needed to change outcome
50
+ */
51
+ votesNeededToChange(currentResult: ConsensusResult): {
52
+ forApproval: number;
53
+ forRejection: number;
54
+ };
55
+ }
56
+ export declare function getConsensusEngine(): ConsensusEngine;
57
+ //# sourceMappingURL=ConsensusEngine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConsensusEngine.d.ts","sourceRoot":"","sources":["../../src/experts/ConsensusEngine.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EACL,UAAU,EACV,uBAAuB,EACvB,wBAAwB,EAEzB,MAAM,2BAA2B,CAAA;AAMlC,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AACvE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AAEzE,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,UAAU,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,UAAU,EAAE,CAAA;IACnB,SAAS,EAAE,kBAAkB,CAAA;IAC7B,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,SAAS,EAAE,kBAAkB,CAAA;IAC7B,YAAY,EAAE,OAAO,CAAA;IACrB,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAA;QACf,MAAM,EAAE,MAAM,CAAA;QACd,IAAI,EAAE,MAAM,CAAA;QACZ,OAAO,EAAE,MAAM,CAAA;KAChB,CAAA;IACD,aAAa,EAAE,MAAM,CAAA;IACrB,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,eAAe,EAAE,MAAM,CAAA;CACxB;AAMD,qBAAa,eAAe;IAC1B;;OAEG;IACH,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,eAAe;IA4DjD;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAqCzB;;OAEG;IACH,kBAAkB,CAChB,aAAa,EAAE,eAAe,EAC9B,OAAO,EAAE,UAAU,GAClB,OAAO;IA+BV;;OAEG;IACH,mBAAmB,CAAC,aAAa,EAAE,eAAe,GAAG;QACnD,WAAW,EAAE,MAAM,CAAA;QACnB,YAAY,EAAE,MAAM,CAAA;KACrB;CAoBF;AAQD,wBAAgB,kBAAkB,IAAI,eAAe,CAKpD"}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * @file ConsensusEngine - Voting logic for expert panel
3
+ * @description Calculates consensus from expert votes with configurable thresholds
4
+ */
5
+ // =============================================================================
6
+ // ConsensusEngine Implementation
7
+ // =============================================================================
8
+ export class ConsensusEngine {
9
+ /**
10
+ * Calculate consensus from votes
11
+ */
12
+ calculate(input) {
13
+ const { taskId, votes, threshold, startTime } = input;
14
+ // Count votes
15
+ const counts = {
16
+ approve: 0,
17
+ reject: 0,
18
+ warn: 0,
19
+ abstain: 0,
20
+ };
21
+ let totalConfidence = 0;
22
+ const decisionIds = [];
23
+ for (const vote of votes) {
24
+ switch (vote.vote) {
25
+ case 'APPROVE':
26
+ counts.approve++;
27
+ break;
28
+ case 'REJECT':
29
+ counts.reject++;
30
+ break;
31
+ case 'WARN':
32
+ counts.warn++;
33
+ break;
34
+ case 'ABSTAIN':
35
+ counts.abstain++;
36
+ break;
37
+ }
38
+ totalConfidence += vote.confidence;
39
+ if (vote.decisionId) {
40
+ decisionIds.push(vote.decisionId);
41
+ }
42
+ }
43
+ // Calculate average confidence (excluding abstains)
44
+ const activeVotes = votes.filter(v => v.vote !== 'ABSTAIN');
45
+ const avgConfidence = activeVotes.length > 0
46
+ ? totalConfidence / activeVotes.length
47
+ : 0;
48
+ // Determine decision based on threshold
49
+ const { decision, metThreshold } = this.determineDecision(counts, threshold, activeVotes.length);
50
+ return {
51
+ decision,
52
+ threshold,
53
+ metThreshold,
54
+ votes: counts,
55
+ avgConfidence,
56
+ expertDecisionIds: decisionIds,
57
+ panelDurationMs: Date.now() - startTime,
58
+ };
59
+ }
60
+ /**
61
+ * Determine the final decision based on vote counts and threshold
62
+ */
63
+ determineDecision(counts, threshold, activeVotes) {
64
+ // No active votes = needs review
65
+ if (activeVotes === 0) {
66
+ return { decision: 'NEEDS_REVIEW', metThreshold: false };
67
+ }
68
+ // UNANIMITY: All must approve (no rejects)
69
+ if (threshold === 'UNANIMITY') {
70
+ if (counts.reject > 0) {
71
+ return { decision: 'REJECTED', metThreshold: false };
72
+ }
73
+ if (counts.warn > 0 && counts.approve === 0) {
74
+ return { decision: 'NEEDS_REVIEW', metThreshold: false };
75
+ }
76
+ // All approved or warned (no rejects)
77
+ return { decision: 'APPROVED', metThreshold: true };
78
+ }
79
+ // MAJORITY: More than half must approve
80
+ const majorityThreshold = Math.ceil(activeVotes / 2);
81
+ if (counts.approve >= majorityThreshold) {
82
+ return { decision: 'APPROVED', metThreshold: true };
83
+ }
84
+ if (counts.reject >= majorityThreshold) {
85
+ return { decision: 'REJECTED', metThreshold: true };
86
+ }
87
+ // No clear majority
88
+ return { decision: 'NEEDS_REVIEW', metThreshold: false };
89
+ }
90
+ /**
91
+ * Check if a single vote would change the outcome
92
+ */
93
+ wouldChangeOutcome(currentResult, newVote) {
94
+ // Clone counts
95
+ const newCounts = { ...currentResult.votes };
96
+ // Add new vote
97
+ switch (newVote) {
98
+ case 'APPROVE':
99
+ newCounts.approve++;
100
+ break;
101
+ case 'REJECT':
102
+ newCounts.reject++;
103
+ break;
104
+ case 'WARN':
105
+ newCounts.warn++;
106
+ break;
107
+ case 'ABSTAIN':
108
+ newCounts.abstain++;
109
+ return false; // Abstain never changes outcome
110
+ }
111
+ const activeVotes = newCounts.approve + newCounts.reject + newCounts.warn;
112
+ const { decision } = this.determineDecision(newCounts, currentResult.threshold, activeVotes);
113
+ return decision !== currentResult.decision;
114
+ }
115
+ /**
116
+ * Get votes needed to change outcome
117
+ */
118
+ votesNeededToChange(currentResult) {
119
+ const activeVotes = currentResult.votes.approve +
120
+ currentResult.votes.reject +
121
+ currentResult.votes.warn;
122
+ if (currentResult.threshold === 'UNANIMITY') {
123
+ return {
124
+ forApproval: currentResult.votes.reject > 0 ? Infinity : 0,
125
+ forRejection: 1, // Any reject blocks
126
+ };
127
+ }
128
+ // MAJORITY
129
+ const majorityThreshold = Math.ceil((activeVotes + 1) / 2);
130
+ return {
131
+ forApproval: Math.max(0, majorityThreshold - currentResult.votes.approve),
132
+ forRejection: Math.max(0, majorityThreshold - currentResult.votes.reject),
133
+ };
134
+ }
135
+ }
136
+ // =============================================================================
137
+ // Singleton
138
+ // =============================================================================
139
+ let globalEngine = null;
140
+ export function getConsensusEngine() {
141
+ if (!globalEngine) {
142
+ globalEngine = new ConsensusEngine();
143
+ }
144
+ return globalEngine;
145
+ }
146
+ //# sourceMappingURL=ConsensusEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConsensusEngine.js","sourceRoot":"","sources":["../../src/experts/ConsensusEngine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * @file ExpertPanelService - Full expert panel orchestration
3
+ * @description Coordinates expert routing, vote collection, and consensus
4
+ *
5
+ * Flow:
6
+ * 1. Receive task for review
7
+ * 2. Detect criticality and route to experts
8
+ * 3. Collect votes in parallel
9
+ * 4. Calculate consensus
10
+ * 5. Emit events and return result
11
+ */
12
+ import { RoutingContext, RoutingResult, ExpertId, ExpertSelection } from './ExpertRouter.js';
13
+ import { ConsensusResult, ConsensusThreshold } from './ConsensusEngine.js';
14
+ import { ExpertVoteResult, ExpertVoteProvider } from './VoteCollector.js';
15
+ import { ExpertIssue } from '../schema/expert-types.js';
16
+ export interface PanelRequest {
17
+ taskId: string;
18
+ files: string[];
19
+ content?: string;
20
+ diff?: string;
21
+ domain?: string;
22
+ /** Force specific threshold (overrides auto-detection) */
23
+ forceThreshold?: ConsensusThreshold;
24
+ /** Include only specific experts */
25
+ includeExperts?: ExpertId[];
26
+ /** Exclude specific experts */
27
+ excludeExperts?: ExpertId[];
28
+ }
29
+ export interface PanelResult {
30
+ taskId: string;
31
+ panelId: string;
32
+ routing: RoutingResult;
33
+ votes: ExpertVoteResult[];
34
+ consensus: ConsensusResult;
35
+ allIssues: ExpertIssue[];
36
+ timing: PanelTiming;
37
+ }
38
+ export interface PanelTiming {
39
+ startedAt: string;
40
+ completedAt: string;
41
+ routingMs: number;
42
+ votingMs: number;
43
+ consensusMs: number;
44
+ totalMs: number;
45
+ }
46
+ export interface ExpertPanelConfig {
47
+ /** Timeout per expert vote */
48
+ voteTimeout: number;
49
+ /** Enable debug logging */
50
+ debug: boolean;
51
+ }
52
+ export declare class ExpertPanelService {
53
+ private config;
54
+ private router;
55
+ private collector;
56
+ private consensusEngine;
57
+ private eventBus;
58
+ private voteProvider;
59
+ constructor(config?: Partial<ExpertPanelConfig>);
60
+ /**
61
+ * Set the vote provider (how to get votes from experts)
62
+ * This allows injection of different providers (real API, mock, etc.)
63
+ */
64
+ setVoteProvider(provider: ExpertVoteProvider): void;
65
+ /**
66
+ * Run the full expert panel for a task
67
+ */
68
+ runPanel(request: PanelRequest): Promise<PanelResult>;
69
+ /**
70
+ * Apply include/exclude filters to expert selection
71
+ */
72
+ private applyExpertFilters;
73
+ /**
74
+ * Quick check if a task needs review
75
+ */
76
+ needsReview(files: string[], content?: string): boolean;
77
+ /**
78
+ * Get which experts would review a task (without running the panel)
79
+ */
80
+ previewExperts(context: RoutingContext): ExpertSelection[];
81
+ }
82
+ export declare function getExpertPanelService(config?: Partial<ExpertPanelConfig>): ExpertPanelService;
83
+ export declare function resetExpertPanelService(): void;
84
+ //# sourceMappingURL=ExpertPanelService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpertPanelService.d.ts","sourceRoot":"","sources":["../../src/experts/ExpertPanelService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,EAGL,cAAc,EACd,aAAa,EACb,QAAQ,EACR,eAAe,EAEhB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAGL,eAAe,EACf,kBAAkB,EACnB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAIL,gBAAgB,EAChB,kBAAkB,EAEnB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAOvD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,0DAA0D;IAC1D,cAAc,CAAC,EAAE,kBAAkB,CAAA;IACnC,oCAAoC;IACpC,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAA;IAC3B,+BAA+B;IAC/B,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAA;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,aAAa,CAAA;IACtB,KAAK,EAAE,gBAAgB,EAAE,CAAA;IACzB,SAAS,EAAE,eAAe,CAAA;IAC1B,SAAS,EAAE,WAAW,EAAE,CAAA;IACxB,MAAM,EAAE,WAAW,CAAA;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,8BAA8B;IAC9B,WAAW,EAAE,MAAM,CAAA;IACnB,2BAA2B;IAC3B,KAAK,EAAE,OAAO,CAAA;CACf;AAWD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,SAAS,CAAe;IAChC,OAAO,CAAC,eAAe,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAU;IAC1B,OAAO,CAAC,YAAY,CAAkC;gBAE1C,MAAM,GAAE,OAAO,CAAC,iBAAiB,CAAM;IAQnD;;;OAGG;IACH,eAAe,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI;IAInD;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IAwI3D;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAsB1B;;OAEG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO;IAKvD;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,eAAe,EAAE;CAG3D;AAQD,wBAAgB,qBAAqB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,kBAAkB,CAK7F;AAED,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C"}
@@ -0,0 +1,204 @@
1
+ /**
2
+ * @file ExpertPanelService - Full expert panel orchestration
3
+ * @description Coordinates expert routing, vote collection, and consensus
4
+ *
5
+ * Flow:
6
+ * 1. Receive task for review
7
+ * 2. Detect criticality and route to experts
8
+ * 3. Collect votes in parallel
9
+ * 4. Calculate consensus
10
+ * 5. Emit events and return result
11
+ */
12
+ import { getEventBus } from '../events/EventBus.js';
13
+ import { createEventMetadata } from '../events/types.js';
14
+ import { getExpertRouter, } from './ExpertRouter.js';
15
+ import { getConsensusEngine, } from './ConsensusEngine.js';
16
+ import { getVoteCollector, } from './VoteCollector.js';
17
+ import { ulid } from 'ulid';
18
+ const DEFAULT_CONFIG = {
19
+ voteTimeout: 5000,
20
+ debug: false,
21
+ };
22
+ // =============================================================================
23
+ // ExpertPanelService Implementation
24
+ // =============================================================================
25
+ export class ExpertPanelService {
26
+ config;
27
+ router;
28
+ collector;
29
+ consensusEngine;
30
+ eventBus;
31
+ voteProvider = null;
32
+ constructor(config = {}) {
33
+ this.config = { ...DEFAULT_CONFIG, ...config };
34
+ this.router = getExpertRouter();
35
+ this.collector = getVoteCollector({ voteTimeout: this.config.voteTimeout });
36
+ this.consensusEngine = getConsensusEngine();
37
+ this.eventBus = getEventBus();
38
+ }
39
+ /**
40
+ * Set the vote provider (how to get votes from experts)
41
+ * This allows injection of different providers (real API, mock, etc.)
42
+ */
43
+ setVoteProvider(provider) {
44
+ this.voteProvider = provider;
45
+ }
46
+ /**
47
+ * Run the full expert panel for a task
48
+ */
49
+ async runPanel(request) {
50
+ if (!this.voteProvider) {
51
+ throw new Error('Vote provider not set. Call setVoteProvider() first.');
52
+ }
53
+ const panelId = `panel-${ulid()}`;
54
+ const startTime = Date.now();
55
+ const startedAt = new Date().toISOString();
56
+ if (this.config.debug) {
57
+ console.log(`[ExpertPanel] Starting panel ${panelId} for task ${request.taskId}`);
58
+ }
59
+ // Step 1: Route to experts (do this first to get criticality)
60
+ const routingStart = Date.now();
61
+ const routingContext = {
62
+ files: request.files,
63
+ content: request.content,
64
+ domain: request.domain,
65
+ };
66
+ let routing = this.router.route(routingContext);
67
+ const routingMs = Date.now() - routingStart;
68
+ // Emit task needs review event (now we have criticality)
69
+ await this.eventBus.publish({
70
+ type: 'task.needs_review',
71
+ taskId: request.taskId,
72
+ files: request.files,
73
+ criticality: routing.criticality.level,
74
+ domain: request.domain,
75
+ metadata: createEventMetadata('ExpertPanelService'),
76
+ });
77
+ // Apply expert filters
78
+ routing = this.applyExpertFilters(routing, request);
79
+ // Override threshold if forced
80
+ if (request.forceThreshold) {
81
+ routing = { ...routing, threshold: request.forceThreshold };
82
+ }
83
+ if (this.config.debug) {
84
+ console.log(`[ExpertPanel] Routing complete in ${routingMs}ms`);
85
+ console.log(`[ExpertPanel] Criticality: ${routing.criticality.level}`);
86
+ console.log(`[ExpertPanel] Experts: ${routing.selectedExperts.map(e => e.expertId).join(', ')}`);
87
+ console.log(`[ExpertPanel] Threshold: ${routing.threshold}`);
88
+ }
89
+ // Step 2: Collect votes in parallel
90
+ const votingStart = Date.now();
91
+ const reviewContext = {
92
+ files: request.files,
93
+ content: request.content,
94
+ diff: request.diff,
95
+ domain: request.domain,
96
+ };
97
+ const voteCollection = await this.collector.collectVotes(request.taskId, routing.selectedExperts, reviewContext, this.voteProvider);
98
+ const votingMs = Date.now() - votingStart;
99
+ if (this.config.debug) {
100
+ console.log(`[ExpertPanel] Vote collection complete in ${votingMs}ms`);
101
+ console.log(`[ExpertPanel] Votes: ${voteCollection.completed}/${routing.selectedExperts.length}`);
102
+ }
103
+ // Step 3: Calculate consensus
104
+ const consensusStart = Date.now();
105
+ const voteRecords = this.collector.toVoteRecords(voteCollection.votes);
106
+ const consensus = this.consensusEngine.calculate({
107
+ taskId: request.taskId,
108
+ votes: voteRecords,
109
+ threshold: routing.threshold,
110
+ startTime,
111
+ });
112
+ const consensusMs = Date.now() - consensusStart;
113
+ // Collect all issues
114
+ const allIssues = voteCollection.votes.flatMap(v => v.issues);
115
+ // Build timing info
116
+ const completedAt = new Date().toISOString();
117
+ const totalMs = Date.now() - startTime;
118
+ const timing = {
119
+ startedAt,
120
+ completedAt,
121
+ routingMs,
122
+ votingMs,
123
+ consensusMs,
124
+ totalMs,
125
+ };
126
+ if (this.config.debug) {
127
+ console.log(`[ExpertPanel] Panel complete in ${totalMs}ms`);
128
+ console.log(`[ExpertPanel] Decision: ${consensus.decision}`);
129
+ console.log(`[ExpertPanel] Issues found: ${allIssues.length}`);
130
+ }
131
+ // Emit consensus reached event
132
+ await this.eventBus.publish({
133
+ type: 'consensus.reached',
134
+ taskId: request.taskId,
135
+ decision: consensus.decision,
136
+ threshold: consensus.threshold,
137
+ metThreshold: consensus.metThreshold,
138
+ votes: consensus.votes,
139
+ expertDecisionIds: consensus.expertDecisionIds,
140
+ metadata: createEventMetadata('ExpertPanelService'),
141
+ });
142
+ // Emit task reviewed event
143
+ await this.eventBus.publish({
144
+ type: 'task.reviewed',
145
+ taskId: request.taskId,
146
+ decision: consensus.decision,
147
+ metadata: createEventMetadata('ExpertPanelService'),
148
+ });
149
+ return {
150
+ taskId: request.taskId,
151
+ panelId,
152
+ routing,
153
+ votes: voteCollection.votes,
154
+ consensus,
155
+ allIssues,
156
+ timing,
157
+ };
158
+ }
159
+ /**
160
+ * Apply include/exclude filters to expert selection
161
+ */
162
+ applyExpertFilters(routing, request) {
163
+ let experts = routing.selectedExperts;
164
+ // Include filter
165
+ if (request.includeExperts && request.includeExperts.length > 0) {
166
+ experts = experts.filter(e => request.includeExperts.includes(e.expertId));
167
+ }
168
+ // Exclude filter
169
+ if (request.excludeExperts && request.excludeExperts.length > 0) {
170
+ experts = experts.filter(e => !request.excludeExperts.includes(e.expertId));
171
+ }
172
+ return {
173
+ ...routing,
174
+ selectedExperts: experts,
175
+ };
176
+ }
177
+ /**
178
+ * Quick check if a task needs review
179
+ */
180
+ needsReview(files, content) {
181
+ const routing = this.router.route({ files, content });
182
+ return routing.criticality.level === 'critical' || routing.selectedExperts.length >= 2;
183
+ }
184
+ /**
185
+ * Get which experts would review a task (without running the panel)
186
+ */
187
+ previewExperts(context) {
188
+ return this.router.route(context).selectedExperts;
189
+ }
190
+ }
191
+ // =============================================================================
192
+ // Singleton
193
+ // =============================================================================
194
+ let globalPanel = null;
195
+ export function getExpertPanelService(config) {
196
+ if (!globalPanel) {
197
+ globalPanel = new ExpertPanelService(config);
198
+ }
199
+ return globalPanel;
200
+ }
201
+ export function resetExpertPanelService() {
202
+ globalPanel = null;
203
+ }
204
+ //# sourceMappingURL=ExpertPanelService.js.map