pmp-gywd 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +27 -0
- package/README.md +567 -0
- package/bin/install.js +348 -0
- package/commands/gywd/add-phase.md +207 -0
- package/commands/gywd/anticipate.md +271 -0
- package/commands/gywd/bootstrap.md +336 -0
- package/commands/gywd/challenge.md +344 -0
- package/commands/gywd/check-drift.md +144 -0
- package/commands/gywd/complete-milestone.md +106 -0
- package/commands/gywd/consider-issues.md +202 -0
- package/commands/gywd/context.md +93 -0
- package/commands/gywd/create-roadmap.md +115 -0
- package/commands/gywd/deps.md +169 -0
- package/commands/gywd/digest.md +138 -0
- package/commands/gywd/discuss-milestone.md +47 -0
- package/commands/gywd/discuss-phase.md +60 -0
- package/commands/gywd/execute-plan.md +161 -0
- package/commands/gywd/extract-decisions.md +325 -0
- package/commands/gywd/health.md +150 -0
- package/commands/gywd/help.md +556 -0
- package/commands/gywd/history.md +278 -0
- package/commands/gywd/impact.md +317 -0
- package/commands/gywd/init.md +95 -0
- package/commands/gywd/insert-phase.md +227 -0
- package/commands/gywd/list-phase-assumptions.md +50 -0
- package/commands/gywd/map-codebase.md +84 -0
- package/commands/gywd/memory.md +159 -0
- package/commands/gywd/new-milestone.md +59 -0
- package/commands/gywd/new-project.md +315 -0
- package/commands/gywd/pause-work.md +123 -0
- package/commands/gywd/plan-fix.md +205 -0
- package/commands/gywd/plan-phase.md +93 -0
- package/commands/gywd/preview-plan.md +139 -0
- package/commands/gywd/profile.md +363 -0
- package/commands/gywd/progress.md +317 -0
- package/commands/gywd/remove-phase.md +338 -0
- package/commands/gywd/research-phase.md +91 -0
- package/commands/gywd/resume-work.md +40 -0
- package/commands/gywd/rollback.md +179 -0
- package/commands/gywd/status.md +42 -0
- package/commands/gywd/sync-github.md +234 -0
- package/commands/gywd/verify-work.md +71 -0
- package/commands/gywd/why.md +251 -0
- package/docs/COMMANDS.md +722 -0
- package/docs/CONTRIBUTING.md +342 -0
- package/docs/EXAMPLES.md +535 -0
- package/docs/GETTING-STARTED.md +262 -0
- package/docs/README.md +55 -0
- package/docs/RELEASING.md +159 -0
- package/get-your-work-done/core/agent-patterns.md +331 -0
- package/get-your-work-done/core/architecture.md +334 -0
- package/get-your-work-done/core/context-model-schema.json +154 -0
- package/get-your-work-done/core/decisions-schema.json +193 -0
- package/get-your-work-done/core/learning-state-schema.json +133 -0
- package/get-your-work-done/core/profile-schema.json +257 -0
- package/get-your-work-done/references/adaptive-decomposition.md +175 -0
- package/get-your-work-done/references/checkpoints.md +287 -0
- package/get-your-work-done/references/confidence-scoring.md +169 -0
- package/get-your-work-done/references/continuation-format.md +255 -0
- package/get-your-work-done/references/git-integration.md +254 -0
- package/get-your-work-done/references/plan-format.md +428 -0
- package/get-your-work-done/references/principles.md +157 -0
- package/get-your-work-done/references/questioning.md +162 -0
- package/get-your-work-done/references/research-pitfalls.md +215 -0
- package/get-your-work-done/references/scope-estimation.md +172 -0
- package/get-your-work-done/references/tdd.md +263 -0
- package/get-your-work-done/templates/codebase/architecture.md +255 -0
- package/get-your-work-done/templates/codebase/concerns.md +310 -0
- package/get-your-work-done/templates/codebase/conventions.md +307 -0
- package/get-your-work-done/templates/codebase/integrations.md +280 -0
- package/get-your-work-done/templates/codebase/stack.md +186 -0
- package/get-your-work-done/templates/codebase/structure.md +285 -0
- package/get-your-work-done/templates/codebase/testing.md +480 -0
- package/get-your-work-done/templates/config.json +18 -0
- package/get-your-work-done/templates/context.md +161 -0
- package/get-your-work-done/templates/continue-here.md +78 -0
- package/get-your-work-done/templates/discovery.md +146 -0
- package/get-your-work-done/templates/issues.md +32 -0
- package/get-your-work-done/templates/milestone-archive.md +123 -0
- package/get-your-work-done/templates/milestone-context.md +93 -0
- package/get-your-work-done/templates/milestone.md +115 -0
- package/get-your-work-done/templates/phase-prompt.md +303 -0
- package/get-your-work-done/templates/project.md +184 -0
- package/get-your-work-done/templates/research.md +529 -0
- package/get-your-work-done/templates/roadmap.md +196 -0
- package/get-your-work-done/templates/state.md +210 -0
- package/get-your-work-done/templates/summary.md +273 -0
- package/get-your-work-done/templates/uat-issues.md +143 -0
- package/get-your-work-done/workflows/complete-milestone.md +643 -0
- package/get-your-work-done/workflows/create-milestone.md +416 -0
- package/get-your-work-done/workflows/create-roadmap.md +481 -0
- package/get-your-work-done/workflows/discovery-phase.md +293 -0
- package/get-your-work-done/workflows/discuss-milestone.md +236 -0
- package/get-your-work-done/workflows/discuss-phase.md +247 -0
- package/get-your-work-done/workflows/execute-phase.md +1625 -0
- package/get-your-work-done/workflows/list-phase-assumptions.md +178 -0
- package/get-your-work-done/workflows/map-codebase.md +434 -0
- package/get-your-work-done/workflows/plan-phase.md +488 -0
- package/get-your-work-done/workflows/research-phase.md +436 -0
- package/get-your-work-done/workflows/resume-project.md +287 -0
- package/get-your-work-done/workflows/transition.md +580 -0
- package/get-your-work-done/workflows/verify-work.md +202 -0
- package/lib/automation/dependency-analyzer.js +635 -0
- package/lib/automation/doc-generator.js +643 -0
- package/lib/automation/index.js +42 -0
- package/lib/automation/test-generator.js +628 -0
- package/lib/context/context-analyzer.js +554 -0
- package/lib/context/context-cache.js +426 -0
- package/lib/context/context-predictor.js +622 -0
- package/lib/context/index.js +44 -0
- package/lib/memory/confidence-calibrator.js +484 -0
- package/lib/memory/feedback-collector.js +551 -0
- package/lib/memory/global-memory.js +465 -0
- package/lib/memory/index.js +75 -0
- package/lib/memory/pattern-aggregator.js +487 -0
- package/lib/memory/team-sync.js +501 -0
- package/lib/profile/index.js +24 -0
- package/lib/profile/pattern-learner.js +303 -0
- package/lib/profile/profile-manager.js +445 -0
- package/lib/questioning/index.js +49 -0
- package/lib/questioning/question-engine.js +311 -0
- package/lib/questioning/question-templates.js +315 -0
- package/lib/validators/command-validator.js +188 -0
- package/lib/validators/index.js +29 -0
- package/lib/validators/schema-validator.js +183 -0
- package/package.json +61 -0
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adaptive Questioning Engine
|
|
3
|
+
*
|
|
4
|
+
* Generates context-aware questions that learn from responses.
|
|
5
|
+
* Core component of the "sophisticated brain" for v3.0.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Question types for different purposes
|
|
10
|
+
*/
|
|
11
|
+
const QUESTION_TYPES = {
|
|
12
|
+
CLARIFYING: 'clarifying', // Clarify ambiguous requirements
|
|
13
|
+
EXPLORATORY: 'exploratory', // Discover unknown aspects
|
|
14
|
+
VALIDATING: 'validating', // Confirm assumptions
|
|
15
|
+
TECHNICAL: 'technical', // Technical decisions
|
|
16
|
+
PREFERENCE: 'preference', // User preferences
|
|
17
|
+
CONSTRAINT: 'constraint', // Identify constraints
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Question priority levels
|
|
22
|
+
*/
|
|
23
|
+
const PRIORITY = {
|
|
24
|
+
CRITICAL: 'critical', // Must ask before proceeding
|
|
25
|
+
HIGH: 'high', // Important but can infer
|
|
26
|
+
MEDIUM: 'medium', // Good to know
|
|
27
|
+
LOW: 'low', // Nice to have
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Question template structure
|
|
32
|
+
*/
|
|
33
|
+
const createQuestion = (opts) => ({
|
|
34
|
+
// Spread opts first to include any extra fields (expertText, beginnerText, etc.)
|
|
35
|
+
...opts,
|
|
36
|
+
// Then set defaults for standard fields
|
|
37
|
+
id: opts.id || `q-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
38
|
+
type: opts.type || QUESTION_TYPES.CLARIFYING,
|
|
39
|
+
priority: opts.priority || PRIORITY.MEDIUM,
|
|
40
|
+
text: opts.text,
|
|
41
|
+
context: opts.context || null,
|
|
42
|
+
options: opts.options || null,
|
|
43
|
+
defaultAnswer: opts.defaultAnswer || null,
|
|
44
|
+
followUps: opts.followUps || [],
|
|
45
|
+
tags: opts.tags || [],
|
|
46
|
+
askCondition: opts.askCondition || null,
|
|
47
|
+
skipIfKnown: opts.skipIfKnown || [],
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Adaptive Questioning Engine class
|
|
52
|
+
*/
|
|
53
|
+
class QuestionEngine {
|
|
54
|
+
constructor() {
|
|
55
|
+
this.questionHistory = [];
|
|
56
|
+
this.knowledgeBase = new Map();
|
|
57
|
+
this.askedQuestions = new Set();
|
|
58
|
+
this.userProfile = null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Set user profile for personalized questions
|
|
63
|
+
* @param {object} profile - User profile from ProfileManager
|
|
64
|
+
*/
|
|
65
|
+
setProfile(profile) {
|
|
66
|
+
this.userProfile = profile;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Record an answer to a question
|
|
71
|
+
* @param {string} questionId - Question ID
|
|
72
|
+
* @param {any} answer - The answer provided
|
|
73
|
+
* @param {object} metadata - Additional metadata
|
|
74
|
+
*/
|
|
75
|
+
recordAnswer(questionId, answer, metadata = {}) {
|
|
76
|
+
this.questionHistory.push({
|
|
77
|
+
questionId,
|
|
78
|
+
answer,
|
|
79
|
+
timestamp: Date.now(),
|
|
80
|
+
...metadata,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Update knowledge base
|
|
84
|
+
if (metadata.knowledgeKey) {
|
|
85
|
+
this.knowledgeBase.set(metadata.knowledgeKey, {
|
|
86
|
+
value: answer,
|
|
87
|
+
source: 'direct-answer',
|
|
88
|
+
confidence: 1.0,
|
|
89
|
+
timestamp: Date.now(),
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
this.askedQuestions.add(questionId);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Record inferred knowledge
|
|
98
|
+
* @param {string} key - Knowledge key
|
|
99
|
+
* @param {any} value - Inferred value
|
|
100
|
+
* @param {number} confidence - Confidence level (0-1)
|
|
101
|
+
*/
|
|
102
|
+
recordInference(key, value, confidence = 0.7) {
|
|
103
|
+
this.knowledgeBase.set(key, {
|
|
104
|
+
value,
|
|
105
|
+
source: 'inference',
|
|
106
|
+
confidence,
|
|
107
|
+
timestamp: Date.now(),
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Check if we already know something
|
|
113
|
+
* @param {string} key - Knowledge key
|
|
114
|
+
* @param {number} minConfidence - Minimum confidence required
|
|
115
|
+
* @returns {boolean}
|
|
116
|
+
*/
|
|
117
|
+
isKnown(key, minConfidence = 0.7) {
|
|
118
|
+
const knowledge = this.knowledgeBase.get(key);
|
|
119
|
+
if (!knowledge) return false;
|
|
120
|
+
return knowledge.confidence >= minConfidence;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Get known value
|
|
125
|
+
* @param {string} key - Knowledge key
|
|
126
|
+
* @returns {any} The known value or undefined
|
|
127
|
+
*/
|
|
128
|
+
getKnowledge(key) {
|
|
129
|
+
const knowledge = this.knowledgeBase.get(key);
|
|
130
|
+
return knowledge ? knowledge.value : undefined;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Check if a question should be asked
|
|
135
|
+
* @param {object} question - Question object
|
|
136
|
+
* @returns {boolean}
|
|
137
|
+
*/
|
|
138
|
+
shouldAsk(question) {
|
|
139
|
+
// Already asked this specific question
|
|
140
|
+
if (this.askedQuestions.has(question.id)) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Check skipIfKnown conditions
|
|
145
|
+
if (question.skipIfKnown && question.skipIfKnown.length > 0) {
|
|
146
|
+
const allKnown = question.skipIfKnown.every(key => this.isKnown(key));
|
|
147
|
+
if (allKnown) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Check custom ask condition
|
|
153
|
+
if (question.askCondition && typeof question.askCondition === 'function') {
|
|
154
|
+
return question.askCondition(this.knowledgeBase, this.userProfile);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Filter questions to only those that should be asked
|
|
162
|
+
* @param {Array} questions - Array of questions
|
|
163
|
+
* @returns {Array} Filtered questions
|
|
164
|
+
*/
|
|
165
|
+
filterQuestions(questions) {
|
|
166
|
+
return questions.filter(q => this.shouldAsk(q));
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Sort questions by priority
|
|
171
|
+
* @param {Array} questions - Array of questions
|
|
172
|
+
* @returns {Array} Sorted questions
|
|
173
|
+
*/
|
|
174
|
+
sortByPriority(questions) {
|
|
175
|
+
const priorityOrder = {
|
|
176
|
+
[PRIORITY.CRITICAL]: 0,
|
|
177
|
+
[PRIORITY.HIGH]: 1,
|
|
178
|
+
[PRIORITY.MEDIUM]: 2,
|
|
179
|
+
[PRIORITY.LOW]: 3,
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
return [...questions].sort((a, b) => {
|
|
183
|
+
// Use ?? instead of || because 0 is a valid priority value
|
|
184
|
+
const aOrder = priorityOrder[a.priority] ?? 2;
|
|
185
|
+
const bOrder = priorityOrder[b.priority] ?? 2;
|
|
186
|
+
return aOrder - bOrder;
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Get next questions to ask
|
|
192
|
+
* @param {Array} questions - Available questions
|
|
193
|
+
* @param {number} maxCount - Maximum number to return
|
|
194
|
+
* @returns {Array} Questions to ask
|
|
195
|
+
*/
|
|
196
|
+
getNextQuestions(questions, maxCount = 3) {
|
|
197
|
+
const filtered = this.filterQuestions(questions);
|
|
198
|
+
const sorted = this.sortByPriority(filtered);
|
|
199
|
+
return sorted.slice(0, maxCount);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Adapt question depth based on user expertise
|
|
204
|
+
* @param {object} question - Question object
|
|
205
|
+
* @param {string} domain - Domain area
|
|
206
|
+
* @returns {object} Adapted question
|
|
207
|
+
*/
|
|
208
|
+
adaptToExpertise(question, domain) {
|
|
209
|
+
if (!this.userProfile) return question;
|
|
210
|
+
|
|
211
|
+
const expertise = this.userProfile.domain?.expertiseAreas || [];
|
|
212
|
+
const isExpert = expertise.includes(domain);
|
|
213
|
+
|
|
214
|
+
if (isExpert) {
|
|
215
|
+
// Experts get more technical, less explanation
|
|
216
|
+
return {
|
|
217
|
+
...question,
|
|
218
|
+
text: question.expertText || question.text,
|
|
219
|
+
options: question.expertOptions || question.options,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Non-experts get more context
|
|
224
|
+
return {
|
|
225
|
+
...question,
|
|
226
|
+
text: question.beginnerText || question.text,
|
|
227
|
+
context: question.beginnerContext || question.context,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Generate follow-up questions based on answer
|
|
233
|
+
* @param {object} question - Original question
|
|
234
|
+
* @param {any} answer - The answer provided
|
|
235
|
+
* @returns {Array} Follow-up questions
|
|
236
|
+
*/
|
|
237
|
+
generateFollowUps(question, answer) {
|
|
238
|
+
if (!question.followUps || question.followUps.length === 0) {
|
|
239
|
+
return [];
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return question.followUps
|
|
243
|
+
.filter(fu => {
|
|
244
|
+
if (fu.condition && typeof fu.condition === 'function') {
|
|
245
|
+
return fu.condition(answer);
|
|
246
|
+
}
|
|
247
|
+
if (fu.triggerAnswer !== undefined) {
|
|
248
|
+
return fu.triggerAnswer === answer;
|
|
249
|
+
}
|
|
250
|
+
return true;
|
|
251
|
+
})
|
|
252
|
+
.map(fu => createQuestion(fu));
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Get question history summary
|
|
257
|
+
* @returns {object} Summary of asked questions
|
|
258
|
+
*/
|
|
259
|
+
getHistorySummary() {
|
|
260
|
+
const byType = {};
|
|
261
|
+
const byPriority = {};
|
|
262
|
+
|
|
263
|
+
for (const entry of this.questionHistory) {
|
|
264
|
+
const q = entry;
|
|
265
|
+
byType[q.type] = (byType[q.type] || 0) + 1;
|
|
266
|
+
byPriority[q.priority] = (byPriority[q.priority] || 0) + 1;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return {
|
|
270
|
+
totalAsked: this.questionHistory.length,
|
|
271
|
+
byType,
|
|
272
|
+
byPriority,
|
|
273
|
+
knowledgeCount: this.knowledgeBase.size,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Clear all state (for testing)
|
|
279
|
+
*/
|
|
280
|
+
clear() {
|
|
281
|
+
this.questionHistory = [];
|
|
282
|
+
this.knowledgeBase.clear();
|
|
283
|
+
this.askedQuestions.clear();
|
|
284
|
+
this.userProfile = null;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Export current knowledge base
|
|
289
|
+
* @returns {object} Knowledge base as plain object
|
|
290
|
+
*/
|
|
291
|
+
exportKnowledge() {
|
|
292
|
+
return Object.fromEntries(this.knowledgeBase);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Import knowledge base
|
|
297
|
+
* @param {object} knowledge - Knowledge to import
|
|
298
|
+
*/
|
|
299
|
+
importKnowledge(knowledge) {
|
|
300
|
+
for (const [key, value] of Object.entries(knowledge)) {
|
|
301
|
+
this.knowledgeBase.set(key, value);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
module.exports = {
|
|
307
|
+
QuestionEngine,
|
|
308
|
+
QUESTION_TYPES,
|
|
309
|
+
PRIORITY,
|
|
310
|
+
createQuestion,
|
|
311
|
+
};
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Question Templates
|
|
3
|
+
*
|
|
4
|
+
* Predefined question templates for common development scenarios.
|
|
5
|
+
* Used by the Adaptive Questioning Engine.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { QUESTION_TYPES, PRIORITY, createQuestion } = require('./question-engine');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Project initialization questions
|
|
12
|
+
*/
|
|
13
|
+
const PROJECT_QUESTIONS = [
|
|
14
|
+
createQuestion({
|
|
15
|
+
id: 'project-type',
|
|
16
|
+
type: QUESTION_TYPES.CLARIFYING,
|
|
17
|
+
priority: PRIORITY.CRITICAL,
|
|
18
|
+
text: 'What type of project is this?',
|
|
19
|
+
options: [
|
|
20
|
+
{ value: 'web-app', label: 'Web Application' },
|
|
21
|
+
{ value: 'api', label: 'API/Backend Service' },
|
|
22
|
+
{ value: 'cli', label: 'Command Line Tool' },
|
|
23
|
+
{ value: 'library', label: 'Library/Package' },
|
|
24
|
+
{ value: 'mobile', label: 'Mobile Application' },
|
|
25
|
+
{ value: 'other', label: 'Other' },
|
|
26
|
+
],
|
|
27
|
+
tags: ['project', 'initialization'],
|
|
28
|
+
skipIfKnown: ['project.type'],
|
|
29
|
+
}),
|
|
30
|
+
|
|
31
|
+
createQuestion({
|
|
32
|
+
id: 'project-scale',
|
|
33
|
+
type: QUESTION_TYPES.EXPLORATORY,
|
|
34
|
+
priority: PRIORITY.HIGH,
|
|
35
|
+
text: 'What is the expected scale of this project?',
|
|
36
|
+
options: [
|
|
37
|
+
{ value: 'prototype', label: 'Prototype/POC' },
|
|
38
|
+
{ value: 'small', label: 'Small (1-5 files)' },
|
|
39
|
+
{ value: 'medium', label: 'Medium (5-20 files)' },
|
|
40
|
+
{ value: 'large', label: 'Large (20+ files)' },
|
|
41
|
+
{ value: 'enterprise', label: 'Enterprise scale' },
|
|
42
|
+
],
|
|
43
|
+
tags: ['project', 'scope'],
|
|
44
|
+
skipIfKnown: ['project.scale'],
|
|
45
|
+
}),
|
|
46
|
+
|
|
47
|
+
createQuestion({
|
|
48
|
+
id: 'project-team',
|
|
49
|
+
type: QUESTION_TYPES.EXPLORATORY,
|
|
50
|
+
priority: PRIORITY.MEDIUM,
|
|
51
|
+
text: 'Who will be working on this project?',
|
|
52
|
+
options: [
|
|
53
|
+
{ value: 'solo', label: 'Just me' },
|
|
54
|
+
{ value: 'small-team', label: 'Small team (2-5)' },
|
|
55
|
+
{ value: 'large-team', label: 'Large team (5+)' },
|
|
56
|
+
{ value: 'open-source', label: 'Open source community' },
|
|
57
|
+
],
|
|
58
|
+
tags: ['project', 'team'],
|
|
59
|
+
skipIfKnown: ['project.team'],
|
|
60
|
+
}),
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Technical decision questions
|
|
65
|
+
*/
|
|
66
|
+
const TECHNICAL_QUESTIONS = [
|
|
67
|
+
createQuestion({
|
|
68
|
+
id: 'testing-approach',
|
|
69
|
+
type: QUESTION_TYPES.TECHNICAL,
|
|
70
|
+
priority: PRIORITY.HIGH,
|
|
71
|
+
text: 'What testing approach do you prefer?',
|
|
72
|
+
options: [
|
|
73
|
+
{ value: 'tdd', label: 'Test-Driven Development' },
|
|
74
|
+
{ value: 'bdd', label: 'Behavior-Driven Development' },
|
|
75
|
+
{ value: 'post-hoc', label: 'Write tests after implementation' },
|
|
76
|
+
{ value: 'minimal', label: 'Minimal testing' },
|
|
77
|
+
],
|
|
78
|
+
tags: ['testing', 'methodology'],
|
|
79
|
+
skipIfKnown: ['testing.approach'],
|
|
80
|
+
followUps: [
|
|
81
|
+
{
|
|
82
|
+
id: 'testing-coverage',
|
|
83
|
+
type: QUESTION_TYPES.PREFERENCE,
|
|
84
|
+
priority: PRIORITY.MEDIUM,
|
|
85
|
+
text: 'What level of test coverage do you target?',
|
|
86
|
+
options: [
|
|
87
|
+
{ value: 'critical', label: 'Critical paths only (50-60%)' },
|
|
88
|
+
{ value: 'standard', label: 'Standard coverage (70-80%)' },
|
|
89
|
+
{ value: 'comprehensive', label: 'Comprehensive (80%+)' },
|
|
90
|
+
],
|
|
91
|
+
triggerAnswer: value => value !== 'minimal',
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
}),
|
|
95
|
+
|
|
96
|
+
createQuestion({
|
|
97
|
+
id: 'error-handling',
|
|
98
|
+
type: QUESTION_TYPES.TECHNICAL,
|
|
99
|
+
priority: PRIORITY.MEDIUM,
|
|
100
|
+
text: 'How should errors be handled?',
|
|
101
|
+
options: [
|
|
102
|
+
{ value: 'exceptions', label: 'Throw exceptions' },
|
|
103
|
+
{ value: 'result-types', label: 'Return Result/Either types' },
|
|
104
|
+
{ value: 'error-codes', label: 'Return error codes' },
|
|
105
|
+
{ value: 'mixed', label: 'Mixed approach' },
|
|
106
|
+
],
|
|
107
|
+
tags: ['error-handling', 'patterns'],
|
|
108
|
+
skipIfKnown: ['error.handling'],
|
|
109
|
+
}),
|
|
110
|
+
|
|
111
|
+
createQuestion({
|
|
112
|
+
id: 'async-pattern',
|
|
113
|
+
type: QUESTION_TYPES.TECHNICAL,
|
|
114
|
+
priority: PRIORITY.MEDIUM,
|
|
115
|
+
text: 'Preferred async pattern?',
|
|
116
|
+
options: [
|
|
117
|
+
{ value: 'async-await', label: 'async/await' },
|
|
118
|
+
{ value: 'promises', label: 'Promises (.then/.catch)' },
|
|
119
|
+
{ value: 'callbacks', label: 'Callbacks' },
|
|
120
|
+
{ value: 'observables', label: 'Observables/RxJS' },
|
|
121
|
+
],
|
|
122
|
+
tags: ['async', 'patterns'],
|
|
123
|
+
skipIfKnown: ['async.pattern'],
|
|
124
|
+
}),
|
|
125
|
+
];
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Preference questions
|
|
129
|
+
*/
|
|
130
|
+
const PREFERENCE_QUESTIONS = [
|
|
131
|
+
createQuestion({
|
|
132
|
+
id: 'code-style',
|
|
133
|
+
type: QUESTION_TYPES.PREFERENCE,
|
|
134
|
+
priority: PRIORITY.MEDIUM,
|
|
135
|
+
text: 'What code style do you prefer?',
|
|
136
|
+
options: [
|
|
137
|
+
{ value: 'compact', label: 'Compact (fewer lines)' },
|
|
138
|
+
{ value: 'verbose', label: 'Verbose (explicit and clear)' },
|
|
139
|
+
{ value: 'balanced', label: 'Balanced' },
|
|
140
|
+
],
|
|
141
|
+
tags: ['style', 'preferences'],
|
|
142
|
+
skipIfKnown: ['style.code'],
|
|
143
|
+
}),
|
|
144
|
+
|
|
145
|
+
createQuestion({
|
|
146
|
+
id: 'documentation-level',
|
|
147
|
+
type: QUESTION_TYPES.PREFERENCE,
|
|
148
|
+
priority: PRIORITY.LOW,
|
|
149
|
+
text: 'How much documentation do you want?',
|
|
150
|
+
options: [
|
|
151
|
+
{ value: 'minimal', label: 'Minimal (only complex parts)' },
|
|
152
|
+
{ value: 'standard', label: 'Standard (public APIs)' },
|
|
153
|
+
{ value: 'comprehensive', label: 'Comprehensive (everything)' },
|
|
154
|
+
],
|
|
155
|
+
tags: ['documentation', 'preferences'],
|
|
156
|
+
skipIfKnown: ['documentation.level'],
|
|
157
|
+
}),
|
|
158
|
+
|
|
159
|
+
createQuestion({
|
|
160
|
+
id: 'naming-convention',
|
|
161
|
+
type: QUESTION_TYPES.PREFERENCE,
|
|
162
|
+
priority: PRIORITY.LOW,
|
|
163
|
+
text: 'Preferred naming convention for functions?',
|
|
164
|
+
options: [
|
|
165
|
+
{ value: 'camelCase', label: 'camelCase' },
|
|
166
|
+
{ value: 'snake_case', label: 'snake_case' },
|
|
167
|
+
{ value: 'PascalCase', label: 'PascalCase' },
|
|
168
|
+
],
|
|
169
|
+
tags: ['naming', 'preferences'],
|
|
170
|
+
skipIfKnown: ['naming.functions'],
|
|
171
|
+
}),
|
|
172
|
+
];
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Constraint questions
|
|
176
|
+
*/
|
|
177
|
+
const CONSTRAINT_QUESTIONS = [
|
|
178
|
+
createQuestion({
|
|
179
|
+
id: 'browser-support',
|
|
180
|
+
type: QUESTION_TYPES.CONSTRAINT,
|
|
181
|
+
priority: PRIORITY.HIGH,
|
|
182
|
+
text: 'What browsers need to be supported?',
|
|
183
|
+
options: [
|
|
184
|
+
{ value: 'modern', label: 'Modern browsers only' },
|
|
185
|
+
{ value: 'ie11', label: 'Including IE11' },
|
|
186
|
+
{ value: 'mobile', label: 'Mobile browsers focus' },
|
|
187
|
+
{ value: 'all', label: 'All browsers' },
|
|
188
|
+
],
|
|
189
|
+
tags: ['constraints', 'browser'],
|
|
190
|
+
skipIfKnown: ['constraints.browsers'],
|
|
191
|
+
askCondition: (kb) => kb.get('project.type')?.value === 'web-app',
|
|
192
|
+
}),
|
|
193
|
+
|
|
194
|
+
createQuestion({
|
|
195
|
+
id: 'node-version',
|
|
196
|
+
type: QUESTION_TYPES.CONSTRAINT,
|
|
197
|
+
priority: PRIORITY.MEDIUM,
|
|
198
|
+
text: 'Minimum Node.js version to support?',
|
|
199
|
+
options: [
|
|
200
|
+
{ value: '16', label: 'Node 16 LTS' },
|
|
201
|
+
{ value: '18', label: 'Node 18 LTS' },
|
|
202
|
+
{ value: '20', label: 'Node 20 LTS' },
|
|
203
|
+
{ value: '22', label: 'Node 22 (Current)' },
|
|
204
|
+
],
|
|
205
|
+
tags: ['constraints', 'node'],
|
|
206
|
+
skipIfKnown: ['constraints.node'],
|
|
207
|
+
}),
|
|
208
|
+
|
|
209
|
+
createQuestion({
|
|
210
|
+
id: 'dependencies',
|
|
211
|
+
type: QUESTION_TYPES.CONSTRAINT,
|
|
212
|
+
priority: PRIORITY.MEDIUM,
|
|
213
|
+
text: 'What is your dependency philosophy?',
|
|
214
|
+
options: [
|
|
215
|
+
{ value: 'minimal', label: 'Minimize dependencies' },
|
|
216
|
+
{ value: 'pragmatic', label: 'Use well-maintained packages' },
|
|
217
|
+
{ value: 'full', label: 'Use packages freely' },
|
|
218
|
+
],
|
|
219
|
+
tags: ['constraints', 'dependencies'],
|
|
220
|
+
skipIfKnown: ['constraints.dependencies'],
|
|
221
|
+
}),
|
|
222
|
+
];
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Phase-specific questions
|
|
226
|
+
*/
|
|
227
|
+
const PHASE_QUESTIONS = [
|
|
228
|
+
createQuestion({
|
|
229
|
+
id: 'phase-priority',
|
|
230
|
+
type: QUESTION_TYPES.CLARIFYING,
|
|
231
|
+
priority: PRIORITY.HIGH,
|
|
232
|
+
text: 'What is the priority for this phase?',
|
|
233
|
+
options: [
|
|
234
|
+
{ value: 'speed', label: 'Speed (ship fast)' },
|
|
235
|
+
{ value: 'quality', label: 'Quality (thorough testing)' },
|
|
236
|
+
{ value: 'balanced', label: 'Balanced' },
|
|
237
|
+
],
|
|
238
|
+
tags: ['phase', 'priority'],
|
|
239
|
+
}),
|
|
240
|
+
|
|
241
|
+
createQuestion({
|
|
242
|
+
id: 'phase-blockers',
|
|
243
|
+
type: QUESTION_TYPES.EXPLORATORY,
|
|
244
|
+
priority: PRIORITY.HIGH,
|
|
245
|
+
text: 'Are there any known blockers or concerns for this phase?',
|
|
246
|
+
options: [
|
|
247
|
+
{ value: 'none', label: 'No known blockers' },
|
|
248
|
+
{ value: 'technical', label: 'Technical uncertainty' },
|
|
249
|
+
{ value: 'dependencies', label: 'Waiting on dependencies' },
|
|
250
|
+
{ value: 'requirements', label: 'Requirements unclear' },
|
|
251
|
+
],
|
|
252
|
+
tags: ['phase', 'blockers'],
|
|
253
|
+
}),
|
|
254
|
+
];
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Get all question templates
|
|
258
|
+
* @returns {object} Categorized question templates
|
|
259
|
+
*/
|
|
260
|
+
function getAllTemplates() {
|
|
261
|
+
return {
|
|
262
|
+
project: PROJECT_QUESTIONS,
|
|
263
|
+
technical: TECHNICAL_QUESTIONS,
|
|
264
|
+
preference: PREFERENCE_QUESTIONS,
|
|
265
|
+
constraint: CONSTRAINT_QUESTIONS,
|
|
266
|
+
phase: PHASE_QUESTIONS,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Get questions by tags
|
|
272
|
+
* @param {string[]} tags - Tags to filter by
|
|
273
|
+
* @returns {Array} Matching questions
|
|
274
|
+
*/
|
|
275
|
+
function getByTags(tags) {
|
|
276
|
+
const allQuestions = [
|
|
277
|
+
...PROJECT_QUESTIONS,
|
|
278
|
+
...TECHNICAL_QUESTIONS,
|
|
279
|
+
...PREFERENCE_QUESTIONS,
|
|
280
|
+
...CONSTRAINT_QUESTIONS,
|
|
281
|
+
...PHASE_QUESTIONS,
|
|
282
|
+
];
|
|
283
|
+
|
|
284
|
+
return allQuestions.filter(q =>
|
|
285
|
+
q.tags.some(t => tags.includes(t)),
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Get questions by type
|
|
291
|
+
* @param {string} type - Question type
|
|
292
|
+
* @returns {Array} Matching questions
|
|
293
|
+
*/
|
|
294
|
+
function getByType(type) {
|
|
295
|
+
const allQuestions = [
|
|
296
|
+
...PROJECT_QUESTIONS,
|
|
297
|
+
...TECHNICAL_QUESTIONS,
|
|
298
|
+
...PREFERENCE_QUESTIONS,
|
|
299
|
+
...CONSTRAINT_QUESTIONS,
|
|
300
|
+
...PHASE_QUESTIONS,
|
|
301
|
+
];
|
|
302
|
+
|
|
303
|
+
return allQuestions.filter(q => q.type === type);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
module.exports = {
|
|
307
|
+
PROJECT_QUESTIONS,
|
|
308
|
+
TECHNICAL_QUESTIONS,
|
|
309
|
+
PREFERENCE_QUESTIONS,
|
|
310
|
+
CONSTRAINT_QUESTIONS,
|
|
311
|
+
PHASE_QUESTIONS,
|
|
312
|
+
getAllTemplates,
|
|
313
|
+
getByTags,
|
|
314
|
+
getByType,
|
|
315
|
+
};
|