sdd-mcp-server 1.5.1 → 1.6.1

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 (29) hide show
  1. package/README.md +5 -5
  2. package/dist/application/services/AnswerValidator.d.ts +7 -0
  3. package/dist/application/services/AnswerValidator.js +52 -0
  4. package/dist/application/services/AnswerValidator.js.map +1 -0
  5. package/dist/application/services/DescriptionAnalyzer.d.ts +28 -0
  6. package/dist/application/services/DescriptionAnalyzer.js +184 -0
  7. package/dist/application/services/DescriptionAnalyzer.js.map +1 -0
  8. package/dist/application/services/DescriptionEnricher.d.ts +15 -0
  9. package/dist/application/services/DescriptionEnricher.js +77 -0
  10. package/dist/application/services/DescriptionEnricher.js.map +1 -0
  11. package/dist/application/services/QuestionGenerator.d.ts +7 -0
  12. package/dist/application/services/QuestionGenerator.js +30 -0
  13. package/dist/application/services/QuestionGenerator.js.map +1 -0
  14. package/dist/application/services/RequirementsClarificationService.d.ts +22 -51
  15. package/dist/application/services/RequirementsClarificationService.js +44 -419
  16. package/dist/application/services/RequirementsClarificationService.js.map +1 -1
  17. package/dist/application/services/SteeringContextLoader.d.ts +11 -0
  18. package/dist/application/services/SteeringContextLoader.js +90 -0
  19. package/dist/application/services/SteeringContextLoader.js.map +1 -0
  20. package/dist/application/services/clarification-questions.d.ts +15 -0
  21. package/dist/application/services/clarification-questions.js +99 -0
  22. package/dist/application/services/clarification-questions.js.map +1 -0
  23. package/dist/domain/types.d.ts +17 -0
  24. package/dist/infrastructure/di/container.js +18 -0
  25. package/dist/infrastructure/di/container.js.map +1 -1
  26. package/dist/infrastructure/di/types.d.ts +5 -0
  27. package/dist/infrastructure/di/types.js +5 -0
  28. package/dist/infrastructure/di/types.js.map +1 -1
  29. package/package.json +1 -1
package/README.md CHANGED
@@ -6,11 +6,11 @@
6
6
 
7
7
  A Model Context Protocol (MCP) server implementing Spec-Driven Development (SDD) workflows for AI-agent CLIs and IDEs like Claude Code, Cursor, and others.
8
8
 
9
- > 🎯 **v1.5.0 - Interactive Requirements Clarification**: `sdd-init` now **blocks vague requirements**! The agent analyzes your project description (quality score 0-100) and interactively asks targeted clarification questions if score < 70%. Focuses on **WHY** (business justification), WHO (target users), WHAT (core features), and success criteria. Context-aware using existing steering docs. Prevents "garbage in, garbage out" with enriched 5W1H structured descriptions. **New service**: `RequirementsClarificationService` with 13 passing unit tests
9
+ > 🚀 **v1.6.0 - Architecture Refactoring**: Decomposed requirements clarification into **5 focused services** following Single Responsibility Principle! Each service now has one clear purpose: `SteeringContextLoader` (I/O), `DescriptionAnalyzer` (scored semantic detection 0-100), `QuestionGenerator` (template-based), `AnswerValidator` (validation + security), `DescriptionEnricher` (5W1H synthesis). Replaced brittle boolean regex with **scored semantic detection** for better accuracy. Externalized question templates to configuration. **62 new unit tests** (65 total passing) ✅. Services average ~100 LOC vs previous 500 LOC monolith. Better maintainability, testability, and type safety!
10
10
 
11
- > **v1.4.5**: Internal improvements! Reorganized test structure for better maintainability, centralized static steering document creation following DRY principle, improved code organization with better separation of concerns.
11
+ > 🎯 **v1.5.0 - Interactive Requirements Clarification**: `sdd-init` now **blocks vague requirements**! The agent analyzes your project description (quality score 0-100) and interactively asks targeted clarification questions if score < 70%. Focuses on **WHY** (business justification), WHO (target users), WHAT (core features), and success criteria. Context-aware using existing steering docs. Prevents "garbage in, garbage out" with enriched 5W1H structured descriptions.
12
12
 
