clavix 4.2.0 → 4.3.2
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/LICENSE +201 -21
- package/README.md +1 -1
- package/dist/cli/commands/deep.js +4 -58
- package/dist/cli/commands/init.js +13 -16
- package/dist/cli/commands/plan.js +2 -2
- package/dist/core/conversation-quality-tracker.d.ts +81 -0
- package/dist/core/conversation-quality-tracker.js +195 -0
- package/dist/core/intelligence/intent-detector.js +3 -0
- package/dist/core/intelligence/pattern-library.d.ts +18 -1
- package/dist/core/intelligence/pattern-library.js +131 -0
- package/dist/core/intelligence/patterns/conversation-summarizer.d.ts +25 -0
- package/dist/core/intelligence/patterns/conversation-summarizer.js +197 -0
- package/dist/core/intelligence/patterns/dependency-identifier.d.ts +21 -0
- package/dist/core/intelligence/patterns/dependency-identifier.js +149 -0
- package/dist/core/intelligence/patterns/implicit-requirement-extractor.d.ts +20 -0
- package/dist/core/intelligence/patterns/implicit-requirement-extractor.js +129 -0
- package/dist/core/intelligence/patterns/requirement-prioritizer.d.ts +22 -0
- package/dist/core/intelligence/patterns/requirement-prioritizer.js +117 -0
- package/dist/core/intelligence/patterns/success-metrics-enforcer.d.ts +22 -0
- package/dist/core/intelligence/patterns/success-metrics-enforcer.js +142 -0
- package/dist/core/intelligence/patterns/topic-coherence-analyzer.d.ts +22 -0
- package/dist/core/intelligence/patterns/topic-coherence-analyzer.js +140 -0
- package/dist/core/intelligence/patterns/user-persona-enricher.d.ts +22 -0
- package/dist/core/intelligence/patterns/user-persona-enricher.js +124 -0
- package/dist/core/intelligence/quality-assessor.js +2 -0
- package/dist/core/intelligence/types.d.ts +7 -2
- package/dist/core/intelligence/universal-optimizer.d.ts +27 -2
- package/dist/core/intelligence/universal-optimizer.js +65 -5
- package/dist/core/task-manager.d.ts +1 -2
- package/dist/core/task-manager.js +21 -26
- package/dist/templates/slash-commands/_canonical/deep.md +37 -69
- package/dist/templates/slash-commands/_canonical/fast.md +1 -0
- package/dist/templates/slash-commands/_components/sections/pattern-visibility.md +26 -2
- package/package.json +3 -3
- package/dist/templates/instructions/README 2.md +0 -311
- package/dist/templates/instructions/core 2/clavix-mode.md +0 -275
- package/dist/templates/instructions/core 2/file-operations.md +0 -330
- package/dist/templates/instructions/core 2/verification.md +0 -377
- package/dist/templates/instructions/troubleshooting 2/jumped-to-implementation.md +0 -234
- package/dist/templates/instructions/troubleshooting 2/mode-confusion.md +0 -402
- package/dist/templates/instructions/troubleshooting 2/skipped-file-creation.md +0 -385
- package/dist/templates/slash-commands/_canonical 2/archive.md +0 -410
- package/dist/templates/slash-commands/_canonical 2/deep.md +0 -512
- package/dist/templates/slash-commands/_canonical 2/execute.md +0 -80
- package/dist/templates/slash-commands/_canonical 2/fast.md +0 -370
- package/dist/templates/slash-commands/_canonical 2/implement.md +0 -364
- package/dist/templates/slash-commands/_canonical 2/plan.md +0 -329
- package/dist/templates/slash-commands/_canonical 2/prd.md +0 -320
- package/dist/templates/slash-commands/_canonical 2/prompts.md +0 -97
- package/dist/templates/slash-commands/_canonical 2/start.md +0 -204
- package/dist/templates/slash-commands/_canonical 2/summarize.md +0 -395
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v4.3.2: Conversation Quality Tracker
|
|
3
|
+
*
|
|
4
|
+
* Implements the "Supportive Companion" UX pattern for conversational mode.
|
|
5
|
+
* Silently tracks quality, provides positive reinforcement, and gentle guidance.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* ConversationQualityTracker - "Supportive Companion" UX
|
|
9
|
+
*
|
|
10
|
+
* Design principles:
|
|
11
|
+
* - Silent tracking during normal flow
|
|
12
|
+
* - Celebrate progress, don't criticize gaps
|
|
13
|
+
* - Gentle nudge only for critical issues (max 1 per session)
|
|
14
|
+
* - Always reassure that Clavix will help
|
|
15
|
+
*/
|
|
16
|
+
export class ConversationQualityTracker {
|
|
17
|
+
topics = new Map();
|
|
18
|
+
messageCount = 0;
|
|
19
|
+
hasNudged = false;
|
|
20
|
+
lastCheckpointAt = 0;
|
|
21
|
+
// Topic detection keywords
|
|
22
|
+
TOPIC_KEYWORDS = {
|
|
23
|
+
features: ['feature', 'functionality', 'should', 'must', 'need', 'want', 'capability'],
|
|
24
|
+
'tech stack': [
|
|
25
|
+
'react',
|
|
26
|
+
'node',
|
|
27
|
+
'typescript',
|
|
28
|
+
'python',
|
|
29
|
+
'database',
|
|
30
|
+
'api',
|
|
31
|
+
'backend',
|
|
32
|
+
'frontend',
|
|
33
|
+
],
|
|
34
|
+
constraints: [
|
|
35
|
+
'constraint',
|
|
36
|
+
'limitation',
|
|
37
|
+
'budget',
|
|
38
|
+
'timeline',
|
|
39
|
+
'deadline',
|
|
40
|
+
'must not',
|
|
41
|
+
'cannot',
|
|
42
|
+
],
|
|
43
|
+
users: ['user', 'customer', 'audience', 'persona', 'who will'],
|
|
44
|
+
goals: ['goal', 'objective', 'purpose', 'why', 'problem', 'solve'],
|
|
45
|
+
scope: ['scope', 'out of scope', 'not include', 'exclude', 'later', 'mvp'],
|
|
46
|
+
success: ['success', 'metric', 'kpi', 'measure', 'criteria'],
|
|
47
|
+
design: ['design', 'ui', 'ux', 'layout', 'interface', 'look'],
|
|
48
|
+
};
|
|
49
|
+
// Critical gaps that warrant a nudge (only if quality < 40%)
|
|
50
|
+
CRITICAL_TOPICS = ['features', 'goals'];
|
|
51
|
+
/**
|
|
52
|
+
* Track a new message (silent analysis)
|
|
53
|
+
*/
|
|
54
|
+
trackMessage(content) {
|
|
55
|
+
this.messageCount++;
|
|
56
|
+
this.analyzeTopics(content);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get positive checkpoint message (call after ~5 messages or on "status")
|
|
60
|
+
* Returns null if not time for a checkpoint
|
|
61
|
+
*/
|
|
62
|
+
getPositiveCheckpoint() {
|
|
63
|
+
// Only show checkpoint every 5 messages
|
|
64
|
+
if (this.messageCount < 5 || this.messageCount - this.lastCheckpointAt < 5) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
this.lastCheckpointAt = this.messageCount;
|
|
68
|
+
const coveredTopics = this.getCoveredTopics();
|
|
69
|
+
if (coveredTopics.length === 0) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
// Format covered topics nicely
|
|
73
|
+
const topicList = coveredTopics.slice(0, 3).join(', ');
|
|
74
|
+
return `📝 Shaping up nicely! Covered: ${topicList}. Continue or /summarize anytime.`;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Check if a gentle nudge is needed (max 1 per session, only for critical gaps)
|
|
78
|
+
*/
|
|
79
|
+
shouldNudge() {
|
|
80
|
+
// Only nudge once per session
|
|
81
|
+
if (this.hasNudged) {
|
|
82
|
+
return { shouldNudge: false };
|
|
83
|
+
}
|
|
84
|
+
// Only nudge after a few messages
|
|
85
|
+
if (this.messageCount < 3) {
|
|
86
|
+
return { shouldNudge: false };
|
|
87
|
+
}
|
|
88
|
+
// Only nudge if quality is low
|
|
89
|
+
const quality = this.calculateQuality();
|
|
90
|
+
if (quality.overallCompleteness >= 40) {
|
|
91
|
+
return { shouldNudge: false };
|
|
92
|
+
}
|
|
93
|
+
// Find critical gap
|
|
94
|
+
const criticalGap = this.findCriticalGap();
|
|
95
|
+
if (!criticalGap) {
|
|
96
|
+
return { shouldNudge: false };
|
|
97
|
+
}
|
|
98
|
+
// Mark that we've nudged
|
|
99
|
+
this.hasNudged = true;
|
|
100
|
+
return {
|
|
101
|
+
shouldNudge: true,
|
|
102
|
+
gap: criticalGap,
|
|
103
|
+
message: `💡 One thought: a note about ${criticalGap} would help. No worries—Clavix will fill gaps when you summarize.`,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Get reassuring end-of-session message
|
|
108
|
+
*/
|
|
109
|
+
getEndMessage() {
|
|
110
|
+
const coveredTopics = this.getCoveredTopics();
|
|
111
|
+
if (coveredTopics.length === 0) {
|
|
112
|
+
return '✨ Session recorded! Clavix Intelligence will help structure your requirements.';
|
|
113
|
+
}
|
|
114
|
+
if (coveredTopics.length >= 3) {
|
|
115
|
+
return '✨ Great session! You covered several key areas. Clavix Intelligence will enhance your summary.';
|
|
116
|
+
}
|
|
117
|
+
return '✨ Great session! Clavix Intelligence will enhance your summary with any missing pieces.';
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Get current quality metrics (for internal use)
|
|
121
|
+
*/
|
|
122
|
+
calculateQuality() {
|
|
123
|
+
const topics = Array.from(this.topics.values());
|
|
124
|
+
// Calculate completeness based on covered topics
|
|
125
|
+
const totalPossibleTopics = Object.keys(this.TOPIC_KEYWORDS).length;
|
|
126
|
+
const coveredCount = topics.filter((t) => t.confidence >= 30).length;
|
|
127
|
+
const overallCompleteness = Math.min(100, Math.round((coveredCount / totalPossibleTopics) * 100));
|
|
128
|
+
// Estimate ambiguity (higher if fewer topics covered with low confidence)
|
|
129
|
+
const avgConfidence = topics.length > 0 ? topics.reduce((sum, t) => sum + t.confidence, 0) / topics.length : 0;
|
|
130
|
+
const ambiguityLevel = Math.max(0, 100 - avgConfidence);
|
|
131
|
+
return {
|
|
132
|
+
topics,
|
|
133
|
+
overallCompleteness,
|
|
134
|
+
ambiguityLevel,
|
|
135
|
+
messageCount: this.messageCount,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get list of covered topics (user-friendly names)
|
|
140
|
+
*/
|
|
141
|
+
getCoveredTopics() {
|
|
142
|
+
return Array.from(this.topics.values())
|
|
143
|
+
.filter((t) => t.confidence >= 30)
|
|
144
|
+
.sort((a, b) => b.confidence - a.confidence)
|
|
145
|
+
.map((t) => t.name);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Find a critical gap to nudge about
|
|
149
|
+
*/
|
|
150
|
+
findCriticalGap() {
|
|
151
|
+
for (const topic of this.CRITICAL_TOPICS) {
|
|
152
|
+
const tracked = this.topics.get(topic);
|
|
153
|
+
if (!tracked || tracked.confidence < 20) {
|
|
154
|
+
return topic;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Analyze message content for topic coverage
|
|
161
|
+
*/
|
|
162
|
+
analyzeTopics(content) {
|
|
163
|
+
const lowerContent = content.toLowerCase();
|
|
164
|
+
for (const [topic, keywords] of Object.entries(this.TOPIC_KEYWORDS)) {
|
|
165
|
+
const matchedKeywords = keywords.filter((kw) => lowerContent.includes(kw));
|
|
166
|
+
if (matchedKeywords.length > 0) {
|
|
167
|
+
const existing = this.topics.get(topic);
|
|
168
|
+
const confidence = Math.min(100, matchedKeywords.length * 25 + (existing?.confidence || 0));
|
|
169
|
+
this.topics.set(topic, {
|
|
170
|
+
name: topic,
|
|
171
|
+
confidence,
|
|
172
|
+
firstMentioned: existing?.firstMentioned || this.messageCount,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Reset tracker for new session
|
|
179
|
+
*/
|
|
180
|
+
reset() {
|
|
181
|
+
this.topics.clear();
|
|
182
|
+
this.messageCount = 0;
|
|
183
|
+
this.hasNudged = false;
|
|
184
|
+
this.lastCheckpointAt = 0;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Get summary for debugging/logging
|
|
188
|
+
*/
|
|
189
|
+
getSummary() {
|
|
190
|
+
const quality = this.calculateQuality();
|
|
191
|
+
const topics = this.getCoveredTopics();
|
|
192
|
+
return `Messages: ${this.messageCount}, Topics: [${topics.join(', ')}], Completeness: ${quality.overallCompleteness}%`;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=conversation-quality-tracker.js.map
|
|
@@ -306,6 +306,8 @@ export class IntentDetector {
|
|
|
306
306
|
migration: this.calculateIntentScore(lowerPrompt, words, 'migration'),
|
|
307
307
|
'security-review': this.calculateIntentScore(lowerPrompt, words, 'security-review'),
|
|
308
308
|
learning: this.calculateIntentScore(lowerPrompt, words, 'learning'),
|
|
309
|
+
// v4.3.2: Conversational mode intent
|
|
310
|
+
summarization: 0, // Summarization is explicit command, not inferred
|
|
309
311
|
};
|
|
310
312
|
// Apply intent priority rules
|
|
311
313
|
const primaryIntent = this.selectPrimaryIntent(scores, lowerPrompt);
|
|
@@ -685,6 +687,7 @@ export class IntentDetector {
|
|
|
685
687
|
migration: this.calculateIntentScore(lowerPrompt, words, 'migration'),
|
|
686
688
|
'security-review': this.calculateIntentScore(lowerPrompt, words, 'security-review'),
|
|
687
689
|
learning: this.calculateIntentScore(lowerPrompt, words, 'learning'),
|
|
690
|
+
summarization: 0, // v4.3.2: Explicit command
|
|
688
691
|
};
|
|
689
692
|
// Get secondary intents (top 2-3 after primary, with score > 10)
|
|
690
693
|
const secondaryIntents = this.getSecondaryIntents(scores, basicAnalysis.primaryIntent);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BasePattern } from './patterns/base-pattern.js';
|
|
2
|
-
import { IntentAnalysis, OptimizationMode } from './types.js';
|
|
2
|
+
import { IntentAnalysis, OptimizationMode, OptimizationPhase } from './types.js';
|
|
3
3
|
export declare class PatternLibrary {
|
|
4
4
|
private patterns;
|
|
5
5
|
constructor();
|
|
@@ -28,6 +28,23 @@ export declare class PatternLibrary {
|
|
|
28
28
|
* Select applicable patterns for the given context
|
|
29
29
|
*/
|
|
30
30
|
selectPatterns(intent: IntentAnalysis, mode: OptimizationMode): BasePattern[];
|
|
31
|
+
/**
|
|
32
|
+
* v4.3.2: Select patterns for specific mode with phase-awareness
|
|
33
|
+
* Maps PRD and conversational modes to appropriate base modes and patterns
|
|
34
|
+
*/
|
|
35
|
+
selectPatternsForMode(mode: OptimizationMode, intent: IntentAnalysis, phase?: OptimizationPhase): BasePattern[];
|
|
36
|
+
/**
|
|
37
|
+
* Map extended modes to base modes for pattern compatibility
|
|
38
|
+
*/
|
|
39
|
+
private mapToBaseMode;
|
|
40
|
+
/**
|
|
41
|
+
* Check if pattern is applicable for PRD phase
|
|
42
|
+
*/
|
|
43
|
+
private isPatternApplicableForPRDPhase;
|
|
44
|
+
/**
|
|
45
|
+
* Check if pattern is applicable for conversational phase
|
|
46
|
+
*/
|
|
47
|
+
private isPatternApplicableForConversationalPhase;
|
|
31
48
|
/**
|
|
32
49
|
* Get all registered patterns
|
|
33
50
|
*/
|
|
@@ -21,6 +21,15 @@ import { SuccessCriteriaEnforcer } from './patterns/success-criteria-enforcer.js
|
|
|
21
21
|
import { ErrorToleranceEnhancer } from './patterns/error-tolerance-enhancer.js';
|
|
22
22
|
import { PrerequisiteIdentifier } from './patterns/prerequisite-identifier.js';
|
|
23
23
|
import { DomainContextEnricher } from './patterns/domain-context-enricher.js';
|
|
24
|
+
// v4.3.2 PRD patterns
|
|
25
|
+
import { RequirementPrioritizer } from './patterns/requirement-prioritizer.js';
|
|
26
|
+
import { UserPersonaEnricher } from './patterns/user-persona-enricher.js';
|
|
27
|
+
import { SuccessMetricsEnforcer } from './patterns/success-metrics-enforcer.js';
|
|
28
|
+
import { DependencyIdentifier } from './patterns/dependency-identifier.js';
|
|
29
|
+
// v4.3.2 Conversational patterns
|
|
30
|
+
import { ConversationSummarizer } from './patterns/conversation-summarizer.js';
|
|
31
|
+
import { TopicCoherenceAnalyzer } from './patterns/topic-coherence-analyzer.js';
|
|
32
|
+
import { ImplicitRequirementExtractor } from './patterns/implicit-requirement-extractor.js';
|
|
24
33
|
export class PatternLibrary {
|
|
25
34
|
patterns = new Map();
|
|
26
35
|
constructor() {
|
|
@@ -51,6 +60,15 @@ export class PatternLibrary {
|
|
|
51
60
|
this.register(new ErrorToleranceEnhancer()); // P5 - Add error handling (deep only)
|
|
52
61
|
this.register(new PrerequisiteIdentifier()); // P6 - Identify prerequisites (deep only)
|
|
53
62
|
this.register(new DomainContextEnricher()); // P5 - Add domain best practices (both modes)
|
|
63
|
+
// v4.3.2 PRD patterns
|
|
64
|
+
this.register(new RequirementPrioritizer()); // P7 - Separate must-have from nice-to-have
|
|
65
|
+
this.register(new UserPersonaEnricher()); // P6 - Add user context and personas
|
|
66
|
+
this.register(new SuccessMetricsEnforcer()); // P7 - Ensure measurable success criteria
|
|
67
|
+
this.register(new DependencyIdentifier()); // P5 - Identify technical/external dependencies
|
|
68
|
+
// v4.3.2 Conversational patterns
|
|
69
|
+
this.register(new ConversationSummarizer()); // P8 - Extract structured requirements
|
|
70
|
+
this.register(new TopicCoherenceAnalyzer()); // P6 - Detect topic shifts
|
|
71
|
+
this.register(new ImplicitRequirementExtractor()); // P7 - Surface implicit requirements
|
|
54
72
|
}
|
|
55
73
|
/**
|
|
56
74
|
* Register a new pattern
|
|
@@ -102,6 +120,119 @@ export class PatternLibrary {
|
|
|
102
120
|
// Sort by priority (highest first)
|
|
103
121
|
return applicablePatterns.sort((a, b) => b.priority - a.priority);
|
|
104
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* v4.3.2: Select patterns for specific mode with phase-awareness
|
|
125
|
+
* Maps PRD and conversational modes to appropriate base modes and patterns
|
|
126
|
+
*/
|
|
127
|
+
selectPatternsForMode(mode, intent, phase) {
|
|
128
|
+
// Map PRD/conversational modes to base modes for pattern selection
|
|
129
|
+
const baseMode = this.mapToBaseMode(mode, phase);
|
|
130
|
+
const applicablePatterns = [];
|
|
131
|
+
for (const pattern of this.patterns.values()) {
|
|
132
|
+
// Check mode compatibility (use mapped base mode)
|
|
133
|
+
if (pattern.mode !== 'both' && pattern.mode !== baseMode) {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
// Check intent compatibility
|
|
137
|
+
if (!pattern.applicableIntents.includes(intent.primaryIntent)) {
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
// Phase-specific filtering for PRD mode
|
|
141
|
+
if (mode === 'prd' && phase) {
|
|
142
|
+
if (!this.isPatternApplicableForPRDPhase(pattern, phase)) {
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Phase-specific filtering for conversational mode
|
|
147
|
+
if (mode === 'conversational' && phase) {
|
|
148
|
+
if (!this.isPatternApplicableForConversationalPhase(pattern, phase)) {
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
applicablePatterns.push(pattern);
|
|
153
|
+
}
|
|
154
|
+
// Sort by priority (highest first)
|
|
155
|
+
return applicablePatterns.sort((a, b) => b.priority - a.priority);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Map extended modes to base modes for pattern compatibility
|
|
159
|
+
*/
|
|
160
|
+
mapToBaseMode(mode, phase) {
|
|
161
|
+
switch (mode) {
|
|
162
|
+
case 'prd':
|
|
163
|
+
// PRD uses deep mode for output generation, fast for validation
|
|
164
|
+
return phase === 'question-validation' ? 'fast' : 'deep';
|
|
165
|
+
case 'conversational':
|
|
166
|
+
// Conversational uses fast mode for tracking, deep for summarization
|
|
167
|
+
return phase === 'summarization' ? 'deep' : 'fast';
|
|
168
|
+
case 'fast':
|
|
169
|
+
case 'deep':
|
|
170
|
+
default:
|
|
171
|
+
return mode;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Check if pattern is applicable for PRD phase
|
|
176
|
+
*/
|
|
177
|
+
isPatternApplicableForPRDPhase(pattern, phase) {
|
|
178
|
+
// Patterns for question validation (lightweight, clarity-focused)
|
|
179
|
+
const questionValidationPatterns = [
|
|
180
|
+
'ambiguity-detector',
|
|
181
|
+
'completeness-validator',
|
|
182
|
+
'objective-clarifier',
|
|
183
|
+
];
|
|
184
|
+
// Patterns for output generation (comprehensive)
|
|
185
|
+
const outputGenerationPatterns = [
|
|
186
|
+
'prd-structure-enforcer',
|
|
187
|
+
'structure-organizer',
|
|
188
|
+
'success-criteria-enforcer',
|
|
189
|
+
'scope-definer',
|
|
190
|
+
'edge-case-identifier',
|
|
191
|
+
'assumption-explicitizer',
|
|
192
|
+
'technical-context-enricher',
|
|
193
|
+
'domain-context-enricher',
|
|
194
|
+
// v4.3.2 PRD patterns will be added here
|
|
195
|
+
'requirement-prioritizer',
|
|
196
|
+
'user-persona-enricher',
|
|
197
|
+
'success-metrics-enforcer',
|
|
198
|
+
'dependency-identifier',
|
|
199
|
+
];
|
|
200
|
+
if (phase === 'question-validation') {
|
|
201
|
+
return questionValidationPatterns.includes(pattern.id);
|
|
202
|
+
}
|
|
203
|
+
if (phase === 'output-generation') {
|
|
204
|
+
return outputGenerationPatterns.includes(pattern.id);
|
|
205
|
+
}
|
|
206
|
+
return true; // Default: allow pattern
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Check if pattern is applicable for conversational phase
|
|
210
|
+
*/
|
|
211
|
+
isPatternApplicableForConversationalPhase(pattern, phase) {
|
|
212
|
+
// Patterns for conversation tracking (minimal, non-intrusive)
|
|
213
|
+
const conversationTrackingPatterns = ['ambiguity-detector', 'completeness-validator'];
|
|
214
|
+
// Patterns for summarization (comprehensive extraction)
|
|
215
|
+
const summarizationPatterns = [
|
|
216
|
+
'structure-organizer',
|
|
217
|
+
'completeness-validator',
|
|
218
|
+
'success-criteria-enforcer',
|
|
219
|
+
'edge-case-identifier',
|
|
220
|
+
'actionability-enhancer',
|
|
221
|
+
'technical-context-enricher',
|
|
222
|
+
'domain-context-enricher',
|
|
223
|
+
// v4.3.2 Conversational patterns will be added here
|
|
224
|
+
'conversation-summarizer',
|
|
225
|
+
'topic-coherence-analyzer',
|
|
226
|
+
'implicit-requirement-extractor',
|
|
227
|
+
];
|
|
228
|
+
if (phase === 'conversation-tracking') {
|
|
229
|
+
return conversationTrackingPatterns.includes(pattern.id);
|
|
230
|
+
}
|
|
231
|
+
if (phase === 'summarization') {
|
|
232
|
+
return summarizationPatterns.includes(pattern.id);
|
|
233
|
+
}
|
|
234
|
+
return true; // Default: allow pattern
|
|
235
|
+
}
|
|
105
236
|
/**
|
|
106
237
|
* Get all registered patterns
|
|
107
238
|
*/
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BasePattern } from './base-pattern.js';
|
|
2
|
+
import { PromptIntent, OptimizationMode, PatternContext, PatternResult } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* v4.3.2 Conversational Pattern: ConversationSummarizer
|
|
5
|
+
*
|
|
6
|
+
* Extracts structured requirements from conversational messages.
|
|
7
|
+
* Organizes free-form discussion into actionable requirements.
|
|
8
|
+
*/
|
|
9
|
+
export declare class ConversationSummarizer extends BasePattern {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
description: string;
|
|
13
|
+
applicableIntents: PromptIntent[];
|
|
14
|
+
mode: OptimizationMode | 'both';
|
|
15
|
+
priority: number;
|
|
16
|
+
apply(prompt: string, _context: PatternContext): PatternResult;
|
|
17
|
+
private isAlreadyStructured;
|
|
18
|
+
private isConversationalContent;
|
|
19
|
+
private extractAndStructure;
|
|
20
|
+
private extractRequirements;
|
|
21
|
+
private extractConstraints;
|
|
22
|
+
private extractGoals;
|
|
23
|
+
private cleanRequirement;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=conversation-summarizer.d.ts.map
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { BasePattern } from './base-pattern.js';
|
|
2
|
+
/**
|
|
3
|
+
* v4.3.2 Conversational Pattern: ConversationSummarizer
|
|
4
|
+
*
|
|
5
|
+
* Extracts structured requirements from conversational messages.
|
|
6
|
+
* Organizes free-form discussion into actionable requirements.
|
|
7
|
+
*/
|
|
8
|
+
export class ConversationSummarizer extends BasePattern {
|
|
9
|
+
id = 'conversation-summarizer';
|
|
10
|
+
name = 'ConversationSummarizer';
|
|
11
|
+
description = 'Extracts structured requirements from messages';
|
|
12
|
+
applicableIntents = ['summarization', 'planning', 'prd-generation'];
|
|
13
|
+
mode = 'deep';
|
|
14
|
+
priority = 8;
|
|
15
|
+
apply(prompt, _context) {
|
|
16
|
+
// Check if content is already well-structured
|
|
17
|
+
if (this.isAlreadyStructured(prompt)) {
|
|
18
|
+
return {
|
|
19
|
+
enhancedPrompt: prompt,
|
|
20
|
+
improvement: {
|
|
21
|
+
dimension: 'structure',
|
|
22
|
+
description: 'Content already well-structured',
|
|
23
|
+
impact: 'low',
|
|
24
|
+
},
|
|
25
|
+
applied: false,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
// Check if this looks like conversational content
|
|
29
|
+
if (!this.isConversationalContent(prompt)) {
|
|
30
|
+
return {
|
|
31
|
+
enhancedPrompt: prompt,
|
|
32
|
+
improvement: {
|
|
33
|
+
dimension: 'structure',
|
|
34
|
+
description: 'Not conversational content',
|
|
35
|
+
impact: 'low',
|
|
36
|
+
},
|
|
37
|
+
applied: false,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
// Extract and structure requirements
|
|
41
|
+
const enhanced = this.extractAndStructure(prompt);
|
|
42
|
+
return {
|
|
43
|
+
enhancedPrompt: enhanced,
|
|
44
|
+
improvement: {
|
|
45
|
+
dimension: 'structure',
|
|
46
|
+
description: 'Extracted structured requirements from conversation',
|
|
47
|
+
impact: 'high',
|
|
48
|
+
},
|
|
49
|
+
applied: true,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
isAlreadyStructured(prompt) {
|
|
53
|
+
// Check for markdown structure
|
|
54
|
+
const structureIndicators = [
|
|
55
|
+
'##',
|
|
56
|
+
'###',
|
|
57
|
+
'**Requirements:**',
|
|
58
|
+
'**Features:**',
|
|
59
|
+
'- [ ]',
|
|
60
|
+
'1.',
|
|
61
|
+
'2.',
|
|
62
|
+
'3.',
|
|
63
|
+
];
|
|
64
|
+
const matches = structureIndicators.filter((indicator) => prompt.includes(indicator));
|
|
65
|
+
return matches.length >= 3;
|
|
66
|
+
}
|
|
67
|
+
isConversationalContent(prompt) {
|
|
68
|
+
// Conversational markers
|
|
69
|
+
const conversationalMarkers = [
|
|
70
|
+
'i want',
|
|
71
|
+
'i need',
|
|
72
|
+
'we need',
|
|
73
|
+
'should be able to',
|
|
74
|
+
'would like',
|
|
75
|
+
'thinking about',
|
|
76
|
+
'maybe we could',
|
|
77
|
+
'what if',
|
|
78
|
+
'how about',
|
|
79
|
+
'let me',
|
|
80
|
+
"let's",
|
|
81
|
+
'also',
|
|
82
|
+
'and then',
|
|
83
|
+
'basically',
|
|
84
|
+
'so basically',
|
|
85
|
+
];
|
|
86
|
+
const lowerPrompt = prompt.toLowerCase();
|
|
87
|
+
const matches = conversationalMarkers.filter((marker) => lowerPrompt.includes(marker));
|
|
88
|
+
// Also check for lack of structure (sentences without bullet points)
|
|
89
|
+
const sentences = this.extractSentences(prompt);
|
|
90
|
+
const hasBulletPoints = prompt.includes('- ') || prompt.includes('* ');
|
|
91
|
+
return matches.length >= 2 || (sentences.length > 3 && !hasBulletPoints);
|
|
92
|
+
}
|
|
93
|
+
extractAndStructure(prompt) {
|
|
94
|
+
const requirements = this.extractRequirements(prompt);
|
|
95
|
+
const constraints = this.extractConstraints(prompt);
|
|
96
|
+
const goals = this.extractGoals(prompt);
|
|
97
|
+
let structured = '### Extracted Requirements\n\n';
|
|
98
|
+
if (goals.length > 0) {
|
|
99
|
+
structured += '**Goals:**\n';
|
|
100
|
+
structured += goals.map((g) => `- ${g}`).join('\n');
|
|
101
|
+
structured += '\n\n';
|
|
102
|
+
}
|
|
103
|
+
if (requirements.length > 0) {
|
|
104
|
+
structured += '**Requirements:**\n';
|
|
105
|
+
structured += requirements.map((r) => `- ${r}`).join('\n');
|
|
106
|
+
structured += '\n\n';
|
|
107
|
+
}
|
|
108
|
+
if (constraints.length > 0) {
|
|
109
|
+
structured += '**Constraints:**\n';
|
|
110
|
+
structured += constraints.map((c) => `- ${c}`).join('\n');
|
|
111
|
+
structured += '\n\n';
|
|
112
|
+
}
|
|
113
|
+
structured += '---\n\n**Original Context:**\n' + prompt;
|
|
114
|
+
return structured;
|
|
115
|
+
}
|
|
116
|
+
extractRequirements(prompt) {
|
|
117
|
+
const requirements = [];
|
|
118
|
+
const sentences = this.extractSentences(prompt);
|
|
119
|
+
const requirementPatterns = [
|
|
120
|
+
/(?:need|want|should|must|require)\s+(?:to\s+)?(.+)/i,
|
|
121
|
+
/(?:should be able to|needs to)\s+(.+)/i,
|
|
122
|
+
/(?:feature|functionality):\s*(.+)/i,
|
|
123
|
+
];
|
|
124
|
+
for (const sentence of sentences) {
|
|
125
|
+
for (const pattern of requirementPatterns) {
|
|
126
|
+
const match = sentence.match(pattern);
|
|
127
|
+
if (match && match[1]) {
|
|
128
|
+
const req = this.cleanRequirement(match[1]);
|
|
129
|
+
if (req && !requirements.includes(req)) {
|
|
130
|
+
requirements.push(req);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return requirements.slice(0, 10); // Max 10 requirements
|
|
136
|
+
}
|
|
137
|
+
extractConstraints(prompt) {
|
|
138
|
+
const constraints = [];
|
|
139
|
+
const lowerPrompt = prompt.toLowerCase();
|
|
140
|
+
const constraintPatterns = [
|
|
141
|
+
/(?:can't|cannot|shouldn't|must not)\s+(.+)/gi,
|
|
142
|
+
/(?:limited to|restricted to|only)\s+(.+)/gi,
|
|
143
|
+
/(?:within|budget|deadline|timeline):\s*(.+)/gi,
|
|
144
|
+
/(?:no more than|at most|maximum)\s+(.+)/gi,
|
|
145
|
+
];
|
|
146
|
+
for (const pattern of constraintPatterns) {
|
|
147
|
+
const matches = prompt.matchAll(pattern);
|
|
148
|
+
for (const match of matches) {
|
|
149
|
+
if (match[1]) {
|
|
150
|
+
const constraint = this.cleanRequirement(match[1]);
|
|
151
|
+
if (constraint && !constraints.includes(constraint)) {
|
|
152
|
+
constraints.push(constraint);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Common constraint keywords
|
|
158
|
+
if (lowerPrompt.includes('performance')) {
|
|
159
|
+
constraints.push('Performance requirements to be defined');
|
|
160
|
+
}
|
|
161
|
+
if (lowerPrompt.includes('security')) {
|
|
162
|
+
constraints.push('Security requirements to be defined');
|
|
163
|
+
}
|
|
164
|
+
if (lowerPrompt.includes('mobile') && lowerPrompt.includes('desktop')) {
|
|
165
|
+
constraints.push('Must work on both mobile and desktop');
|
|
166
|
+
}
|
|
167
|
+
return constraints.slice(0, 5); // Max 5 constraints
|
|
168
|
+
}
|
|
169
|
+
extractGoals(prompt) {
|
|
170
|
+
const goals = [];
|
|
171
|
+
const goalPatterns = [
|
|
172
|
+
/(?:goal is to|aim to|objective is to)\s+(.+)/gi,
|
|
173
|
+
/(?:trying to|looking to|hoping to)\s+(.+)/gi,
|
|
174
|
+
/(?:so that|in order to)\s+(.+)/gi,
|
|
175
|
+
];
|
|
176
|
+
for (const pattern of goalPatterns) {
|
|
177
|
+
const matches = prompt.matchAll(pattern);
|
|
178
|
+
for (const match of matches) {
|
|
179
|
+
if (match[1]) {
|
|
180
|
+
const goal = this.cleanRequirement(match[1]);
|
|
181
|
+
if (goal && !goals.includes(goal)) {
|
|
182
|
+
goals.push(goal);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return goals.slice(0, 3); // Max 3 goals
|
|
188
|
+
}
|
|
189
|
+
cleanRequirement(text) {
|
|
190
|
+
return text
|
|
191
|
+
.trim()
|
|
192
|
+
.replace(/[.!?,;:]+$/, '')
|
|
193
|
+
.replace(/\s+/g, ' ')
|
|
194
|
+
.substring(0, 200);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=conversation-summarizer.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BasePattern } from './base-pattern.js';
|
|
2
|
+
import { PromptIntent, OptimizationMode, PatternContext, PatternResult } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* v4.3.2 PRD Pattern: DependencyIdentifier
|
|
5
|
+
*
|
|
6
|
+
* Identifies technical and external dependencies in PRD content.
|
|
7
|
+
* Helps surface hidden requirements and blockers.
|
|
8
|
+
*/
|
|
9
|
+
export declare class DependencyIdentifier extends BasePattern {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
description: string;
|
|
13
|
+
applicableIntents: PromptIntent[];
|
|
14
|
+
mode: OptimizationMode | 'both';
|
|
15
|
+
priority: number;
|
|
16
|
+
apply(prompt: string, _context: PatternContext): PatternResult;
|
|
17
|
+
private hasDependencySection;
|
|
18
|
+
private identifyDependencies;
|
|
19
|
+
private addDependencySection;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=dependency-identifier.d.ts.map
|