hardness 1.0.0 → 1.1.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/AGENTS.md +11 -0
- package/CHANGELOG.md +36 -0
- package/README.md +62 -15
- package/node_modules/@hardness/analyzers/package.json +1 -1
- package/node_modules/@hardness/core/dist/common/paths.js +2 -2
- package/node_modules/@hardness/core/dist/common/paths.js.map +1 -1
- package/node_modules/@hardness/core/package.json +1 -1
- package/node_modules/@hardness/prompts/package.json +1 -1
- package/package.json +1 -1
- package/packages/analyzers/package.json +1 -1
- package/packages/cli/dist/commands/discover.js +47 -6
- package/packages/cli/dist/commands/discover.js.map +1 -1
- package/packages/cli/dist/commands/plan.js +39 -6
- package/packages/cli/dist/commands/plan.js.map +1 -1
- package/packages/cli/dist/commands/spec.js +34 -6
- package/packages/cli/dist/commands/spec.js.map +1 -1
- package/packages/cli/dist/dispatcher.d.ts +2 -0
- package/packages/cli/dist/dispatcher.js +63 -62
- package/packages/cli/dist/dispatcher.js.map +1 -1
- package/packages/cli/dist/generators/prd-generator.d.ts +14 -0
- package/packages/cli/dist/generators/prd-generator.js +164 -0
- package/packages/cli/dist/generators/prd-generator.js.map +1 -0
- package/packages/cli/dist/generators/spec-generator.d.ts +35 -0
- package/packages/cli/dist/generators/spec-generator.js +245 -0
- package/packages/cli/dist/generators/spec-generator.js.map +1 -0
- package/packages/cli/dist/generators/sprint-generator.d.ts +51 -0
- package/packages/cli/dist/generators/sprint-generator.js +162 -0
- package/packages/cli/dist/generators/sprint-generator.js.map +1 -0
- package/packages/cli/dist/index.js +1 -1
- package/packages/cli/dist/interview/evaluator-prompt.d.ts +9 -0
- package/packages/cli/dist/interview/evaluator-prompt.js +192 -0
- package/packages/cli/dist/interview/evaluator-prompt.js.map +1 -0
- package/packages/cli/dist/interview/evaluator.d.ts +46 -0
- package/packages/cli/dist/interview/evaluator.js +142 -0
- package/packages/cli/dist/interview/evaluator.js.map +1 -0
- package/packages/cli/dist/interview/questions.d.ts +29 -0
- package/packages/cli/dist/interview/questions.js +642 -0
- package/packages/cli/dist/interview/questions.js.map +1 -0
- package/packages/cli/dist/interview/runner.d.ts +14 -0
- package/packages/cli/dist/interview/runner.js +327 -0
- package/packages/cli/dist/interview/runner.js.map +1 -0
- package/packages/cli/dist/interview/suggestions.d.ts +6 -0
- package/packages/cli/dist/interview/suggestions.js +230 -0
- package/packages/cli/dist/interview/suggestions.js.map +1 -0
- package/packages/cli/dist/interview/types.d.ts +46 -0
- package/packages/cli/dist/interview/types.js +50 -0
- package/packages/cli/dist/interview/types.js.map +1 -0
- package/packages/cli/package.json +1 -1
- package/packages/core/dist/common/paths.js +2 -2
- package/packages/core/dist/common/paths.js.map +1 -1
- package/packages/core/package.json +1 -1
- package/packages/prompts/package.json +1 -1
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import readline from 'readline';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import pc from 'picocolors';
|
|
5
|
+
import { getProjectRoot } from '@hardness/core';
|
|
6
|
+
import { detectStack } from './types.js';
|
|
7
|
+
import { createSuggestionEngine } from './suggestions.js';
|
|
8
|
+
import { QUESTIONS, getPromptForLevel, getChoicesForLevel } from './questions.js';
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Constants
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
const PHASE_ORDER = [
|
|
13
|
+
'opening', 'vision', 'people', 'features', 'constraints', 'boundaries', 'review',
|
|
14
|
+
];
|
|
15
|
+
const PHASE_LABELS = {
|
|
16
|
+
opening: 'Phase 0 — Opening',
|
|
17
|
+
vision: 'Phase 1 — Vision',
|
|
18
|
+
people: 'Phase 2 — People',
|
|
19
|
+
features: 'Phase 3 — Features',
|
|
20
|
+
constraints: 'Phase 4 — Constraints',
|
|
21
|
+
boundaries: 'Phase 5 — Boundaries',
|
|
22
|
+
review: 'Phase 6 — Review',
|
|
23
|
+
};
|
|
24
|
+
const PROJECT_TYPE_CHOICES = {
|
|
25
|
+
'1': 'web-app',
|
|
26
|
+
'2': 'api',
|
|
27
|
+
'3': 'cli',
|
|
28
|
+
'4': 'library',
|
|
29
|
+
'5': 'desktop',
|
|
30
|
+
'6': 'mobile',
|
|
31
|
+
'7': 'other',
|
|
32
|
+
'web-app': 'web-app',
|
|
33
|
+
api: 'api',
|
|
34
|
+
cli: 'cli',
|
|
35
|
+
library: 'library',
|
|
36
|
+
desktop: 'desktop',
|
|
37
|
+
mobile: 'mobile',
|
|
38
|
+
other: 'other',
|
|
39
|
+
// Beginner-friendly choice mappings
|
|
40
|
+
'a website or web system that people use in the browser': 'web-app',
|
|
41
|
+
'a behind-the-scenes service that other programs talk to': 'api',
|
|
42
|
+
'a tool you run from the command line (terminal)': 'cli',
|
|
43
|
+
'a reusable piece of code that other developers can use': 'library',
|
|
44
|
+
'an app that runs on a computer (windows, mac, linux)': 'desktop',
|
|
45
|
+
'a phone app (ios, android)': 'mobile',
|
|
46
|
+
'something else': 'other',
|
|
47
|
+
// Intermediate mappings
|
|
48
|
+
'web application (frontend + backend)': 'web-app',
|
|
49
|
+
'api / backend service': 'api',
|
|
50
|
+
'cli tool': 'cli',
|
|
51
|
+
'library / sdk': 'library',
|
|
52
|
+
'desktop application': 'desktop',
|
|
53
|
+
'mobile application': 'mobile',
|
|
54
|
+
};
|
|
55
|
+
const USER_LEVEL_CHOICES = {
|
|
56
|
+
'1': 'beginner',
|
|
57
|
+
'2': 'intermediate',
|
|
58
|
+
'3': 'advanced',
|
|
59
|
+
beginner: 'beginner',
|
|
60
|
+
intermediate: 'intermediate',
|
|
61
|
+
advanced: 'advanced',
|
|
62
|
+
};
|
|
63
|
+
const MAX_EXTRA_QUESTIONS_PER_PHASE = 3;
|
|
64
|
+
const MIN_EVALUATION_SCORE = 9;
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
// Line queue — collects all input lines upfront so we never block
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
class LineQueue {
|
|
69
|
+
lines = [];
|
|
70
|
+
resolvers = [];
|
|
71
|
+
closed = false;
|
|
72
|
+
push(line) {
|
|
73
|
+
if (this.resolvers.length > 0) {
|
|
74
|
+
const resolve = this.resolvers.shift();
|
|
75
|
+
resolve(line);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
this.lines.push(line);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
close() {
|
|
82
|
+
this.closed = true;
|
|
83
|
+
while (this.resolvers.length > 0) {
|
|
84
|
+
const resolve = this.resolvers.shift();
|
|
85
|
+
resolve('');
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
next() {
|
|
89
|
+
if (this.lines.length > 0) {
|
|
90
|
+
return Promise.resolve(this.lines.shift());
|
|
91
|
+
}
|
|
92
|
+
if (this.closed) {
|
|
93
|
+
return Promise.resolve('');
|
|
94
|
+
}
|
|
95
|
+
return new Promise((resolve) => {
|
|
96
|
+
this.resolvers.push(resolve);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
// Helpers
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
function formatSuggestion(value) {
|
|
104
|
+
return Array.isArray(value) ? value.join(', ') : value;
|
|
105
|
+
}
|
|
106
|
+
function savePartialState(state, questionIndex, root) {
|
|
107
|
+
const hardnessDir = path.join(root, '.hardness');
|
|
108
|
+
try {
|
|
109
|
+
if (!fs.existsSync(hardnessDir)) {
|
|
110
|
+
fs.mkdirSync(hardnessDir, { recursive: true });
|
|
111
|
+
}
|
|
112
|
+
const sessionPath = path.join(hardnessDir, 'discover-session.json');
|
|
113
|
+
fs.writeFileSync(sessionPath, JSON.stringify({ questionIndex, state }, null, 2), 'utf-8');
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
// best-effort
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function detectLocale() {
|
|
120
|
+
try {
|
|
121
|
+
return Intl.DateTimeFormat().resolvedOptions().locale;
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return 'en-US';
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
export async function runInterview(options = {}) {
|
|
128
|
+
const root = options.root ?? getProjectRoot();
|
|
129
|
+
const detectedStack = detectStack(root);
|
|
130
|
+
const locale = options.locale ?? detectLocale();
|
|
131
|
+
const state = {
|
|
132
|
+
phase: 'opening',
|
|
133
|
+
answers: {},
|
|
134
|
+
detectedStack,
|
|
135
|
+
projectType: 'other',
|
|
136
|
+
userLevel: 'beginner',
|
|
137
|
+
locale,
|
|
138
|
+
};
|
|
139
|
+
const engine = createSuggestionEngine();
|
|
140
|
+
const evaluator = options.evaluator ?? null;
|
|
141
|
+
// Build a line queue from the rl interface
|
|
142
|
+
const queue = new LineQueue();
|
|
143
|
+
const rl = options.rl ??
|
|
144
|
+
readline.createInterface({
|
|
145
|
+
input: process.stdin,
|
|
146
|
+
output: undefined,
|
|
147
|
+
terminal: false,
|
|
148
|
+
});
|
|
149
|
+
rl.on('line', (line) => queue.push(line));
|
|
150
|
+
rl.on('close', () => queue.close());
|
|
151
|
+
let questionIndex = 0;
|
|
152
|
+
// Ctrl+C handler
|
|
153
|
+
rl.on('SIGINT', () => {
|
|
154
|
+
process.stdout.write('\n');
|
|
155
|
+
process.stdout.write(pc.yellow('Interview interrupted. Saving partial session...\n'));
|
|
156
|
+
savePartialState(state, questionIndex, root);
|
|
157
|
+
process.stdout.write(pc.dim('Session saved to .hardness/discover-session.json\n'));
|
|
158
|
+
process.stdout.write(pc.dim('Run `hardness discover` again to resume.\n'));
|
|
159
|
+
rl.close();
|
|
160
|
+
process.exit(0);
|
|
161
|
+
});
|
|
162
|
+
// Translate questions if locale is not English and evaluator is available
|
|
163
|
+
let translationMap = null;
|
|
164
|
+
if (evaluator && !locale.startsWith('en')) {
|
|
165
|
+
try {
|
|
166
|
+
const questionsToTranslate = QUESTIONS
|
|
167
|
+
.filter(q => q.type !== 'action')
|
|
168
|
+
.map(q => ({
|
|
169
|
+
id: q.id,
|
|
170
|
+
prompt: getPromptForLevel(q, state.userLevel),
|
|
171
|
+
choices: getChoicesForLevel(q, state.userLevel),
|
|
172
|
+
}));
|
|
173
|
+
const translated = await evaluator.translateQuestions(locale, questionsToTranslate);
|
|
174
|
+
translationMap = new Map(translated.map(t => [t.id, t]));
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
// Translation failed — fall back to English
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// Helper to get the display prompt for a question
|
|
181
|
+
function getDisplayPrompt(question) {
|
|
182
|
+
if (translationMap?.has(question.id)) {
|
|
183
|
+
return translationMap.get(question.id).prompt;
|
|
184
|
+
}
|
|
185
|
+
return getPromptForLevel(question, state.userLevel);
|
|
186
|
+
}
|
|
187
|
+
function getDisplayChoices(question) {
|
|
188
|
+
if (translationMap?.has(question.id)) {
|
|
189
|
+
return translationMap.get(question.id).choices;
|
|
190
|
+
}
|
|
191
|
+
return getChoicesForLevel(question, state.userLevel);
|
|
192
|
+
}
|
|
193
|
+
// Ask a single question and collect the answer
|
|
194
|
+
async function askQuestion(question) {
|
|
195
|
+
const prompt = getDisplayPrompt(question);
|
|
196
|
+
const choices = getDisplayChoices(question);
|
|
197
|
+
process.stdout.write(`\n${pc.white(prompt)}\n`);
|
|
198
|
+
if (question.type === 'choice' && choices) {
|
|
199
|
+
for (const c of choices) {
|
|
200
|
+
process.stdout.write(` ${pc.dim(c)}\n`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
process.stdout.write(pc.dim('(? for suggestion, Enter to use default)\n'));
|
|
204
|
+
process.stdout.write(`${pc.cyan('>')} `);
|
|
205
|
+
if (question.type === 'multiline') {
|
|
206
|
+
const collected = [];
|
|
207
|
+
for (;;) {
|
|
208
|
+
const line = await queue.next();
|
|
209
|
+
if (line.trim() === '')
|
|
210
|
+
break;
|
|
211
|
+
collected.push(line);
|
|
212
|
+
}
|
|
213
|
+
if (collected.length === 0) {
|
|
214
|
+
const suggestion = engine.suggest(question.suggestionId, state);
|
|
215
|
+
state.answers[question.id] = Array.isArray(suggestion) ? suggestion : [suggestion];
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
state.answers[question.id] = collected;
|
|
219
|
+
}
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
// Single-line questions
|
|
223
|
+
const rawInput = await queue.next();
|
|
224
|
+
const trimmed = rawInput.trim();
|
|
225
|
+
if (trimmed === '?') {
|
|
226
|
+
const suggestion = engine.suggest(question.suggestionId, state);
|
|
227
|
+
const formatted = formatSuggestion(suggestion);
|
|
228
|
+
process.stdout.write(`${pc.yellow('Suggestion:')} ${formatted}\n`);
|
|
229
|
+
process.stdout.write(`${pc.cyan('>')} `);
|
|
230
|
+
const next = await queue.next();
|
|
231
|
+
state.answers[question.id] = next.trim() !== '' ? next.trim() : formatted;
|
|
232
|
+
}
|
|
233
|
+
else if (trimmed === '') {
|
|
234
|
+
const suggestion = engine.suggest(question.suggestionId, state);
|
|
235
|
+
const formatted = formatSuggestion(suggestion);
|
|
236
|
+
process.stdout.write(`${pc.dim(`Using suggestion: ${formatted}`)}\n`);
|
|
237
|
+
state.answers[question.id] = formatted;
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
state.answers[question.id] = trimmed;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// Iterate through all phases
|
|
244
|
+
for (const phase of PHASE_ORDER) {
|
|
245
|
+
state.phase = phase;
|
|
246
|
+
// Print phase header
|
|
247
|
+
process.stdout.write(`\n${pc.bold(pc.blue(PHASE_LABELS[phase]))}\n`);
|
|
248
|
+
process.stdout.write(`${pc.dim('─'.repeat(40))}\n`);
|
|
249
|
+
// Get base questions for this phase (exclude actions)
|
|
250
|
+
const phaseQuestions = QUESTIONS.filter(q => q.phase === phase && q.type !== 'action');
|
|
251
|
+
// Ask base questions
|
|
252
|
+
for (const question of phaseQuestions) {
|
|
253
|
+
questionIndex++;
|
|
254
|
+
await askQuestion(question);
|
|
255
|
+
// Resolve user level after q0.2
|
|
256
|
+
if (question.id === 'q0.2') {
|
|
257
|
+
const raw = state.answers['q0.2'];
|
|
258
|
+
const key = raw.split(/[—\-]/)[0].trim().toLowerCase();
|
|
259
|
+
state.userLevel = USER_LEVEL_CHOICES[key] ?? 'beginner';
|
|
260
|
+
// Re-translate questions if needed (now we know the user level)
|
|
261
|
+
if (evaluator && translationMap && !locale.startsWith('en')) {
|
|
262
|
+
try {
|
|
263
|
+
const questionsToTranslate = QUESTIONS
|
|
264
|
+
.filter(q => q.type !== 'action')
|
|
265
|
+
.map(q => ({
|
|
266
|
+
id: q.id,
|
|
267
|
+
prompt: getPromptForLevel(q, state.userLevel),
|
|
268
|
+
choices: getChoicesForLevel(q, state.userLevel),
|
|
269
|
+
}));
|
|
270
|
+
const translated = await evaluator.translateQuestions(locale, questionsToTranslate);
|
|
271
|
+
translationMap = new Map(translated.map(t => [t.id, t]));
|
|
272
|
+
}
|
|
273
|
+
catch {
|
|
274
|
+
// Fall back to existing translations
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
// Resolve projectType after q1.4
|
|
279
|
+
if (question.id === 'q1.4') {
|
|
280
|
+
const raw = state.answers['q1.4'];
|
|
281
|
+
const key = raw.split(/[\s—]/)[0].trim().toLowerCase();
|
|
282
|
+
state.projectType = PROJECT_TYPE_CHOICES[key] ?? 'other';
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
// Evaluate phase completion via LLM (invisible to user)
|
|
286
|
+
// Skip evaluation for opening and review phases
|
|
287
|
+
if (evaluator && phase !== 'opening' && phase !== 'review') {
|
|
288
|
+
let extraAsked = 0;
|
|
289
|
+
for (let round = 0; round < MAX_EXTRA_QUESTIONS_PER_PHASE; round++) {
|
|
290
|
+
try {
|
|
291
|
+
const evaluation = await evaluator.evaluatePhase(phase, state, QUESTIONS);
|
|
292
|
+
if (evaluation.score >= MIN_EVALUATION_SCORE) {
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
// Ask follow-up questions
|
|
296
|
+
const followUps = evaluation.followUpQuestions.slice(0, MAX_EXTRA_QUESTIONS_PER_PHASE - extraAsked);
|
|
297
|
+
if (followUps.length === 0)
|
|
298
|
+
break;
|
|
299
|
+
for (const fq of followUps) {
|
|
300
|
+
if (extraAsked >= MAX_EXTRA_QUESTIONS_PER_PHASE)
|
|
301
|
+
break;
|
|
302
|
+
const dynamicQuestion = {
|
|
303
|
+
id: fq.id,
|
|
304
|
+
phase,
|
|
305
|
+
prompt: fq.prompt,
|
|
306
|
+
type: fq.type,
|
|
307
|
+
choices: fq.choices,
|
|
308
|
+
suggestionId: fq.id,
|
|
309
|
+
};
|
|
310
|
+
questionIndex++;
|
|
311
|
+
await askQuestion(dynamicQuestion);
|
|
312
|
+
extraAsked++;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
catch {
|
|
316
|
+
// Evaluation failed — continue without it
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
if (!options.rl) {
|
|
323
|
+
rl.close();
|
|
324
|
+
}
|
|
325
|
+
return state;
|
|
326
|
+
}
|
|
327
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/interview/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { InterviewState, SuggestionEngine } from './types.js';
|
|
2
|
+
export declare class StaticSuggestionEngine implements SuggestionEngine {
|
|
3
|
+
suggest(questionId: string, state: InterviewState): string | string[];
|
|
4
|
+
}
|
|
5
|
+
/** Convenience factory */
|
|
6
|
+
export declare function createSuggestionEngine(): SuggestionEngine;
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Static suggestion table: (projectType) → (questionId → suggestion)
|
|
3
|
+
// Stack-aware refinements are applied inside suggest() when needed.
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
const SUGGESTIONS = {
|
|
6
|
+
'web-app': {
|
|
7
|
+
'q0.1': 'I want to build a web application that helps users manage their tasks and projects through an intuitive browser-based interface.',
|
|
8
|
+
'q0.2': 'beginner',
|
|
9
|
+
'q1.1': 'my-web-app',
|
|
10
|
+
'q1.2': 'A web application that solves a specific business problem.',
|
|
11
|
+
'q1.3': 'Automates web workflows for end users, reducing manual effort and errors.',
|
|
12
|
+
'q1.4': 'web-app',
|
|
13
|
+
'q2.1': 'end user',
|
|
14
|
+
'q2.2': 'DevOps engineer, QA tester, product manager',
|
|
15
|
+
'q2.3': '1',
|
|
16
|
+
'q3.1': ['User authentication', 'Dashboard', 'Data visualization', 'REST API', 'Admin panel'],
|
|
17
|
+
'q3.2': '1',
|
|
18
|
+
'q3.3': 'The feature works end-to-end without errors and is covered by tests.',
|
|
19
|
+
'q4.1': '1',
|
|
20
|
+
'q4.2': 'React with Vite',
|
|
21
|
+
'q4.3': 'PostgreSQL',
|
|
22
|
+
'q4.4': 'Email/password + optional OAuth',
|
|
23
|
+
'q4.5': '1',
|
|
24
|
+
'q4.6': 'Docker + VPS',
|
|
25
|
+
'q4.7': 'API responses under 200ms p95. Static assets under 100ms.',
|
|
26
|
+
'q4.8': 'Logging + metrics',
|
|
27
|
+
'q5.1': ['Mobile native app', 'Internationalization (i18n)', 'Custom theme builder', 'Billing system'],
|
|
28
|
+
'q5.2': 'Users have Node.js 20+ installed. Network is available for external dependencies.',
|
|
29
|
+
'q5.3': 'Scope may grow — strict sprint discipline is required. External API rate limits may apply.',
|
|
30
|
+
'q6.1': '1',
|
|
31
|
+
},
|
|
32
|
+
api: {
|
|
33
|
+
'q0.1': 'I want to build an API service that exposes business data and logic for other applications to consume.',
|
|
34
|
+
'q0.2': 'intermediate',
|
|
35
|
+
'q1.1': 'my-api',
|
|
36
|
+
'q1.2': 'A REST API service that exposes data and business logic over HTTP.',
|
|
37
|
+
'q1.3': 'Provides a reliable and secure backend API for client applications.',
|
|
38
|
+
'q1.4': 'api',
|
|
39
|
+
'q2.1': 'backend developer',
|
|
40
|
+
'q2.2': 'DevOps engineer, QA engineer',
|
|
41
|
+
'q2.3': '3',
|
|
42
|
+
'q3.1': ['CRUD endpoints', 'Authentication', 'Rate limiting', 'Pagination', 'Error handling'],
|
|
43
|
+
'q3.2': '1',
|
|
44
|
+
'q3.3': 'The feature works end-to-end without errors and is covered by tests.',
|
|
45
|
+
'q4.1': '1',
|
|
46
|
+
'q4.2': 'No frontend (API only)',
|
|
47
|
+
'q4.3': 'PostgreSQL',
|
|
48
|
+
'q4.4': 'API keys / tokens',
|
|
49
|
+
'q4.5': '1',
|
|
50
|
+
'q4.6': 'Docker container',
|
|
51
|
+
'q4.7': 'API responses under 200ms p95.',
|
|
52
|
+
'q4.8': 'Logging + metrics',
|
|
53
|
+
'q5.1': ['GraphQL gateway', 'WebSocket streaming', 'Admin UI'],
|
|
54
|
+
'q5.2': 'Clients must supply a valid API key in each request.',
|
|
55
|
+
'q5.3': 'Scope may grow — strict sprint discipline is required. Third-party rate limits may apply.',
|
|
56
|
+
'q6.1': '1',
|
|
57
|
+
},
|
|
58
|
+
cli: {
|
|
59
|
+
'q0.1': 'I want to build a command-line tool that automates repetitive developer tasks.',
|
|
60
|
+
'q0.2': 'advanced',
|
|
61
|
+
'q1.1': 'my-cli',
|
|
62
|
+
'q1.2': 'A command-line tool that automates developer workflows.',
|
|
63
|
+
'q1.3': 'Eliminates repetitive manual tasks for developers by providing a reliable CLI.',
|
|
64
|
+
'q1.4': 'cli',
|
|
65
|
+
'q2.1': 'developer',
|
|
66
|
+
'q2.2': 'DevOps engineer, power user',
|
|
67
|
+
'q2.3': '3',
|
|
68
|
+
'q3.1': ['Init command', 'Config management', 'Run/execute', 'Output formatting', 'Help system'],
|
|
69
|
+
'q3.2': '1',
|
|
70
|
+
'q3.3': 'The feature works end-to-end without errors and is covered by tests.',
|
|
71
|
+
'q4.1': '1',
|
|
72
|
+
'q4.2': 'No frontend (API only)',
|
|
73
|
+
'q4.3': 'None needed',
|
|
74
|
+
'q4.4': 'API keys / tokens',
|
|
75
|
+
'q4.5': '1',
|
|
76
|
+
'q4.6': 'Distributed via npm (npx / global install)',
|
|
77
|
+
'q4.7': 'Commands complete in under 2 seconds for typical workloads.',
|
|
78
|
+
'q4.8': 'Logging only (console/file)',
|
|
79
|
+
'q5.1': ['GUI version', 'Auto-update mechanism', 'Plugin system'],
|
|
80
|
+
'q5.2': 'Users have the required runtime installed. No network required for core commands.',
|
|
81
|
+
'q5.3': 'Scope may grow — strict sprint discipline is required.',
|
|
82
|
+
'q6.1': '1',
|
|
83
|
+
},
|
|
84
|
+
library: {
|
|
85
|
+
'q0.1': 'I want to build a reusable library that other developers can use in their projects.',
|
|
86
|
+
'q0.2': 'advanced',
|
|
87
|
+
'q1.1': 'my-library',
|
|
88
|
+
'q1.2': 'A reusable library / SDK for developers.',
|
|
89
|
+
'q1.3': 'Provides well-tested building blocks that other projects can depend on.',
|
|
90
|
+
'q1.4': 'library',
|
|
91
|
+
'q2.1': 'developer',
|
|
92
|
+
'q2.2': 'Open-source contributors, QA engineer',
|
|
93
|
+
'q2.3': '3',
|
|
94
|
+
'q3.1': ['Core API', 'Type definitions', 'Documentation', 'Examples', 'Tests'],
|
|
95
|
+
'q3.2': '1',
|
|
96
|
+
'q3.3': 'The feature works end-to-end without errors and is covered by tests.',
|
|
97
|
+
'q4.1': '1',
|
|
98
|
+
'q4.2': 'No frontend (API only)',
|
|
99
|
+
'q4.3': 'None needed',
|
|
100
|
+
'q4.4': 'No authentication',
|
|
101
|
+
'q4.5': '1',
|
|
102
|
+
'q4.6': 'Distributed via npm / crates.io / PyPI',
|
|
103
|
+
'q4.7': 'Library calls complete in under 10ms for typical inputs.',
|
|
104
|
+
'q4.8': 'Logging only (console/file)',
|
|
105
|
+
'q5.1': ['CLI wrapper', 'GUI explorer', 'Cloud service integration'],
|
|
106
|
+
'q5.2': 'Consumers use a supported language / runtime version.',
|
|
107
|
+
'q5.3': 'API surface must remain stable — breaking changes require a major version bump.',
|
|
108
|
+
'q6.1': '1',
|
|
109
|
+
},
|
|
110
|
+
desktop: {
|
|
111
|
+
'q0.1': 'I want to build a desktop application that runs natively on Windows, Mac, or Linux.',
|
|
112
|
+
'q0.2': 'intermediate',
|
|
113
|
+
'q1.1': 'my-desktop-app',
|
|
114
|
+
'q1.2': 'A desktop application that runs natively on the user\'s machine.',
|
|
115
|
+
'q1.3': 'Delivers a rich native experience for power users who need offline capabilities.',
|
|
116
|
+
'q1.4': 'desktop',
|
|
117
|
+
'q2.1': 'end user',
|
|
118
|
+
'q2.2': 'IT administrator, support engineer',
|
|
119
|
+
'q2.3': '1',
|
|
120
|
+
'q3.1': ['Main window / UI', 'Data persistence', 'Settings', 'Auto-update', 'Help / docs'],
|
|
121
|
+
'q3.2': '1',
|
|
122
|
+
'q3.3': 'The feature works end-to-end without errors and is covered by tests.',
|
|
123
|
+
'q4.1': '1',
|
|
124
|
+
'q4.2': 'Static HTML / CSS',
|
|
125
|
+
'q4.3': 'SQLite (embedded)',
|
|
126
|
+
'q4.4': 'No authentication',
|
|
127
|
+
'q4.5': '1',
|
|
128
|
+
'q4.6': 'Packaged installer (Electron / Tauri)',
|
|
129
|
+
'q4.7': 'App launches in under 3 seconds.',
|
|
130
|
+
'q4.8': 'Logging only (console/file)',
|
|
131
|
+
'q5.1': ['Web version', 'Mobile companion app', 'Plugin marketplace'],
|
|
132
|
+
'q5.2': 'Target OS versions are Windows 10+, macOS 12+, Ubuntu 22+.',
|
|
133
|
+
'q5.3': 'Cross-platform packaging adds complexity — start with one OS if needed.',
|
|
134
|
+
'q6.1': '1',
|
|
135
|
+
},
|
|
136
|
+
mobile: {
|
|
137
|
+
'q0.1': 'I want to build a mobile app for phones that people can download and use on the go.',
|
|
138
|
+
'q0.2': 'intermediate',
|
|
139
|
+
'q1.1': 'my-mobile-app',
|
|
140
|
+
'q1.2': 'A mobile application for iOS and/or Android.',
|
|
141
|
+
'q1.3': 'Delivers a native mobile experience that users can access anywhere.',
|
|
142
|
+
'q1.4': 'mobile',
|
|
143
|
+
'q2.1': 'end user',
|
|
144
|
+
'q2.2': 'Product manager, QA engineer',
|
|
145
|
+
'q2.3': '1',
|
|
146
|
+
'q3.1': ['Onboarding', 'Core user flow', 'Push notifications', 'Settings', 'Offline support'],
|
|
147
|
+
'q3.2': '1',
|
|
148
|
+
'q3.3': 'The feature works end-to-end without errors and is covered by tests.',
|
|
149
|
+
'q4.1': '1',
|
|
150
|
+
'q4.2': 'No frontend (API only)',
|
|
151
|
+
'q4.3': 'PostgreSQL',
|
|
152
|
+
'q4.4': 'Email/password + optional OAuth',
|
|
153
|
+
'q4.5': '1',
|
|
154
|
+
'q4.6': 'App Store / Google Play',
|
|
155
|
+
'q4.7': 'Screens render in under 300ms. API calls under 500ms p95.',
|
|
156
|
+
'q4.8': 'Logging + metrics',
|
|
157
|
+
'q5.1': ['Tablet-specific layout', 'Wearable app', 'Desktop companion'],
|
|
158
|
+
'q5.2': 'Target: iOS 16+, Android 11+.',
|
|
159
|
+
'q5.3': 'App store review cycles add 1-2 week delays to releases.',
|
|
160
|
+
'q6.1': '1',
|
|
161
|
+
},
|
|
162
|
+
other: {
|
|
163
|
+
'q0.1': 'I want to build a software project that solves a specific problem.',
|
|
164
|
+
'q0.2': 'intermediate',
|
|
165
|
+
'q1.1': 'my-project',
|
|
166
|
+
'q1.2': 'A software project with a specific purpose.',
|
|
167
|
+
'q1.3': 'Solves a well-defined problem in a reliable and maintainable way.',
|
|
168
|
+
'q1.4': 'other',
|
|
169
|
+
'q2.1': 'user',
|
|
170
|
+
'q2.2': 'DevOps engineer, QA engineer',
|
|
171
|
+
'q2.3': '2',
|
|
172
|
+
'q3.1': ['Core feature', 'Configuration', 'Documentation', 'Tests'],
|
|
173
|
+
'q3.2': '1',
|
|
174
|
+
'q3.3': 'The feature works end-to-end without errors and is covered by tests.',
|
|
175
|
+
'q4.1': '1',
|
|
176
|
+
'q4.2': 'No frontend (API only)',
|
|
177
|
+
'q4.3': 'None needed',
|
|
178
|
+
'q4.4': 'No authentication',
|
|
179
|
+
'q4.5': '1',
|
|
180
|
+
'q4.6': 'On-premises',
|
|
181
|
+
'q4.7': 'Operations complete in reasonable time for the expected workload.',
|
|
182
|
+
'q4.8': 'Logging only (console/file)',
|
|
183
|
+
'q5.1': ['Unrelated future features'],
|
|
184
|
+
'q5.2': 'Required runtime is installed on the target environment.',
|
|
185
|
+
'q5.3': 'Scope may grow — strict sprint discipline is required.',
|
|
186
|
+
'q6.1': '1',
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
// ---------------------------------------------------------------------------
|
|
190
|
+
// Stack-aware overrides applied on top of the base table
|
|
191
|
+
// ---------------------------------------------------------------------------
|
|
192
|
+
function applyStackOverrides(base, questionId, state) {
|
|
193
|
+
const { stackProfile } = state.detectedStack;
|
|
194
|
+
// Deployment suggestion adapts to detected stack
|
|
195
|
+
if (questionId === 'q4.6') {
|
|
196
|
+
if (stackProfile === 'typescript-node') {
|
|
197
|
+
if (state.projectType === 'cli' || state.projectType === 'library') {
|
|
198
|
+
return 'Distributed via npm (npx / global install)';
|
|
199
|
+
}
|
|
200
|
+
return 'Docker + VPS';
|
|
201
|
+
}
|
|
202
|
+
if (state.detectedStack.label === 'Python') {
|
|
203
|
+
if (state.projectType === 'cli' || state.projectType === 'library') {
|
|
204
|
+
return 'Distributed via PyPI (pip install)';
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (state.detectedStack.label === 'Rust') {
|
|
208
|
+
return 'Distributed via crates.io (cargo install)';
|
|
209
|
+
}
|
|
210
|
+
if (state.detectedStack.label === 'Go') {
|
|
211
|
+
return 'Compiled binary distributed via GitHub Releases';
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return base;
|
|
215
|
+
}
|
|
216
|
+
// ---------------------------------------------------------------------------
|
|
217
|
+
// Exported suggestion engine implementation
|
|
218
|
+
// ---------------------------------------------------------------------------
|
|
219
|
+
export class StaticSuggestionEngine {
|
|
220
|
+
suggest(questionId, state) {
|
|
221
|
+
const table = SUGGESTIONS[state.projectType] ?? SUGGESTIONS.other;
|
|
222
|
+
const base = table[questionId] ?? 'No suggestion available.';
|
|
223
|
+
return applyStackOverrides(base, questionId, state);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/** Convenience factory */
|
|
227
|
+
export function createSuggestionEngine() {
|
|
228
|
+
return new StaticSuggestionEngine();
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=suggestions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suggestions.js","sourceRoot":"","sources":["../../src/interview/suggestions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export interface StackDetection {
|
|
2
|
+
manifest: string | null;
|
|
3
|
+
stackProfile: 'typescript-node' | 'generic';
|
|
4
|
+
label: string;
|
|
5
|
+
files: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare const MANIFEST_MAP: Record<string, {
|
|
8
|
+
stackProfile: StackDetection['stackProfile'];
|
|
9
|
+
label: string;
|
|
10
|
+
}>;
|
|
11
|
+
export declare const SOURCE_EXTENSIONS: Set<string>;
|
|
12
|
+
export declare function detectStack(root: string): StackDetection;
|
|
13
|
+
export type ProjectType = 'web-app' | 'api' | 'cli' | 'library' | 'desktop' | 'mobile' | 'other';
|
|
14
|
+
export type UserLevel = 'beginner' | 'intermediate' | 'advanced';
|
|
15
|
+
export interface InterviewState {
|
|
16
|
+
/** Current interview phase */
|
|
17
|
+
phase: 'opening' | 'vision' | 'people' | 'features' | 'constraints' | 'boundaries' | 'review';
|
|
18
|
+
/** All collected answers keyed by question id */
|
|
19
|
+
answers: Record<string, string | string[]>;
|
|
20
|
+
/** Stack detected from the project directory */
|
|
21
|
+
detectedStack: StackDetection;
|
|
22
|
+
/** Project type resolved during the Vision phase */
|
|
23
|
+
projectType: ProjectType;
|
|
24
|
+
/** User's self-reported knowledge level (set during opening phase) */
|
|
25
|
+
userLevel: UserLevel;
|
|
26
|
+
/** Detected locale code (e.g. 'pt-BR', 'en-US') */
|
|
27
|
+
locale: string;
|
|
28
|
+
}
|
|
29
|
+
export interface PhaseEvaluation {
|
|
30
|
+
/** Quality score 0-10 for the specifications collected so far */
|
|
31
|
+
score: number;
|
|
32
|
+
/** Identified gaps in the collected information */
|
|
33
|
+
gaps: string[];
|
|
34
|
+
/** Follow-up questions generated by the LLM to fill the gaps */
|
|
35
|
+
followUpQuestions: Array<{
|
|
36
|
+
id: string;
|
|
37
|
+
prompt: string;
|
|
38
|
+
type: 'string' | 'multiline' | 'choice';
|
|
39
|
+
choices?: string[];
|
|
40
|
+
}>;
|
|
41
|
+
/** LLM's reasoning for the score */
|
|
42
|
+
reasoning: string;
|
|
43
|
+
}
|
|
44
|
+
export interface SuggestionEngine {
|
|
45
|
+
suggest(questionId: string, state: InterviewState): string | string[];
|
|
46
|
+
}
|