13
- > ✅ **v1.4.4**: Comprehensive codebase analysis + TDD workflow! Documents are generated with real multi-language detection (TypeScript, Java, Python, Go, Ruby, PHP, Rust, C#, Scala), framework detection (Spring Boot, Django, FastAPI, Rails, Laravel, Express, React, etc.), and architecture pattern recognition. New `principles.md` steering document enforces SOLID, DRY, KISS, YAGNI, Separation of Concerns, and Modularity. Task generation now follows Test-Driven Development (RED-GREEN-REFACTOR) workflow.
13
+ > ✅ **v1.4.5**: Internal improvements! Reorganized test structure for better maintainability, centralized static steering document creation following DRY principle, improved code organization with better separation of concerns.
14
14
 
15
15
  ## 🚀 Quick Start
16
16
 
@@ -20,7 +20,7 @@ A Model Context Protocol (MCP) server implementing Spec-Driven Development (SDD)
20
20
  npx -y sdd-mcp-server@latest
21
21
 
22
22
  # Pin exact version (optional)
23
- npx -y sdd-mcp-server@1.4.5
23
+ npx -y sdd-mcp-server@1.6.0
24
24
 
25
25
  # For Claude Code MCP integration, add to your configuration:
26
26
  # "sdd-mcp-server": {
@@ -35,7 +35,7 @@ npx -y sdd-mcp-server@1.4.5
35
35
  npm install -g sdd-mcp-server@latest
36
36
 
37
37
  # Pin exact version (optional)
38
- npm install -g sdd-mcp-server@1.4.5
38
+ npm install -g sdd-mcp-server@1.6.0
39
39
 
40
40
  # Start the server
41
41
  sdd-mcp-server
@@ -0,0 +1,7 @@
1
+ import { ClarificationQuestion, ClarificationAnswers, AnswerValidationResult } from "../../domain/types.js";
2
+ export declare class AnswerValidator {
3
+ /**
4
+ * Validate user-provided clarification answers
5
+ */
6
+ validate(questions: ClarificationQuestion[], answers: ClarificationAnswers): AnswerValidationResult;
7
+ }
@@ -0,0 +1,52 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { injectable } from "inversify";
8
+ import { ANSWER_VALIDATION } from "./clarification-constants.js";
9
+ let AnswerValidator = class AnswerValidator {
10
+ /**
11
+ * Validate user-provided clarification answers
12
+ */
13
+ validate(questions, answers) {
14
+ const missingRequired = [];
15
+ const tooShort = [];
16
+ const containsInvalidContent = [];
17
+ for (const question of questions) {
18
+ const answer = answers[question.id]?.trim() || "";
19
+ // Check for missing required answers
20
+ if (question.required && !answer) {
21
+ missingRequired.push(question.question);
22
+ continue;
23
+ }
24
+ // Check for too-short answers
25
+ if (answer && answer.length < ANSWER_VALIDATION.MIN_ANSWER_LENGTH) {
26
+ tooShort.push({
27
+ question: question.question,
28
+ minLength: ANSWER_VALIDATION.MIN_ANSWER_LENGTH,
29
+ currentLength: answer.length,
30
+ });
31
+ }
32
+ // Check for potentially malicious content
33
+ if (answer && ANSWER_VALIDATION.INVALID_CONTENT_PATTERN.test(answer)) {
34
+ containsInvalidContent.push(question.question);
35
+ }
36
+ }
37
+ const valid = missingRequired.length === 0 &&
38
+ tooShort.length === 0 &&
39
+ containsInvalidContent.length === 0;
40
+ return {
41
+ valid,
42
+ missingRequired,
43
+ tooShort,
44
+ containsInvalidContent,
45
+ };
46
+ }
47
+ };
48
+ AnswerValidator = __decorate([
49
+ injectable()
50
+ ], AnswerValidator);
51
+ export { AnswerValidator };
52
+ //# sourceMappingURL=AnswerValidator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnswerValidator.js","sourceRoot":"","sources":["../../../src/application/services/AnswerValidator.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAMvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAG1D,IAAM,eAAe,GAArB,MAAM,eAAe;IAC1B;;OAEG;IACH,QAAQ,CACN,SAAkC,EAClC,OAA6B;QAE7B,MAAM,eAAe,GAAa,EAAE,CAAC;QACrC,MAAM,QAAQ,GAIT,EAAE,CAAC;QACR,MAAM,sBAAsB,GAAa,EAAE,CAAC;QAE5C,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;YAElD,qCAAqC;YACrC,IAAI,QAAQ,CAAC,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;gBACjC,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBACxC,SAAS;YACX,CAAC;YAED,8BAA8B;YAC9B,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,iBAAiB,CAAC,iBAAiB,EAAE,CAAC;gBAClE,QAAQ,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,QAAQ,CAAC,QAAQ;oBAC3B,SAAS,EAAE,iBAAiB,CAAC,iBAAiB;oBAC9C,aAAa,EAAE,MAAM,CAAC,MAAM;iBAC7B,CAAC,CAAC;YACL,CAAC;YAED,0CAA0C;YAC1C,IAAI,MAAM,IAAI,iBAAiB,CAAC,uBAAuB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;gBACrE,sBAAsB,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;QAED,MAAM,KAAK,GACT,eAAe,CAAC,MAAM,KAAK,CAAC;YAC5B,QAAQ,CAAC,MAAM,KAAK,CAAC;YACrB,sBAAsB,CAAC,MAAM,KAAK,CAAC,CAAC;QAEtC,OAAO;YACL,KAAK;YACL,eAAe;YACf,QAAQ;YACR,sBAAsB;SACvB,CAAC;IACJ,CAAC;CACF,CAAA;AApDY,eAAe;IAD3B,UAAU,EAAE;GACA,eAAe,CAoD3B"}
@@ -0,0 +1,28 @@
1
+ import { ClarificationAnalysis, SteeringContext } from "../../domain/types.js";
2
+ export declare class DescriptionAnalyzer {
3
+ /**
4
+ * Analyzes a project description for completeness using scored semantic detection
5
+ */
6
+ analyze(description: string, context: SteeringContext): ClarificationAnalysis;
7
+ /**
8
+ * Score semantic presence using keyword density approach
9
+ * Returns 0-100 based on presence and density of matching patterns
10
+ */
11
+ private scoreSemanticPresence;
12
+ /**
13
+ * Detect ambiguous terms in the description
14
+ */
15
+ private detectAmbiguousTerms;
16
+ /**
17
+ * Calculate overall quality score based on presence of elements
18
+ */
19
+ private calculateQualityScore;
20
+ /**
21
+ * Identify which elements are missing considering steering context
22
+ */
23
+ private identifyMissingElements;
24
+ /**
25
+ * Extract context around a matched term for better clarity
26
+ */
27
+ private extractContext;
28
+ }
@@ -0,0 +1,184 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { injectable } from "inversify";
8
+ import { QUALITY_SCORE_WEIGHTS, PATTERN_DETECTION, AMBIGUOUS_TERMS, } from "./clarification-constants.js";
9
+ let DescriptionAnalyzer = class DescriptionAnalyzer {
10
+ /**
11
+ * Analyzes a project description for completeness using scored semantic detection
12
+ */
13
+ analyze(description, context) {
14
+ // Handle empty descriptions
15
+ if (!description || description.trim().length === 0) {
16
+ return {
17
+ qualityScore: 0,
18
+ whyScore: 0,
19
+ whoScore: 0,
20
+ whatScore: 0,
21
+ successScore: 0,
22
+ hasWhy: false,
23
+ hasWho: false,
24
+ hasWhat: false,
25
+ hasSuccessCriteria: false,
26
+ missingElements: ["WHY", "WHO", "WHAT", "Success Criteria"],
27
+ ambiguousTerms: [],
28
+ needsClarification: true,
29
+ };
30
+ }
31
+ // Calculate semantic scores (0-100 each)
32
+ const whyScore = this.scoreSemanticPresence(description, PATTERN_DETECTION.WHY_PATTERNS);
33
+ const whoScore = this.scoreSemanticPresence(description, PATTERN_DETECTION.WHO_PATTERNS);
34
+ const whatScore = this.scoreSemanticPresence(description, PATTERN_DETECTION.WHAT_PATTERNS);
35
+ const successScore = this.scoreSemanticPresence(description, PATTERN_DETECTION.SUCCESS_PATTERNS);
36
+ // Derive boolean presence (threshold: 30%)
37
+ const hasWhy = whyScore > 30;
38
+ const hasWho = whoScore > 30;
39
+ const hasWhat = whatScore > 30;
40
+ const hasSuccessCriteria = successScore > 30;
41
+ // Detect ambiguous terms
42
+ const ambiguousTerms = this.detectAmbiguousTerms(description);
43
+ // Calculate overall quality score
44
+ const qualityScore = this.calculateQualityScore({
45
+ hasWhy,
46
+ hasWho,
47
+ hasWhat,
48
+ hasSuccessCriteria,
49
+ ambiguousTermCount: ambiguousTerms.length,
50
+ descriptionLength: description.length,
51
+ });
52
+ // Determine missing elements considering steering context
53
+ const missingElements = this.identifyMissingElements({ hasWhy, hasWho, hasWhat, hasSuccessCriteria }, context);
54
+ // Need clarification if score below threshold or missing critical elements
55
+ const needsClarification = qualityScore < QUALITY_SCORE_WEIGHTS.MIN_ACCEPTABLE_SCORE ||
56
+ missingElements.length > 0;
57
+ return {
58
+ qualityScore,
59
+ whyScore,
60
+ whoScore,
61
+ whatScore,
62
+ successScore,
63
+ hasWhy,
64
+ hasWho,
65
+ hasWhat,
66
+ hasSuccessCriteria,
67
+ missingElements,
68
+ ambiguousTerms,
69
+ needsClarification,
70
+ };
71
+ }
72
+ /**
73
+ * Score semantic presence using keyword density approach
74
+ * Returns 0-100 based on presence and density of matching patterns
75
+ */
76
+ scoreSemanticPresence(description, patterns) {
77
+ const words = description
78
+ .toLowerCase()
79
+ .split(/\s+/)
80
+ .filter((w) => w.length > 0);
81
+ if (words.length === 0)
82
+ return 0;
83
+ const matchedWords = words.filter((word) => patterns.some((pattern) => pattern.test(word)));
84
+ if (matchedWords.length === 0)
85
+ return 0;
86
+ // Base score for any presence
87
+ const coverage = 50;
88
+ // Density score based on percentage of matched words
89
+ const density = (matchedWords.length / words.length) * 100;
90
+ // Total score capped at 100
91
+ return Math.min(100, coverage + density);
92
+ }
93
+ /**
94
+ * Detect ambiguous terms in the description
95
+ */
96
+ detectAmbiguousTerms(description) {
97
+ const ambiguousTerms = [];
98
+ for (const { pattern, suggestion } of AMBIGUOUS_TERMS) {
99
+ const matches = description.match(pattern);
100
+ if (matches) {
101
+ for (const match of matches) {
102
+ const context = this.extractContext(description, match);
103
+ ambiguousTerms.push({
104
+ term: match,
105
+ context,
106
+ suggestion,
107
+ });
108
+ }
109
+ }
110
+ }
111
+ return ambiguousTerms;
112
+ }
113
+ /**
114
+ * Calculate overall quality score based on presence of elements
115
+ */
116
+ calculateQualityScore(metrics) {
117
+ let score = 0;
118
+ // WHY is most important
119
+ if (metrics.hasWhy)
120
+ score += QUALITY_SCORE_WEIGHTS.HAS_WHY;
121
+ // WHO is critical
122
+ if (metrics.hasWho)
123
+ score += QUALITY_SCORE_WEIGHTS.HAS_WHO;
124
+ // WHAT is essential
125
+ if (metrics.hasWhat)
126
+ score += QUALITY_SCORE_WEIGHTS.HAS_WHAT;
127
+ // Success criteria
128
+ if (metrics.hasSuccessCriteria)
129
+ score += QUALITY_SCORE_WEIGHTS.HAS_SUCCESS;
130
+ // Penalize ambiguous terms
131
+ const ambiguityPenalty = Math.min(QUALITY_SCORE_WEIGHTS.MAX_AMBIGUITY_PENALTY, metrics.ambiguousTermCount * QUALITY_SCORE_WEIGHTS.AMBIGUITY_PENALTY);
132
+ score -= ambiguityPenalty;
133
+ // Length bonus - adequate detail
134
+ if (metrics.descriptionLength > QUALITY_SCORE_WEIGHTS.LENGTH_BONUS_THRESHOLD_1)
135
+ score += QUALITY_SCORE_WEIGHTS.LENGTH_BONUS_POINTS;
136
+ if (metrics.descriptionLength > QUALITY_SCORE_WEIGHTS.LENGTH_BONUS_THRESHOLD_2)
137
+ score += QUALITY_SCORE_WEIGHTS.LENGTH_BONUS_POINTS;
138
+ if (metrics.descriptionLength > QUALITY_SCORE_WEIGHTS.LENGTH_BONUS_THRESHOLD_3)
139
+ score += QUALITY_SCORE_WEIGHTS.LENGTH_BONUS_POINTS;
140
+ return Math.max(0, Math.min(100, score));
141
+ }
142
+ /**
143
+ * Identify which elements are missing considering steering context
144
+ */
145
+ identifyMissingElements(presence, context) {
146
+ const missing = [];
147
+ // WHY is required unless product context exists
148
+ if (!presence.hasWhy && !context.hasProductContext) {
149
+ missing.push("Business justification (WHY)");
150
+ }
151
+ // WHO is required unless target users documented
152
+ if (!presence.hasWho && !context.hasTargetUsers) {
153
+ missing.push("Target users (WHO)");
154
+ }
155
+ // WHAT is always required
156
+ if (!presence.hasWhat) {
157
+ missing.push("Core features (WHAT)");
158
+ }
159
+ // Success criteria always required
160
+ if (!presence.hasSuccessCriteria) {
161
+ missing.push("Success criteria");
162
+ }
163
+ return missing;
164
+ }
165
+ /**
166
+ * Extract context around a matched term for better clarity
167
+ */
168
+ extractContext(description, term) {
169
+ const index = description.toLowerCase().indexOf(term.toLowerCase());
170
+ if (index === -1)
171
+ return "";
172
+ const start = Math.max(0, index - 30);
173
+ const end = Math.min(description.length, index + term.length + 30);
174
+ const context = description.substring(start, end);
175
+ return ((start > 0 ? "..." : "") +
176
+ context +
177
+ (end < description.length ? "..." : ""));
178
+ }
179
+ };
180
+ DescriptionAnalyzer = __decorate([
181
+ injectable()
182
+ ], DescriptionAnalyzer);
183
+ export { DescriptionAnalyzer };
184
+ //# sourceMappingURL=DescriptionAnalyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DescriptionAnalyzer.js","sourceRoot":"","sources":["../../../src/application/services/DescriptionAnalyzer.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAMvC,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,eAAe,GAChB,MAAM,8BAA8B,CAAC;AAG/B,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;IAC9B;;OAEG;IACH,OAAO,CACL,WAAmB,EACnB,OAAwB;QAExB,4BAA4B;QAC5B,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpD,OAAO;gBACL,YAAY,EAAE,CAAC;gBACf,QAAQ,EAAE,CAAC;gBACX,QAAQ,EAAE,CAAC;gBACX,SAAS,EAAE,CAAC;gBACZ,YAAY,EAAE,CAAC;gBACf,MAAM,EAAE,KAAK;gBACb,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,KAAK;gBACd,kBAAkB,EAAE,KAAK;gBACzB,eAAe,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,CAAC;gBAC3D,cAAc,EAAE,EAAE;gBAClB,kBAAkB,EAAE,IAAI;aACzB,CAAC;QACJ,CAAC;QAED,yCAAyC;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,qBAAqB,CACzC,WAAW,EACX,iBAAiB,CAAC,YAAY,CAC/B,CAAC;QACF,MAAM,QAAQ,GAAG,IAAI,CAAC,qBAAqB,CACzC,WAAW,EACX,iBAAiB,CAAC,YAAY,CAC/B,CAAC;QACF,MAAM,SAAS,GAAG,IAAI,CAAC,qBAAqB,CAC1C,WAAW,EACX,iBAAiB,CAAC,aAAa,CAChC,CAAC;QACF,MAAM,YAAY,GAAG,IAAI,CAAC,qBAAqB,CAC7C,WAAW,EACX,iBAAiB,CAAC,gBAAgB,CACnC,CAAC;QAEF,2CAA2C;QAC3C,MAAM,MAAM,GAAG,QAAQ,GAAG,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,QAAQ,GAAG,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,SAAS,GAAG,EAAE,CAAC;QAC/B,MAAM,kBAAkB,GAAG,YAAY,GAAG,EAAE,CAAC;QAE7C,yBAAyB;QACzB,MAAM,cAAc,GAAG,IAAI,CAAC,oBAAoB,CAAC,WAAW,CAAC,CAAC;QAE9D,kCAAkC;QAClC,MAAM,YAAY,GAAG,IAAI,CAAC,qBAAqB,CAAC;YAC9C,MAAM;YACN,MAAM;YACN,OAAO;YACP,kBAAkB;YAClB,kBAAkB,EAAE,cAAc,CAAC,MAAM;YACzC,iBAAiB,EAAE,WAAW,CAAC,MAAM;SACtC,CAAC,CAAC;QAEH,0DAA0D;QAC1D,MAAM,eAAe,GAAG,IAAI,CAAC,uBAAuB,CAClD,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,EAAE,EAC/C,OAAO,CACR,CAAC;QAEF,2EAA2E;QAC3E,MAAM,kBAAkB,GACtB,YAAY,GAAG,qBAAqB,CAAC,oBAAoB;YACzD,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC;QAE7B,OAAO;YACL,YAAY;YACZ,QAAQ;YACR,QAAQ;YACR,SAAS;YACT,YAAY;YACZ,MAAM;YACN,MAAM;YACN,OAAO;YACP,kBAAkB;YAClB,eAAe;YACf,cAAc;YACd,kBAAkB;SACnB,CAAC;IACJ,CAAC;IAED;;;OAGG;IACK,qBAAqB,CAC3B,WAAmB,EACnB,QAA2B;QAE3B,MAAM,KAAK,GAAG,WAAW;aACtB,WAAW,EAAE;aACb,KAAK,CAAC,KAAK,CAAC;aACZ,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAE/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QAEjC,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CACzC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAC/C,CAAC;QAEF,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QAExC,8BAA8B;QAC9B,MAAM,QAAQ,GAAG,EAAE,CAAC;QAEpB,qDAAqD;QACrD,MAAM,OAAO,GAAG,CAAC,YAAY,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC;QAE3D,4BAA4B;QAC5B,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED;;OAEG;IACK,oBAAoB,CAAC,WAAmB;QAC9C,MAAM,cAAc,GAAoB,EAAE,CAAC;QAE3C,KAAK,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,eAAe,EAAE,CAAC;YACtD,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC3C,IAAI,OAAO,EAAE,CAAC;gBACZ,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;oBAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;oBACxD,cAAc,CAAC,IAAI,CAAC;wBAClB,IAAI,EAAE,KAAK;wBACX,OAAO;wBACP,UAAU;qBACX,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,cAAc,CAAC;IACxB,CAAC;IAED;;OAEG;IACK,qBAAqB,CAAC,OAO7B;QACC,IAAI,KAAK,GAAG,CAAC,CAAC;QAEd,wBAAwB;QACxB,IAAI,OAAO,CAAC,MAAM;YAAE,KAAK,IAAI,qBAAqB,CAAC,OAAO,CAAC;QAE3D,kBAAkB;QAClB,IAAI,OAAO,CAAC,MAAM;YAAE,KAAK,IAAI,qBAAqB,CAAC,OAAO,CAAC;QAE3D,oBAAoB;QACpB,IAAI,OAAO,CAAC,OAAO;YAAE,KAAK,IAAI,qBAAqB,CAAC,QAAQ,CAAC;QAE7D,mBAAmB;QACnB,IAAI,OAAO,CAAC,kBAAkB;YAAE,KAAK,IAAI,qBAAqB,CAAC,WAAW,CAAC;QAE3E,2BAA2B;QAC3B,MAAM,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAC/B,qBAAqB,CAAC,qBAAqB,EAC3C,OAAO,CAAC,kBAAkB,GAAG,qBAAqB,CAAC,iBAAiB,CACrE,CAAC;QACF,KAAK,IAAI,gBAAgB,CAAC;QAE1B,iCAAiC;QACjC,IACE,OAAO,CAAC,iBAAiB,GAAG,qBAAqB,CAAC,wBAAwB;YAE1E,KAAK,IAAI,qBAAqB,CAAC,mBAAmB,CAAC;QACrD,IACE,OAAO,CAAC,iBAAiB,GAAG,qBAAqB,CAAC,wBAAwB;YAE1E,KAAK,IAAI,qBAAqB,CAAC,mBAAmB,CAAC;QACrD,IACE,OAAO,CAAC,iBAAiB,GAAG,qBAAqB,CAAC,wBAAwB;YAE1E,KAAK,IAAI,qBAAqB,CAAC,mBAAmB,CAAC;QAErD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IAC3C,CAAC;IAED;;OAEG;IACK,uBAAuB,CAC7B,QAKC,EACD,OAAwB;QAExB,MAAM,OAAO,GAAa,EAAE,CAAC;QAE7B,gDAAgD;QAChD,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC;YACnD,OAAO,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC/C,CAAC;QAED,iDAAiD;QACjD,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;YAChD,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QACrC,CAAC;QAED,0BAA0B;QAC1B,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YACtB,OAAO,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QACvC,CAAC;QAED,mCAAmC;QACnC,IAAI,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC;YACjC,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACnC,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,WAAmB,EAAE,IAAY;QACtD,MAAM,KAAK,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QACpE,IAAI,KAAK,KAAK,CAAC,CAAC;YAAE,OAAO,EAAE,CAAC;QAE5B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,EAAE,CAAC,CAAC;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;QACnE,MAAM,OAAO,GAAG,WAAW,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAElD,OAAO,CACL,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;YACxB,OAAO;YACP,CAAC,GAAG,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CACxC,CAAC;IACJ,CAAC;CACF,CAAA;AAvPY,mBAAmB;IAD/B,UAAU,EAAE;GACA,mBAAmB,CAuP/B"}
@@ -0,0 +1,15 @@
1
+ import { ClarificationQuestion, ClarificationAnswers, EnrichedProjectDescription } from "../../domain/types.js";
2
+ export declare class DescriptionEnricher {
3
+ /**
4
+ * Synthesize enriched project description from original + clarification answers
5
+ */
6
+ synthesize(originalDescription: string, questions: ClarificationQuestion[], answers: ClarificationAnswers): EnrichedProjectDescription;
7
+ /**
8
+ * Extract all answers for a specific question category
9
+ */
10
+ private extractAnswersByCategory;
11
+ /**
12
+ * Build enriched description with 5W1H structure
13
+ */
14
+ private buildEnrichedDescription;
15
+ }
@@ -0,0 +1,77 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { injectable } from "inversify";
8
+ import { QuestionCategory, } from "../../domain/types.js";
9
+ let DescriptionEnricher = class DescriptionEnricher {
10
+ /**
11
+ * Synthesize enriched project description from original + clarification answers
12
+ */
13
+ synthesize(originalDescription, questions, answers) {
14
+ const why = this.extractAnswersByCategory(questions, answers, QuestionCategory.WHY);
15
+ const who = this.extractAnswersByCategory(questions, answers, QuestionCategory.WHO);
16
+ const what = this.extractAnswersByCategory(questions, answers, QuestionCategory.WHAT);
17
+ const how = this.extractAnswersByCategory(questions, answers, QuestionCategory.HOW);
18
+ const successCriteria = this.extractAnswersByCategory(questions, answers, QuestionCategory.SUCCESS);
19
+ const enriched = this.buildEnrichedDescription({
20
+ original: originalDescription,
21
+ why,
22
+ who,
23
+ what,
24
+ how,
25
+ successCriteria,
26
+ });
27
+ return {
28
+ original: originalDescription,
29
+ why,
30
+ who,
31
+ what,
32
+ how,
33
+ successCriteria,
34
+ enriched,
35
+ };
36
+ }
37
+ /**
38
+ * Extract all answers for a specific question category
39
+ */
40
+ extractAnswersByCategory(questions, answers, category) {
41
+ const categoryQuestions = questions.filter((q) => q.category === category);
42
+ const categoryAnswers = categoryQuestions
43
+ .map((q) => answers[q.id])
44
+ .filter((a) => a && a.trim().length > 0);
45
+ return categoryAnswers.join(" ");
46
+ }
47
+ /**
48
+ * Build enriched description with 5W1H structure
49
+ */
50
+ buildEnrichedDescription(components) {
51
+ const parts = [];
52
+ if (components.original) {
53
+ parts.push(`## Original Description\n${components.original}`);
54
+ }
55
+ if (components.why) {
56
+ parts.push(`## Business Justification (Why)\n${components.why}`);
57
+ }
58
+ if (components.who) {
59
+ parts.push(`## Target Users (Who)\n${components.who}`);
60
+ }
61
+ if (components.what) {
62
+ parts.push(`## Core Features (What)\n${components.what}`);
63
+ }
64
+ if (components.how) {
65
+ parts.push(`## Technical Approach (How)\n${components.how}`);
66
+ }
67
+ if (components.successCriteria) {
68
+ parts.push(`## Success Criteria\n${components.successCriteria}`);
69
+ }
70
+ return parts.join("\n\n");
71
+ }
72
+ };
73
+ DescriptionEnricher = __decorate([
74
+ injectable()
75
+ ], DescriptionEnricher);
76
+ export { DescriptionEnricher };
77
+ //# sourceMappingURL=DescriptionEnricher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DescriptionEnricher.js","sourceRoot":"","sources":["../../../src/application/services/DescriptionEnricher.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAIL,gBAAgB,GAEjB,MAAM,uBAAuB,CAAC;AAGxB,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;IAC9B;;OAEG;IACH,UAAU,CACR,mBAA2B,EAC3B,SAAkC,EAClC,OAA6B;QAE7B,MAAM,GAAG,GAAG,IAAI,CAAC,wBAAwB,CACvC,SAAS,EACT,OAAO,EACP,gBAAgB,CAAC,GAAG,CACrB,CAAC;QACF,MAAM,GAAG,GAAG,IAAI,CAAC,wBAAwB,CACvC,SAAS,EACT,OAAO,EACP,gBAAgB,CAAC,GAAG,CACrB,CAAC;QACF,MAAM,IAAI,GAAG,IAAI,CAAC,wBAAwB,CACxC,SAAS,EACT,OAAO,EACP,gBAAgB,CAAC,IAAI,CACtB,CAAC;QACF,MAAM,GAAG,GAAG,IAAI,CAAC,wBAAwB,CACvC,SAAS,EACT,OAAO,EACP,gBAAgB,CAAC,GAAG,CACrB,CAAC;QACF,MAAM,eAAe,GAAG,IAAI,CAAC,wBAAwB,CACnD,SAAS,EACT,OAAO,EACP,gBAAgB,CAAC,OAAO,CACzB,CAAC;QAEF,MAAM,QAAQ,GAAG,IAAI,CAAC,wBAAwB,CAAC;YAC7C,QAAQ,EAAE,mBAAmB;YAC7B,GAAG;YACH,GAAG;YACH,IAAI;YACJ,GAAG;YACH,eAAe;SAChB,CAAC,CAAC;QAEH,OAAO;YACL,QAAQ,EAAE,mBAAmB;YAC7B,GAAG;YACH,GAAG;YACH,IAAI;YACJ,GAAG;YACH,eAAe;YACf,QAAQ;SACT,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,wBAAwB,CAC9B,SAAkC,EAClC,OAA6B,EAC7B,QAA0B;QAE1B,MAAM,iBAAiB,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;QAC3E,MAAM,eAAe,GAAG,iBAAiB;aACtC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;aACzB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAE3C,OAAO,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAED;;OAEG;IACK,wBAAwB,CAC9B,UAAiC;QAEjC,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;YACxB,KAAK,CAAC,IAAI,CAAC,4BAA4B,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;QAChE,CAAC;QAED,IAAI,UAAU,CAAC,GAAG,EAAE,CAAC;YACnB,KAAK,CAAC,IAAI,CAAC,oCAAoC,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,IAAI,UAAU,CAAC,GAAG,EAAE,CAAC;YACnB,KAAK,CAAC,IAAI,CAAC,0BAA0B,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC;QACzD,CAAC;QAED,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC;YACpB,KAAK,CAAC,IAAI,CAAC,4BAA4B,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5D,CAAC;QAED,IAAI,UAAU,CAAC,GAAG,EAAE,CAAC;YACnB,KAAK,CAAC,IAAI,CAAC,gCAAgC,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC;QAC/D,CAAC;QAED,IAAI,UAAU,CAAC,eAAe,EAAE,CAAC;YAC/B,KAAK,CAAC,IAAI,CAAC,wBAAwB,UAAU,CAAC,eAAe,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;CACF,CAAA;AAzGY,mBAAmB;IAD/B,UAAU,EAAE;GACA,mBAAmB,CAyG/B"}
@@ -0,0 +1,7 @@
1
+ import { ClarificationQuestion, ClarificationAnalysis, SteeringContext } from "../../domain/types.js";
2
+ export declare class QuestionGenerator {
3
+ /**
4
+ * Generate clarification questions based on analysis and steering context
5
+ */
6
+ generateQuestions(analysis: ClarificationAnalysis, context: SteeringContext): ClarificationQuestion[];
7
+ }
@@ -0,0 +1,30 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { injectable } from "inversify";
8
+ import { CLARIFICATION_QUESTIONS } from "./clarification-questions.js";
9
+ let QuestionGenerator = class QuestionGenerator {
10
+ /**
11
+ * Generate clarification questions based on analysis and steering context
12
+ */
13
+ generateQuestions(analysis, context) {
14
+ return Object.values(CLARIFICATION_QUESTIONS)
15
+ .filter((template) => template.condition(analysis, context))
16
+ .map((template) => ({
17
+ id: template.id,
18
+ category: template.category,
19
+ question: template.question,
20
+ why: template.rationale,
21
+ examples: template.examples,
22
+ required: template.required,
23
+ }));
24
+ }
25
+ };
26
+ QuestionGenerator = __decorate([
27
+ injectable()
28
+ ], QuestionGenerator);
29
+ export { QuestionGenerator };
30
+ //# sourceMappingURL=QuestionGenerator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QuestionGenerator.js","sourceRoot":"","sources":["../../../src/application/services/QuestionGenerator.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAMvC,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAGhE,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IAC5B;;OAEG;IACH,iBAAiB,CACf,QAA+B,EAC/B,OAAwB;QAExB,OAAO,MAAM,CAAC,MAAM,CAAC,uBAAuB,CAAC;aAC1C,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;aAC3D,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAClB,EAAE,EAAE,QAAQ,CAAC,EAAE;YACf,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,GAAG,EAAE,QAAQ,CAAC,SAAS;YACvB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;SAC5B,CAAC,CAAC,CAAC;IACR,CAAC;CACF,CAAA;AAnBY,iBAAiB;IAD7B,UAAU,EAAE;GACA,iBAAiB,CAmB7B"}
@@ -1,9 +1,28 @@
1
- import { FileSystemPort, LoggerPort } from "../../domain/ports.js";
1
+ import { LoggerPort } from "../../domain/ports.js";
2
2
  import { ClarificationQuestion, EnrichedProjectDescription, ClarificationResult, ClarificationAnswers, AnswerValidationResult } from "../../domain/types.js";
3
+ import { SteeringContextLoader } from "./SteeringContextLoader.js";
4
+ import { DescriptionAnalyzer } from "./DescriptionAnalyzer.js";
5
+ import { QuestionGenerator } from "./QuestionGenerator.js";
6
+ import { AnswerValidator } from "./AnswerValidator.js";
7
+ import { DescriptionEnricher } from "./DescriptionEnricher.js";
8
+ /**
9
+ * Orchestrator service for requirements clarification workflow
10
+ *
11
+ * Delegates to specialized services:
12
+ * - SteeringContextLoader: Loads steering documents
13
+ * - DescriptionAnalyzer: Analyzes description quality
14
+ * - QuestionGenerator: Generates clarification questions
15
+ * - AnswerValidator: Validates user answers
16
+ * - DescriptionEnricher: Synthesizes enriched descriptions
17
+ */
3
18
  export declare class RequirementsClarificationService {
4
- private readonly fileSystem;
5
19
  private readonly logger;
6
- constructor(fileSystem: FileSystemPort, logger: LoggerPort);
20
+ private readonly steeringLoader;
21
+ private readonly analyzer;
22
+ private readonly questionGenerator;
23
+ private readonly answerValidator;
24
+ private readonly enricher;
25
+ constructor(logger: LoggerPort, steeringLoader: SteeringContextLoader, analyzer: DescriptionAnalyzer, questionGenerator: QuestionGenerator, answerValidator: AnswerValidator, enricher: DescriptionEnricher);
7
26
  /**
8
27
  * Analyzes a project description to determine if clarification is needed
9
28
  */
@@ -16,52 +35,4 @@ export declare class RequirementsClarificationService {
16
35
  * Synthesizes an enriched project description from original + answers
17
36
  */
18
37
  synthesizeDescription(originalDescription: string, questions: ClarificationQuestion[], answers: ClarificationAnswers): EnrichedProjectDescription;
19
- /**
20
- * Performs the core analysis of the description
21
- */
22
- private performAnalysis;
23
- /**
24
- * Generates targeted clarification questions based on analysis
25
- */
26
- private generateQuestions;
27
- /**
28
- * Load steering documents for context
29
- */
30
- private loadSteeringContext;
31
- /**
32
- * Detects if description contains WHY (business justification)
33
- */
34
- private detectWhy;
35
- /**
36
- * Detects if description contains WHO (target users)
37
- */
38
- private detectWho;
39
- /**
40
- * Detects if description contains WHAT (features, scope)
41
- */
42
- private detectWhat;
43
- /**
44
- * Detects if description contains success criteria
45
- */
46
- private detectSuccessCriteria;
47
- /**
48
- * Detects ambiguous terms that need clarification
49
- */
50
- private detectAmbiguousTerms;
51
- /**
52
- * Extracts surrounding context for an ambiguous term
53
- */
54
- private extractContext;
55
- /**
56
- * Calculates quality score based on completeness and clarity
57
- */
58
- private calculateQualityScore;
59
- /**
60
- * Extracts answers for a specific category
61
- */
62
- private extractAnswersByCategory;
63
- /**
64
- * Builds the enriched description from all components
65
- */
66
- private buildEnrichedDescription;
67
38
  }