chekk 0.3.0 → 0.4.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.
- package/bin/chekk.js +1 -1
- package/package.json +1 -1
- package/src/display.js +423 -240
- package/src/index.js +24 -3
- package/src/insights.js +511 -0
- package/src/metrics/ai-leverage.js +13 -3
- package/src/metrics/debug-cycles.js +17 -3
- package/src/metrics/decomposition.js +12 -2
- package/src/metrics/session-structure.js +12 -2
- package/src/scorer.js +55 -26
package/src/display.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
+
import { BENCHMARKS, DIM_RANGES } from './insights.js';
|
|
2
3
|
|
|
3
4
|
// ── Color palette ──
|
|
4
5
|
const gold = chalk.hex('#FFD700');
|
|
@@ -7,6 +8,8 @@ const blue = chalk.hex('#3B82F6');
|
|
|
7
8
|
const green = chalk.hex('#22C55E');
|
|
8
9
|
const cyan = chalk.hex('#06B6D4');
|
|
9
10
|
const orange = chalk.hex('#F97316');
|
|
11
|
+
const red = chalk.hex('#EF4444');
|
|
12
|
+
const yellow = chalk.hex('#EAB308');
|
|
10
13
|
const dim = chalk.dim;
|
|
11
14
|
const bold = chalk.bold;
|
|
12
15
|
const white = chalk.white;
|
|
@@ -22,9 +25,9 @@ function tierColor(tier) {
|
|
|
22
25
|
function scoreColor(score) {
|
|
23
26
|
if (score >= 85) return green;
|
|
24
27
|
if (score >= 70) return cyan;
|
|
25
|
-
if (score >= 55) return
|
|
28
|
+
if (score >= 55) return yellow;
|
|
26
29
|
if (score >= 40) return orange;
|
|
27
|
-
return
|
|
30
|
+
return red;
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
function progressBar(score, width = 18) {
|
|
@@ -45,23 +48,22 @@ function pad(str, len) {
|
|
|
45
48
|
|
|
46
49
|
// ── Qualitative tier labels for dimensions ──
|
|
47
50
|
function dimTierLabel(score) {
|
|
48
|
-
if (score >= 80) return '
|
|
49
|
-
if (score >= 65) return '
|
|
50
|
-
if (score >= 50) return '
|
|
51
|
-
if (score >= 35) return '
|
|
52
|
-
return '
|
|
51
|
+
if (score >= 80) return 'EXCEPTIONAL';
|
|
52
|
+
if (score >= 65) return 'STRONG';
|
|
53
|
+
if (score >= 50) return 'SOLID';
|
|
54
|
+
if (score >= 35) return 'DEVELOPING';
|
|
55
|
+
return 'NEEDS WORK';
|
|
53
56
|
}
|
|
54
57
|
|
|
55
58
|
function dimTierColor(score) {
|
|
56
59
|
if (score >= 80) return green;
|
|
57
60
|
if (score >= 65) return cyan;
|
|
58
|
-
if (score >= 50) return
|
|
61
|
+
if (score >= 50) return yellow;
|
|
59
62
|
if (score >= 35) return orange;
|
|
60
|
-
return
|
|
63
|
+
return red;
|
|
61
64
|
}
|
|
62
65
|
|
|
63
66
|
// ── Snippet helpers ──
|
|
64
|
-
// Longer snippets with context labels instead of truncated decorations
|
|
65
67
|
|
|
66
68
|
function cleanPrompt(prompt, maxLen = 120) {
|
|
67
69
|
if (!prompt) return null;
|
|
@@ -78,15 +80,37 @@ function displayLabeledSnippet(label, prompt, maxLen = 120) {
|
|
|
78
80
|
console.log(` ${dim('\u21B3')} ${dim(label + ':')} ${dim.italic('\u201C' + s + '\u201D')}`);
|
|
79
81
|
}
|
|
80
82
|
|
|
83
|
+
// Cross-dimension filters: reject prompts that clearly belong to another dimension
|
|
84
|
+
const architecturalRe = /\b(architect|design|refactor|redesign|restructure|system design|data model|schema|api design|infrastructure|migration|strategy)\b/i;
|
|
85
|
+
const debugRe = /\b(error|bug|broken|crash|fail|exception|traceback|stack trace|doesn'?t work|not working|TypeError|SyntaxError|ImportError|ReferenceError|500|502|503|404|CORS)\b/i;
|
|
86
|
+
const planningRe = /\b(plan|breakdown|break down|think through|help me think|pros and cons|how should|code review|audit)\b/i;
|
|
87
|
+
|
|
88
|
+
// For each dimension, prompts matching these patterns are *excluded* as evidence
|
|
89
|
+
const dimensionExclusions = {
|
|
90
|
+
'specific_report': [architecturalRe, planningRe],
|
|
91
|
+
'quick_fix': [architecturalRe, planningRe],
|
|
92
|
+
'architectural': [debugRe],
|
|
93
|
+
'planning': [debugRe],
|
|
94
|
+
'exploratory': [debugRe],
|
|
95
|
+
'decomposition': [],
|
|
96
|
+
'followup': [],
|
|
97
|
+
'context_setting': [],
|
|
98
|
+
'refinement': [],
|
|
99
|
+
};
|
|
100
|
+
|
|
81
101
|
function pickExample(examples, type) {
|
|
82
102
|
if (!examples || !examples.length) return null;
|
|
83
|
-
const
|
|
84
|
-
|
|
103
|
+
const exclusions = dimensionExclusions[type] || [];
|
|
104
|
+
// Prefer a match that doesn't trigger exclusion patterns
|
|
105
|
+
const candidates = examples.filter(e => e.type === type);
|
|
106
|
+
if (candidates.length === 0) return null;
|
|
107
|
+
const clean = candidates.find(e => !exclusions.some(re => re.test(e.prompt)));
|
|
108
|
+
return (clean || candidates[0]).prompt;
|
|
85
109
|
}
|
|
86
110
|
|
|
87
111
|
// ── Box drawing ──
|
|
88
112
|
|
|
89
|
-
function box(lines, width =
|
|
113
|
+
function box(lines, width = 47) {
|
|
90
114
|
const out = [];
|
|
91
115
|
out.push(dim(' \u250C' + '\u2500'.repeat(width) + '\u2510'));
|
|
92
116
|
for (const line of lines) {
|
|
@@ -98,33 +122,44 @@ function box(lines, width = 43) {
|
|
|
98
122
|
return out;
|
|
99
123
|
}
|
|
100
124
|
|
|
101
|
-
function doubleRule(width =
|
|
125
|
+
function doubleRule(width = 53) {
|
|
102
126
|
return dim(' ' + '\u2550'.repeat(width));
|
|
103
127
|
}
|
|
104
128
|
|
|
129
|
+
function wrapText(text, maxWidth = 49) {
|
|
130
|
+
const words = text.split(' ');
|
|
131
|
+
const lines = [];
|
|
132
|
+
let current = '';
|
|
133
|
+
for (const word of words) {
|
|
134
|
+
if (current.length + word.length + 1 > maxWidth) {
|
|
135
|
+
lines.push(current);
|
|
136
|
+
current = word;
|
|
137
|
+
} else {
|
|
138
|
+
current = current ? current + ' ' + word : word;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (current) lines.push(current);
|
|
142
|
+
return lines;
|
|
143
|
+
}
|
|
144
|
+
|
|
105
145
|
// ══════════════════════════════════════════════
|
|
106
|
-
// HEADER
|
|
146
|
+
// HEADER — Scanning + progress
|
|
107
147
|
// ══════════════════════════════════════════════
|
|
108
148
|
|
|
109
149
|
export function displayHeader() {
|
|
110
150
|
console.log();
|
|
111
151
|
const lines = [
|
|
112
152
|
'',
|
|
113
|
-
` ${bold.white('chekk')}${dim(' v0.
|
|
114
|
-
` ${dim('
|
|
153
|
+
` ${bold.white('chekk')}${dim(' v0.4.1')}`,
|
|
154
|
+
` ${dim('engineering capability profile')}`,
|
|
115
155
|
'',
|
|
116
156
|
];
|
|
117
157
|
for (const l of box(lines, 45)) console.log(l);
|
|
118
158
|
console.log();
|
|
119
159
|
}
|
|
120
160
|
|
|
121
|
-
// ══════════════════════════════════════════════
|
|
122
|
-
// SCAN RESULTS
|
|
123
|
-
// ══════════════════════════════════════════════
|
|
124
|
-
|
|
125
161
|
export function displayScan(tools) {
|
|
126
162
|
console.log(dim(' Scanning local AI tools...\n'));
|
|
127
|
-
|
|
128
163
|
for (const tool of tools) {
|
|
129
164
|
const sessions = numberFormat(tool.sessions);
|
|
130
165
|
const projects = tool.projects.length;
|
|
@@ -136,10 +171,6 @@ export function displayScan(tools) {
|
|
|
136
171
|
console.log();
|
|
137
172
|
}
|
|
138
173
|
|
|
139
|
-
// ══════════════════════════════════════════════
|
|
140
|
-
// ANALYSIS PROGRESS BAR
|
|
141
|
-
// ══════════════════════════════════════════════
|
|
142
|
-
|
|
143
174
|
export function displayAnalysisStart(dateRange) {
|
|
144
175
|
console.log(` ${dim('Analyzing')} ${white(dateRange)}${dim('...\n')}`);
|
|
145
176
|
}
|
|
@@ -148,7 +179,6 @@ export async function displayProgressBar(durationMs = 2000) {
|
|
|
148
179
|
const width = 40;
|
|
149
180
|
const steps = 40;
|
|
150
181
|
const stepTime = durationMs / steps;
|
|
151
|
-
|
|
152
182
|
for (let i = 0; i <= steps; i++) {
|
|
153
183
|
const filled = i;
|
|
154
184
|
const empty = width - filled;
|
|
@@ -159,108 +189,199 @@ export async function displayProgressBar(durationMs = 2000) {
|
|
|
159
189
|
}
|
|
160
190
|
console.log();
|
|
161
191
|
console.log();
|
|
162
|
-
console.log(` ${green('\u2713')} ${dim('
|
|
192
|
+
console.log(` ${green('\u2713')} ${dim('Profile generated.')}`);
|
|
163
193
|
console.log();
|
|
164
194
|
}
|
|
165
195
|
|
|
166
196
|
// ══════════════════════════════════════════════
|
|
167
|
-
//
|
|
197
|
+
// PROFILE HEADER — Official document feel
|
|
168
198
|
// ══════════════════════════════════════════════
|
|
169
199
|
|
|
170
|
-
|
|
171
|
-
const {
|
|
172
|
-
const
|
|
173
|
-
const
|
|
174
|
-
const
|
|
200
|
+
function displayProfileHeader(result, extra = {}) {
|
|
201
|
+
const { sessionStats } = extra;
|
|
202
|
+
const now = new Date();
|
|
203
|
+
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
204
|
+
const dateStr = `${months[now.getMonth()]} ${now.getDate()}, ${now.getFullYear()}`;
|
|
175
205
|
|
|
176
|
-
// Big score block
|
|
177
206
|
console.log(doubleRule());
|
|
178
207
|
console.log();
|
|
179
|
-
console.log(
|
|
208
|
+
console.log(` ${bold.white('ENGINEERING CAPABILITY PROFILE')}`);
|
|
209
|
+
console.log();
|
|
210
|
+
if (sessionStats) {
|
|
211
|
+
console.log(` ${dim(`Generated ${dateStr} | chekk v0.4.1`)}`);
|
|
212
|
+
console.log(` ${dim(`Analysis: ${sessionStats.totalSessions} sessions \u00B7 ${sessionStats.tools.length} tool${sessionStats.tools.length > 1 ? 's' : ''} \u00B7 ${numberFormat(sessionStats.totalExchanges)} exchanges`)}`);
|
|
213
|
+
if (sessionStats.dateRangeShort) {
|
|
214
|
+
console.log(` ${dim(`Period: ${sessionStats.dateRangeShort}`)}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
console.log();
|
|
218
|
+
console.log(doubleRule());
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ══════════════════════════════════════════════
|
|
222
|
+
// SUMMARY BLOCK
|
|
223
|
+
// ══════════════════════════════════════════════
|
|
224
|
+
|
|
225
|
+
function displaySummary(result, extra = {}) {
|
|
226
|
+
const { overall, scores, archetype, tier, tierBadge, tierPercentile } = result;
|
|
227
|
+
const { scoreDelta, perToolScores, insights, sessionStats } = extra;
|
|
228
|
+
const tc = tierColor(tier);
|
|
229
|
+
|
|
230
|
+
// Find strongest and weakest
|
|
231
|
+
const dims = [
|
|
232
|
+
{ label: 'Thinking', score: scores.decomposition },
|
|
233
|
+
{ label: 'Debugging', score: scores.debugCycles },
|
|
234
|
+
{ label: 'AI Leverage', score: scores.aiLeverage },
|
|
235
|
+
{ label: 'Workflow', score: scores.sessionStructure },
|
|
236
|
+
];
|
|
237
|
+
dims.sort((a, b) => b.score - a.score);
|
|
238
|
+
const strongest = dims[0];
|
|
239
|
+
const weakest = dims[dims.length - 1];
|
|
240
|
+
|
|
180
241
|
console.log();
|
|
242
|
+
console.log(dim(' SUMMARY'));
|
|
181
243
|
|
|
182
|
-
|
|
244
|
+
const badge = tierBadge || '';
|
|
245
|
+
const toolsList = sessionStats ? sessionStats.tools.join(' \u00B7 ') : '';
|
|
246
|
+
const sessionCount = sessionStats ? `${sessionStats.totalSessions} across ${sessionStats.projectCount} projects` : '';
|
|
247
|
+
const period = sessionStats?.dateRangeShort || '';
|
|
248
|
+
|
|
249
|
+
// Delta string
|
|
183
250
|
let deltaStr = '';
|
|
184
251
|
if (scoreDelta !== null && scoreDelta !== undefined) {
|
|
185
|
-
if (scoreDelta > 0) deltaStr = ` ${green('\u2191 +' + scoreDelta
|
|
186
|
-
else if (scoreDelta < 0) deltaStr = ` ${orange('\u2193 ' + scoreDelta
|
|
187
|
-
else deltaStr = ` ${dim('\u2192 same as last scan')}`;
|
|
252
|
+
if (scoreDelta > 0) deltaStr = ` ${green('\u2191 +' + scoreDelta)}`;
|
|
253
|
+
else if (scoreDelta < 0) deltaStr = ` ${orange('\u2193 ' + scoreDelta)}`;
|
|
188
254
|
}
|
|
189
|
-
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
255
|
+
|
|
256
|
+
const summaryLines = [
|
|
257
|
+
'',
|
|
258
|
+
` ${dim('Score')} ${scoreColor(overall).bold(String(overall))}${deltaStr}`,
|
|
259
|
+
` ${dim('Tier')} ${tc(tier)} ${badge} ${dim('\u2014')} ${dim(tierPercentile)}`,
|
|
260
|
+
` ${dim('Archetype')} ${bold.white(archetype.name)}`,
|
|
261
|
+
];
|
|
262
|
+
if (toolsList) summaryLines.push(` ${dim('Tools')} ${dim(toolsList)}`);
|
|
263
|
+
if (sessionCount) summaryLines.push(` ${dim('Sessions')} ${dim(sessionCount)}`);
|
|
264
|
+
if (period) summaryLines.push(` ${dim('Period')} ${dim(period)}`);
|
|
265
|
+
summaryLines.push(` ${dim('Strongest')} ${dim(strongest.label + ' (' + dimTierLabel(strongest.score) + ')')}`);
|
|
266
|
+
summaryLines.push(` ${dim('Growth Area')} ${dim(weakest.label + ' (' + dimTierLabel(weakest.score) + ')')}`);
|
|
267
|
+
summaryLines.push('');
|
|
268
|
+
|
|
269
|
+
for (const l of box(summaryLines, 53)) console.log(l);
|
|
194
270
|
console.log();
|
|
195
|
-
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// ══════════════════════════════════════════════
|
|
274
|
+
// ARCHETYPE DEFINITION
|
|
275
|
+
// ══════════════════════════════════════════════
|
|
196
276
|
|
|
197
|
-
|
|
198
|
-
|
|
277
|
+
function displayArchetype(result) {
|
|
278
|
+
const { archetype } = result;
|
|
279
|
+
console.log(` ${bold.white(archetype.name)}`);
|
|
280
|
+
console.log();
|
|
281
|
+
if (archetype.description) {
|
|
282
|
+
const lines = wrapText(archetype.description, 51);
|
|
283
|
+
for (const line of lines) {
|
|
284
|
+
console.log(` ${dim(line)}`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
if (archetype.distribution) {
|
|
288
|
+
console.log();
|
|
289
|
+
console.log(` ${dim('Distribution: ' + archetype.distribution + ' of scored engineers')}`);
|
|
199
290
|
}
|
|
200
291
|
console.log();
|
|
292
|
+
}
|
|
201
293
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
294
|
+
// ══════════════════════════════════════════════
|
|
295
|
+
// DIMENSIONS — with ranges and qualitative labels
|
|
296
|
+
// ══════════════════════════════════════════════
|
|
297
|
+
|
|
298
|
+
function displayDimensions(result) {
|
|
299
|
+
const { scores } = result;
|
|
300
|
+
console.log(dim(' DIMENSIONS'));
|
|
206
301
|
console.log();
|
|
207
302
|
|
|
208
|
-
//
|
|
209
|
-
console.log(dim('
|
|
303
|
+
// Score weight transparency
|
|
304
|
+
console.log(` ${dim('Weights: Thinking 25% | Debugging 25% | AI Leverage 30% | Workflow 20%')}`);
|
|
305
|
+
console.log();
|
|
210
306
|
|
|
211
|
-
function dimLine(label, score) {
|
|
307
|
+
function dimLine(label, key, score) {
|
|
212
308
|
const labelStr = bold(label);
|
|
213
309
|
const labelVisible = label.length;
|
|
214
310
|
const labelPad = ' '.repeat(Math.max(0, 15 - labelVisible));
|
|
215
|
-
const scoreStr = String(score);
|
|
216
|
-
const scorePad = score < 10 ? ' ' : score < 100 ? ' ' : '';
|
|
217
311
|
const tierLabel = dimTierLabel(score);
|
|
218
|
-
const tierStr = dimTierColor(score)(tierLabel);
|
|
219
|
-
|
|
312
|
+
const tierStr = dimTierColor(score)(pad(tierLabel, 11));
|
|
313
|
+
const range = DIM_RANGES[key];
|
|
314
|
+
const rangeStr = dim(`range: ${range.min}-${range.max} | you: ${score}`);
|
|
315
|
+
return [
|
|
316
|
+
` ${labelStr}${labelPad}${progressBar(score)} ${tierStr}`,
|
|
317
|
+
` ${' '.repeat(15)}${rangeStr}`,
|
|
318
|
+
];
|
|
220
319
|
}
|
|
221
320
|
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
321
|
+
const allLines = [''];
|
|
322
|
+
allLines.push(...dimLine('Thinking', 'decomposition', scores.decomposition));
|
|
323
|
+
allLines.push('');
|
|
324
|
+
allLines.push(...dimLine('Debugging', 'debugCycles', scores.debugCycles));
|
|
325
|
+
allLines.push('');
|
|
326
|
+
allLines.push(...dimLine('AI Leverage', 'aiLeverage', scores.aiLeverage));
|
|
327
|
+
allLines.push('');
|
|
328
|
+
allLines.push(...dimLine('Workflow', 'sessionStructure', scores.sessionStructure));
|
|
329
|
+
allLines.push('');
|
|
330
|
+
|
|
331
|
+
for (const l of box(allLines, 53)) console.log(l);
|
|
332
|
+
console.log();
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// ══════════════════════════════════════════════
|
|
336
|
+
// CROSS-PLATFORM
|
|
337
|
+
// ══════════════════════════════════════════════
|
|
338
|
+
|
|
339
|
+
function displayCrossPlatform(perToolScores) {
|
|
340
|
+
if (!perToolScores || Object.keys(perToolScores).length <= 1) return;
|
|
341
|
+
|
|
342
|
+
console.log(dim(' CROSS-PLATFORM\n'));
|
|
343
|
+
const sorted = Object.entries(perToolScores).sort((a, b) => {
|
|
344
|
+
if (a[1].score === null) return 1;
|
|
345
|
+
if (b[1].score === null) return -1;
|
|
346
|
+
return b[1].score - a[1].score;
|
|
347
|
+
});
|
|
348
|
+
const maxSessions = Math.max(...sorted.map(([, v]) => v.sessions));
|
|
349
|
+
|
|
350
|
+
for (const [tool, data] of sorted) {
|
|
351
|
+
if (data.score !== null) {
|
|
352
|
+
const isPrimary = data.sessions === maxSessions;
|
|
353
|
+
const label = isPrimary ? 'primary tool' : data.sessions < 5 ? 'limited usage' : 'active';
|
|
354
|
+
console.log(` ${pad(bold(tool), 18)} ${bold(String(data.score))} ${progressBar(data.score)} ${dim(label)}`);
|
|
355
|
+
} else {
|
|
356
|
+
console.log(` ${pad(bold(tool), 18)} ${dim('--')} ${dim('\u2591'.repeat(18))} ${dim('limited data')}`);
|
|
257
357
|
}
|
|
358
|
+
}
|
|
359
|
+
console.log();
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// ══════════════════════════════════════════════
|
|
363
|
+
// PROJECT ANALYSIS
|
|
364
|
+
// ══════════════════════════════════════════════
|
|
365
|
+
|
|
366
|
+
function displayProjects(insights) {
|
|
367
|
+
const projects = insights?.projectComplexity;
|
|
368
|
+
if (!projects || projects.length === 0) return;
|
|
369
|
+
|
|
370
|
+
console.log(dim(' PROJECT ANALYSIS\n'));
|
|
371
|
+
for (const p of projects) {
|
|
372
|
+
const compColor = p.complexity === 'HIGH' ? green : p.complexity === 'MEDIUM' ? yellow : dim;
|
|
373
|
+
const signals = p.signals.length > 0 ? p.signals.join(' \u00B7 ') : '';
|
|
374
|
+
console.log(` ${pad(bold(p.name), 32)} Complexity: ${compColor(p.complexity)}`);
|
|
375
|
+
if (signals) {
|
|
376
|
+
console.log(` ${dim(signals)}`);
|
|
377
|
+
}
|
|
378
|
+
console.log(` ${dim(`${p.sessions} sessions \u00B7 ${numberFormat(p.exchanges)} exchanges \u00B7 ${p.daysActive} days active`)}`);
|
|
258
379
|
console.log();
|
|
259
380
|
}
|
|
260
381
|
}
|
|
261
382
|
|
|
262
383
|
// ══════════════════════════════════════════════
|
|
263
|
-
// DIMENSION NARRATIVES
|
|
384
|
+
// DIMENSION NARRATIVES — Clinical, benchmarked
|
|
264
385
|
// ══════════════════════════════════════════════
|
|
265
386
|
|
|
266
387
|
export function displayNarratives(metrics, prose) {
|
|
@@ -275,10 +396,10 @@ export function displayNarratives(metrics, prose) {
|
|
|
275
396
|
|
|
276
397
|
if (prose && prose.sections) {
|
|
277
398
|
const sectionSnippetMap = {
|
|
278
|
-
'thinking': { label: '
|
|
279
|
-
'debugging': { label: '
|
|
280
|
-
'ai leverage': { label: '
|
|
281
|
-
'workflow': { label: '
|
|
399
|
+
'thinking': { label: 'Evidence', prompt: pickExample(metrics.decomposition.examples, 'decomposition') },
|
|
400
|
+
'debugging': { label: 'Evidence', prompt: pickExample(metrics.debugCycles.examples, 'specific_report') || pickExample(metrics.debugCycles.examples, 'quick_fix') },
|
|
401
|
+
'ai leverage': { label: 'Evidence', prompt: pickExample(metrics.aiLeverage.examples, 'architectural') || pickExample(metrics.aiLeverage.examples, 'planning') },
|
|
402
|
+
'workflow': { label: 'Evidence', prompt: pickExample(metrics.sessionStructure.examples, 'context_setting') || pickExample(metrics.sessionStructure.examples, 'refinement') },
|
|
282
403
|
};
|
|
283
404
|
|
|
284
405
|
for (const section of prose.sections) {
|
|
@@ -293,21 +414,17 @@ export function displayNarratives(metrics, prose) {
|
|
|
293
414
|
console.log();
|
|
294
415
|
}
|
|
295
416
|
} else {
|
|
296
|
-
|
|
417
|
+
displayDataNarratives(metrics, shownSnippets);
|
|
297
418
|
}
|
|
298
419
|
}
|
|
299
420
|
|
|
300
|
-
function
|
|
421
|
+
function displayDataNarratives(metrics, shownSnippets) {
|
|
301
422
|
const d = metrics.decomposition.details;
|
|
302
423
|
const db = metrics.debugCycles.details;
|
|
303
424
|
const ai = metrics.aiLeverage.details;
|
|
304
425
|
const ss = metrics.sessionStructure.details;
|
|
305
|
-
const dEx = metrics.decomposition.examples || [];
|
|
306
|
-
const dbEx = metrics.debugCycles.examples || [];
|
|
307
|
-
const aiEx = metrics.aiLeverage.examples || [];
|
|
308
|
-
const ssEx = metrics.sessionStructure.examples || [];
|
|
309
426
|
|
|
310
|
-
function
|
|
427
|
+
function showSnippet(label, prompt) {
|
|
311
428
|
if (!prompt) return;
|
|
312
429
|
const s = cleanPrompt(prompt, 120);
|
|
313
430
|
if (shownSnippets.has(s)) return;
|
|
@@ -315,128 +432,180 @@ function displayDataNarrativesWithTracker(metrics, shownSnippets) {
|
|
|
315
432
|
displayLabeledSnippet(label, prompt);
|
|
316
433
|
}
|
|
317
434
|
|
|
318
|
-
// Thinking
|
|
435
|
+
// Thinking — clinical
|
|
319
436
|
console.log(` ${bold('\uD83E\uDDE0 THINKING')}`);
|
|
320
|
-
|
|
321
|
-
console.log(` ${dim(
|
|
322
|
-
console.log(` ${dim(
|
|
323
|
-
|
|
324
|
-
showLabeledSnippet('Best decomposition prompt', pickExample(dEx, 'decomposition'));
|
|
437
|
+
console.log(` ${dim(`Avg session depth: ${d.avgExchangesPerSession} exchanges (benchmark: ${BENCHMARKS.avgExchangesPerSession})`)}`);
|
|
438
|
+
console.log(` ${dim(`Avg prompt length: ${numberFormat(d.avgPromptLength)} chars (benchmark: ${BENCHMARKS.avgPromptLength})`)}`);
|
|
439
|
+
console.log(` ${dim(`Multi-step ratio: ${d.multiStepSessions}/${d.totalSessions} sessions (${Math.round(d.multiStepSessions / Math.max(1, d.totalSessions) * 100)}%)`)}`);
|
|
440
|
+
showSnippet('Evidence', pickExample(metrics.decomposition.examples, 'decomposition'));
|
|
325
441
|
console.log();
|
|
326
442
|
|
|
327
|
-
// Debugging
|
|
443
|
+
// Debugging — clinical
|
|
328
444
|
console.log(` ${bold('\u26A1 DEBUGGING')}`);
|
|
329
|
-
|
|
330
|
-
console.log(` ${dim(
|
|
331
|
-
console.log(` ${dim(
|
|
332
|
-
|
|
333
|
-
showLabeledSnippet('Best debug prompt', pickExample(dbEx, 'specific_report') || pickExample(dbEx, 'quick_fix'));
|
|
445
|
+
console.log(` ${dim(`Avg resolution: ${db.avgTurnsToResolve} turns (benchmark: ${BENCHMARKS.avgTurnsToResolve})`)}`);
|
|
446
|
+
console.log(` ${dim(`Specific reports: ${db.specificReportRatio}% (benchmark: ${BENCHMARKS.specificReportRatio}%)`)}`);
|
|
447
|
+
console.log(` ${dim(`Extended loops: ${db.longLoops} | Quick fixes: ${db.quickFixes}/${db.totalDebugSequences}`)}`);
|
|
448
|
+
showSnippet('Evidence', pickExample(metrics.debugCycles.examples, 'specific_report') || pickExample(metrics.debugCycles.examples, 'quick_fix'));
|
|
334
449
|
console.log();
|
|
335
450
|
|
|
336
|
-
// AI Leverage
|
|
451
|
+
// AI Leverage — clinical
|
|
337
452
|
console.log(` ${bold('\uD83D\uDD27 AI LEVERAGE')}`);
|
|
338
|
-
console.log(` ${dim(
|
|
339
|
-
|
|
340
|
-
console.log(` ${dim(
|
|
341
|
-
|
|
342
|
-
showLabeledSnippet('Best leverage prompt', pickExample(aiEx, 'architectural') || pickExample(aiEx, 'planning'));
|
|
453
|
+
console.log(` ${dim(`High-level ratio: ${ai.highLevelRatio}% (benchmark: ${BENCHMARKS.highLevelRatio}%)`)}`);
|
|
454
|
+
console.log(` ${dim(`Breakdown: ${ai.architecturalPrompts} architectural \u00B7 ${ai.planningPrompts} planning \u00B7 ${ai.exploratoryPrompts} exploratory`)}`);
|
|
455
|
+
console.log(` ${dim(`Boilerplate: ${ai.boilerplatePrompts} (${Math.round(ai.boilerplatePrompts / Math.max(1, ai.totalPrompts) * 100)}%) \u00B7 Testing: ${ai.testingPrompts}`)}`);
|
|
456
|
+
showSnippet('Evidence', pickExample(metrics.aiLeverage.examples, 'architectural') || pickExample(metrics.aiLeverage.examples, 'planning'));
|
|
343
457
|
console.log();
|
|
344
458
|
|
|
345
|
-
// Workflow
|
|
459
|
+
// Workflow — clinical
|
|
346
460
|
console.log(` ${bold('\uD83D\uDCD0 WORKFLOW')}`);
|
|
347
|
-
console.log(` ${dim(
|
|
348
|
-
console.log(` ${dim(
|
|
349
|
-
console.log(` ${dim(
|
|
350
|
-
|
|
461
|
+
console.log(` ${dim(`Context-setting: ${ss.contextSetRatio}% (benchmark: ${BENCHMARKS.contextSetRatio}%)`)}`);
|
|
462
|
+
console.log(` ${dim(`Review at end: ${ss.reviewEndRatio}% (benchmark: ${BENCHMARKS.reviewEndRatio}%)`)}`);
|
|
463
|
+
console.log(` ${dim(`Refinement rate: ${ss.refinementRatio}% (benchmark: ${BENCHMARKS.refinementRatio}%)`)}`);
|
|
464
|
+
showSnippet('Evidence', pickExample(metrics.sessionStructure.examples, 'context_setting') || pickExample(metrics.sessionStructure.examples, 'refinement'));
|
|
351
465
|
console.log();
|
|
352
466
|
}
|
|
353
467
|
|
|
354
|
-
|
|
355
468
|
// ══════════════════════════════════════════════
|
|
356
|
-
//
|
|
469
|
+
// SIGNATURES — What makes you distinctive
|
|
357
470
|
// ══════════════════════════════════════════════
|
|
358
471
|
|
|
359
|
-
function
|
|
360
|
-
const
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
{
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
// Only show coaching if the weakest is actually dragging things down
|
|
372
|
-
if (weakest.score >= 70) return;
|
|
373
|
-
|
|
374
|
-
const tips = {
|
|
375
|
-
decomposition: 'Break complex tasks into subtasks before prompting.\nEngineers who decompose problems score 15+ points higher.',
|
|
376
|
-
debugCycles: 'Include specific error messages and stack traces in debug prompts.\nPrecise reports resolve 2x faster than "it\'s broken, fix it."',
|
|
377
|
-
aiLeverage: 'Use AI for architecture and planning, not just code generation.\nAsk "what\'s the best approach" before "write the code."',
|
|
378
|
-
sessionStructure: 'Set context at the start of each session and review at the end.\nEngineers who do this score 12 points higher on average.',
|
|
379
|
-
};
|
|
380
|
-
|
|
381
|
-
console.log(` ${bold('\uD83D\uDCA1 TO LEVEL UP')}`);
|
|
382
|
-
console.log(` ${dim(`Your ${weakest.label} score (${weakest.score}) is your biggest opportunity.`)}`);
|
|
383
|
-
const tipLines = tips[weakest.key].split('\n');
|
|
384
|
-
for (const line of tipLines) {
|
|
385
|
-
console.log(` ${dim(line)}`);
|
|
472
|
+
function displaySignatures(insights) {
|
|
473
|
+
const sigs = insights?.signatures;
|
|
474
|
+
if (!sigs || sigs.length === 0) return;
|
|
475
|
+
|
|
476
|
+
console.log(dim(' YOUR SIGNATURES\n'));
|
|
477
|
+
for (const sig of sigs) {
|
|
478
|
+
console.log(` ${cyan('\u2726')} ${bold(sig.name)}`);
|
|
479
|
+
const lines = wrapText(sig.detail, 49);
|
|
480
|
+
for (const line of lines) {
|
|
481
|
+
console.log(` ${dim(line)}`);
|
|
482
|
+
}
|
|
483
|
+
console.log();
|
|
386
484
|
}
|
|
387
|
-
console.log();
|
|
388
485
|
}
|
|
389
486
|
|
|
390
|
-
|
|
391
487
|
// ══════════════════════════════════════════════
|
|
392
|
-
//
|
|
488
|
+
// WATCH POINTS — Areas to improve
|
|
393
489
|
// ══════════════════════════════════════════════
|
|
394
490
|
|
|
395
|
-
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
const eggs = [];
|
|
491
|
+
function displayWatchPoints(insights) {
|
|
492
|
+
const wps = insights?.watchPoints;
|
|
493
|
+
if (!wps || wps.length === 0) return;
|
|
400
494
|
|
|
401
|
-
|
|
402
|
-
|
|
495
|
+
console.log(dim(' WATCH POINTS\n'));
|
|
496
|
+
for (const wp of wps) {
|
|
497
|
+
console.log(` ${orange('\u26A0')} ${bold(wp.name)}`);
|
|
498
|
+
const lines = wrapText(wp.detail, 49);
|
|
499
|
+
for (const line of lines) {
|
|
500
|
+
console.log(` ${dim(line)}`);
|
|
501
|
+
}
|
|
502
|
+
console.log();
|
|
403
503
|
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// ══════════════════════════════════════════════
|
|
507
|
+
// TRAJECTORY — Weekly evolution
|
|
508
|
+
// ══════════════════════════════════════════════
|
|
404
509
|
|
|
405
|
-
|
|
406
|
-
|
|
510
|
+
function displayTrajectory(insights) {
|
|
511
|
+
const traj = insights?.trajectory;
|
|
512
|
+
if (!traj) return;
|
|
513
|
+
|
|
514
|
+
console.log(dim(' YOUR TRAJECTORY\n'));
|
|
515
|
+
for (let i = 0; i < traj.weeks.length; i++) {
|
|
516
|
+
const w = traj.weeks[i];
|
|
517
|
+
const prev = i > 0 ? traj.weeks[i - 1] : null;
|
|
518
|
+
const arrow = prev ? (w.score > prev.score ? green(' \u2191') : w.score < prev.score ? orange(' \u2193') : dim(' \u2192')) : '';
|
|
519
|
+
const tierLabel = dimTierLabel(w.score);
|
|
520
|
+
console.log(` ${dim(pad(w.label, 16))} Score: ${scoreColor(w.score).bold(String(w.score))} ${dimTierColor(w.score)(tierLabel)}${arrow}`);
|
|
407
521
|
}
|
|
522
|
+
console.log();
|
|
523
|
+
const velColor = traj.velocityLabel === 'FAST' ? green : traj.velocityLabel === 'STEADY' ? cyan : traj.velocityLabel === 'STABLE' ? yellow : orange;
|
|
524
|
+
console.log(` ${dim('Learning velocity:')} ${velColor(traj.velocityLabel)} ${dim('\u2014 ' + traj.velocityDetail)}`);
|
|
525
|
+
console.log();
|
|
526
|
+
}
|
|
408
527
|
|
|
409
|
-
|
|
410
|
-
|
|
528
|
+
// ══════════════════════════════════════════════
|
|
529
|
+
// ASSESSMENT — Narrative paragraph
|
|
530
|
+
// ══════════════════════════════════════════════
|
|
531
|
+
|
|
532
|
+
function displayAssessment(insights) {
|
|
533
|
+
const assessment = insights?.assessment;
|
|
534
|
+
if (!assessment) return;
|
|
535
|
+
|
|
536
|
+
console.log(dim(' ASSESSMENT\n'));
|
|
537
|
+
const lines = wrapText(assessment, 51);
|
|
538
|
+
for (const line of lines) {
|
|
539
|
+
console.log(` ${dim(line)}`);
|
|
411
540
|
}
|
|
541
|
+
console.log();
|
|
542
|
+
}
|
|
412
543
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
544
|
+
// ══════════════════════════════════════════════
|
|
545
|
+
// CONFIDENCE INDICATOR
|
|
546
|
+
// ══════════════════════════════════════════════
|
|
547
|
+
|
|
548
|
+
function displayConfidence(insights, sessionStats) {
|
|
549
|
+
const conf = insights?.confidence;
|
|
550
|
+
if (!conf) return;
|
|
551
|
+
|
|
552
|
+
const barWidth = 18;
|
|
553
|
+
const filled = Math.round((conf.score / 100) * barWidth);
|
|
554
|
+
const empty = barWidth - filled;
|
|
555
|
+
const confColor = conf.level === 'HIGH' ? green : conf.level === 'MODERATE' ? yellow : orange;
|
|
556
|
+
const bar = confColor('\u2588'.repeat(filled)) + dim('\u2591'.repeat(empty));
|
|
557
|
+
|
|
558
|
+
console.log(` ${dim('Profile confidence:')} ${bar} ${confColor(conf.level)}`);
|
|
559
|
+
if (sessionStats) {
|
|
560
|
+
console.log(` ${dim(`Based on ${sessionStats.totalSessions} sessions across ${sessionStats.tools.length} tool${sessionStats.tools.length > 1 ? 's' : ''}.`)}`);
|
|
561
|
+
}
|
|
562
|
+
console.log();
|
|
563
|
+
if (conf.level !== 'HIGH') {
|
|
564
|
+
console.log(` ${dim('Confidence increases with more sessions and tool')}`);
|
|
565
|
+
console.log(` ${dim('diversity. Run again in 30 days for updated assessment.')}`);
|
|
417
566
|
console.log();
|
|
418
567
|
}
|
|
419
568
|
}
|
|
420
569
|
|
|
421
570
|
// ══════════════════════════════════════════════
|
|
422
|
-
//
|
|
571
|
+
// METHODOLOGY FOOTER
|
|
423
572
|
// ══════════════════════════════════════════════
|
|
424
573
|
|
|
425
|
-
|
|
574
|
+
function displayMethodology() {
|
|
575
|
+
console.log(doubleRule());
|
|
576
|
+
console.log();
|
|
577
|
+
console.log(` ${dim('METHODOLOGY')}`);
|
|
578
|
+
console.log(` ${dim('Scores derived from structural analysis of prompt')}`);
|
|
579
|
+
console.log(` ${dim('patterns, debug sequences, and session architecture')}`);
|
|
580
|
+
console.log(` ${dim('across detected AI coding tools. Tier placement based')}`);
|
|
581
|
+
console.log(` ${dim('on distribution of scored engineers. No prompt content')}`);
|
|
582
|
+
console.log(` ${dim('is stored or transmitted. Learn more: chekk.dev/methodology')}`);
|
|
583
|
+
console.log();
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// ══════════════════════════════════════════════
|
|
587
|
+
// NEXT STEPS — Credential issuance
|
|
588
|
+
// ══════════════════════════════════════════════
|
|
589
|
+
|
|
590
|
+
function displayNextSteps(result) {
|
|
426
591
|
const { overall, archetype, tier, tierBadge } = result;
|
|
427
592
|
const tc = tierColor(tier);
|
|
428
593
|
|
|
429
594
|
console.log(doubleRule());
|
|
430
595
|
console.log();
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
console.log(` ${dim('\u2192 Claim your profile
|
|
434
|
-
console.log(`
|
|
435
|
-
console.log(`
|
|
436
|
-
console.log(`
|
|
437
|
-
console.log(
|
|
596
|
+
console.log(` ${bold.white('NEXT STEPS')}`);
|
|
597
|
+
console.log();
|
|
598
|
+
console.log(` ${dim('\u2192 Claim your verified profile')}`);
|
|
599
|
+
console.log(` ${dim('Link your GitHub and LinkedIn to create your')}`);
|
|
600
|
+
console.log(` ${dim('portable engineering credential.')}`);
|
|
601
|
+
console.log(` ${cyan.underline('chekk.dev/claim')}`);
|
|
602
|
+
console.log();
|
|
603
|
+
console.log(` ${dim('\u2192 View industry benchmarks')}`);
|
|
604
|
+
console.log(` ${dim('See how you compare across scored engineers.')}`);
|
|
605
|
+
console.log(` ${cyan.underline('chekk.dev/benchmarks')}`);
|
|
438
606
|
console.log();
|
|
439
|
-
console.log(` ${dim('\u2192
|
|
607
|
+
console.log(` ${dim('\u2192 Export this report')}`);
|
|
608
|
+
console.log(` ${dim('npx chekk --json')}`);
|
|
440
609
|
console.log();
|
|
441
610
|
|
|
442
611
|
// Copy-paste share line
|
|
@@ -446,12 +615,12 @@ export function displayEnding(result) {
|
|
|
446
615
|
console.log(` ${dim('\u2191 Copy this to share')}`);
|
|
447
616
|
console.log();
|
|
448
617
|
console.log(doubleRule());
|
|
449
|
-
console.log(` ${dim('chekk.dev \u2014
|
|
618
|
+
console.log(` ${dim('chekk.dev \u2014 engineering capability profiles')}`);
|
|
450
619
|
console.log();
|
|
451
620
|
}
|
|
452
621
|
|
|
453
622
|
// ══════════════════════════════════════════════
|
|
454
|
-
// VERBOSE: DETAILED BREAKDOWN
|
|
623
|
+
// VERBOSE: DETAILED BREAKDOWN
|
|
455
624
|
// ══════════════════════════════════════════════
|
|
456
625
|
|
|
457
626
|
export function displayVerbose(metrics, sessions) {
|
|
@@ -475,72 +644,77 @@ export function displayVerbose(metrics, sessions) {
|
|
|
475
644
|
}
|
|
476
645
|
console.log();
|
|
477
646
|
|
|
478
|
-
// Decomposition
|
|
647
|
+
// Decomposition
|
|
479
648
|
const d = metrics.decomposition.details;
|
|
480
|
-
console.log(bold(' DECOMPOSITION
|
|
481
|
-
console.log(` ${dim(pad('
|
|
482
|
-
console.log(` ${dim(pad('
|
|
483
|
-
console.log(` ${dim(pad('
|
|
484
|
-
console.log(` ${dim(pad('
|
|
485
|
-
console.log(` ${dim(pad('
|
|
486
|
-
console.log(` ${dim(pad('longPromptRatio', 30))} ${dim(d.longPromptRatio + '%')}`);
|
|
487
|
-
console.log(` ${dim(pad('contextualFollowupRatio', 30))} ${dim(d.contextualFollowupRatio + '%')} ${dim(d.contextualFollowupRatio > 20 ? '\u2014 builds on previous context well' : '\u2014 could reference prior context more')}`);
|
|
649
|
+
console.log(bold(' DECOMPOSITION'));
|
|
650
|
+
console.log(` ${dim(pad('Avg session depth', 30))} ${dim(String(d.avgExchangesPerSession))} ${dim(`(benchmark: ${BENCHMARKS.avgExchangesPerSession})`)}`);
|
|
651
|
+
console.log(` ${dim(pad('Avg prompt length', 30))} ${dim(d.avgPromptLength + ' chars')} ${dim(`(benchmark: ${BENCHMARKS.avgPromptLength})`)}`);
|
|
652
|
+
console.log(` ${dim(pad('Multi-step sessions', 30))} ${dim(String(d.multiStepSessions) + '/' + d.totalSessions)} ${dim(d.multiStepSessions > d.totalSessions * 0.5 ? '\u2014 strong' : '\u2014 room to grow')}`);
|
|
653
|
+
console.log(` ${dim(pad('Single-shot sessions', 30))} ${dim(String(d.singleShotSessions))}`);
|
|
654
|
+
console.log(` ${dim(pad('Contextual followups', 30))} ${dim(d.contextualFollowupRatio + '%')} ${dim(d.contextualFollowupRatio > 20 ? '\u2014 builds on context well' : '\u2014 could reference prior work more')}`);
|
|
488
655
|
console.log();
|
|
489
656
|
|
|
490
|
-
// Debug
|
|
657
|
+
// Debug
|
|
491
658
|
const db = metrics.debugCycles.details;
|
|
492
|
-
console.log(bold(' DEBUG
|
|
493
|
-
console.log(` ${dim(pad('
|
|
494
|
-
console.log(` ${dim(pad('
|
|
495
|
-
console.log(` ${dim(pad('
|
|
496
|
-
console.log(` ${dim(pad('
|
|
497
|
-
console.log(` ${dim(pad('
|
|
498
|
-
console.log(` ${dim(pad('
|
|
659
|
+
console.log(bold(' DEBUG CYCLES'));
|
|
660
|
+
console.log(` ${dim(pad('Total sequences', 30))} ${dim(String(db.totalDebugSequences))}`);
|
|
661
|
+
console.log(` ${dim(pad('Avg turns to resolve', 30))} ${dim(String(db.avgTurnsToResolve))} ${dim(`(benchmark: ${BENCHMARKS.avgTurnsToResolve})`)}`);
|
|
662
|
+
console.log(` ${dim(pad('Quick fixes (\u22642 turns)', 30))} ${dim(String(db.quickFixes))}`);
|
|
663
|
+
console.log(` ${dim(pad('Extended loops (>5 turns)', 30))} ${dim(String(db.longLoops))} ${dim(db.longLoops === 0 ? '\u2014 zero spirals' : '')}`);
|
|
664
|
+
console.log(` ${dim(pad('Specific report ratio', 30))} ${dim(db.specificReportRatio + '%')} ${dim(`(benchmark: ${BENCHMARKS.specificReportRatio}%)`)}`);
|
|
665
|
+
console.log(` ${dim(pad('Vague reports', 30))} ${dim(String(db.vagueReports))} ${dim(db.vagueReports === 0 ? '\u2014 never vague' : '')}`);
|
|
499
666
|
console.log();
|
|
500
667
|
|
|
501
|
-
// AI Leverage
|
|
668
|
+
// AI Leverage
|
|
502
669
|
const ai = metrics.aiLeverage.details;
|
|
503
|
-
console.log(bold(' AI LEVERAGE
|
|
504
|
-
console.log(` ${dim(pad('
|
|
505
|
-
console.log(` ${dim(pad('
|
|
506
|
-
console.log(` ${dim(pad('
|
|
507
|
-
console.log(` ${dim(pad('
|
|
508
|
-
console.log(` ${dim(pad('
|
|
509
|
-
console.log(` ${dim(pad('
|
|
510
|
-
console.log(` ${dim(pad('
|
|
511
|
-
console.log(
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
// Session structure details
|
|
670
|
+
console.log(bold(' AI LEVERAGE'));
|
|
671
|
+
console.log(` ${dim(pad('Total prompts', 30))} ${dim(numberFormat(ai.totalPrompts))}`);
|
|
672
|
+
console.log(` ${dim(pad('Architectural', 30))} ${dim(String(ai.architecturalPrompts))} ${dim(`(${Math.round(ai.architecturalPrompts / Math.max(1, ai.totalPrompts) * 100)}%)`)}`);
|
|
673
|
+
console.log(` ${dim(pad('Planning', 30))} ${dim(String(ai.planningPrompts))} ${dim(`(${Math.round(ai.planningPrompts / Math.max(1, ai.totalPrompts) * 100)}%)`)}`);
|
|
674
|
+
console.log(` ${dim(pad('Exploratory', 30))} ${dim(String(ai.exploratoryPrompts))} ${dim(`(${Math.round(ai.exploratoryPrompts / Math.max(1, ai.totalPrompts) * 100)}%)`)}`);
|
|
675
|
+
console.log(` ${dim(pad('Boilerplate', 30))} ${dim(String(ai.boilerplatePrompts))} ${dim(`(${Math.round(ai.boilerplatePrompts / Math.max(1, ai.totalPrompts) * 100)}%)`)} ${dim(ai.boilerplatePrompts < ai.totalPrompts * 0.05 ? '\u2014 minimal' : '')}`);
|
|
676
|
+
console.log(` ${dim(pad('Testing', 30))} ${dim(String(ai.testingPrompts))}`);
|
|
677
|
+
console.log(` ${dim(pad('High-level ratio', 30))} ${dim(ai.highLevelRatio + '%')} ${dim(`(benchmark: ${BENCHMARKS.highLevelRatio}%)`)}`);
|
|
678
|
+
console.log();
|
|
679
|
+
|
|
680
|
+
// Session structure
|
|
516
681
|
const ss = metrics.sessionStructure.details;
|
|
517
|
-
console.log(bold(' SESSION STRUCTURE
|
|
518
|
-
console.log(` ${dim(pad('
|
|
519
|
-
console.log(` ${dim(pad('
|
|
520
|
-
console.log(` ${dim(pad('
|
|
521
|
-
console.log(` ${dim(pad('
|
|
522
|
-
console.log(` ${dim(pad('
|
|
682
|
+
console.log(bold(' SESSION STRUCTURE'));
|
|
683
|
+
console.log(` ${dim(pad('Context-setting', 30))} ${dim(ss.contextSetRatio + '%')} ${dim(`(benchmark: ${BENCHMARKS.contextSetRatio}%)`)}`);
|
|
684
|
+
console.log(` ${dim(pad('Plan before code', 30))} ${dim(ss.planBeforeCodeRatio + '%')}`);
|
|
685
|
+
console.log(` ${dim(pad('Review at end', 30))} ${dim(ss.reviewEndRatio + '%')} ${dim(`(benchmark: ${BENCHMARKS.reviewEndRatio}%)`)}`);
|
|
686
|
+
console.log(` ${dim(pad('Refinement rate', 30))} ${dim(ss.refinementRatio + '%')} ${dim(`(benchmark: ${BENCHMARKS.refinementRatio}%)`)}`);
|
|
687
|
+
console.log(` ${dim(pad('Avg first prompt', 30))} ${dim(ss.avgFirstPromptLength + ' chars')}`);
|
|
523
688
|
if (ss.durationDistribution) {
|
|
524
689
|
const dur = ss.durationDistribution;
|
|
525
|
-
console.log(` ${dim(pad('
|
|
526
|
-
console.log(` ${dim(pad('
|
|
527
|
-
console.log(` ${dim(pad('
|
|
528
|
-
console.log(` ${dim(pad('
|
|
690
|
+
console.log(` ${dim(pad('Focused sessions (10-45m)', 30))} ${dim(String(dur.focused))}`);
|
|
691
|
+
console.log(` ${dim(pad('Short (<5m)', 30))} ${dim(String(dur.short))}`);
|
|
692
|
+
console.log(` ${dim(pad('Medium (5-60m)', 30))} ${dim(String(dur.medium))}`);
|
|
693
|
+
console.log(` ${dim(pad('Long (>60m)', 30))} ${dim(String(dur.long))}`);
|
|
529
694
|
}
|
|
530
695
|
console.log();
|
|
531
696
|
}
|
|
532
697
|
|
|
533
698
|
// ══════════════════════════════════════════════
|
|
534
|
-
// OFFLINE DISPLAY
|
|
699
|
+
// OFFLINE DISPLAY
|
|
535
700
|
// ══════════════════════════════════════════════
|
|
536
701
|
|
|
537
702
|
export function displayOffline(result, metrics, extra = {}) {
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
703
|
+
displayProfileHeader(result, extra);
|
|
704
|
+
displaySummary(result, extra);
|
|
705
|
+
displayArchetype(result);
|
|
706
|
+
displayDimensions(result);
|
|
707
|
+
displayCrossPlatform(extra.perToolScores);
|
|
708
|
+
displayDataNarratives(metrics, new Set());
|
|
709
|
+
displayProjects(extra.insights);
|
|
710
|
+
displaySignatures(extra.insights);
|
|
711
|
+
displayWatchPoints(extra.insights);
|
|
712
|
+
displayTrajectory(extra.insights);
|
|
713
|
+
displayAssessment(extra.insights);
|
|
714
|
+
displayConfidence(extra.insights, extra.sessionStats);
|
|
715
|
+
displayMethodology();
|
|
716
|
+
console.log(dim(' Run without --offline for AI-generated narrative insights\n'));
|
|
717
|
+
displayNextSteps(result);
|
|
544
718
|
}
|
|
545
719
|
|
|
546
720
|
// ══════════════════════════════════════════════
|
|
@@ -548,11 +722,20 @@ export function displayOffline(result, metrics, extra = {}) {
|
|
|
548
722
|
// ══════════════════════════════════════════════
|
|
549
723
|
|
|
550
724
|
export function displayFull(result, metrics, prose, extra = {}) {
|
|
551
|
-
|
|
725
|
+
displayProfileHeader(result, extra);
|
|
726
|
+
displaySummary(result, extra);
|
|
727
|
+
displayArchetype(result);
|
|
728
|
+
displayDimensions(result);
|
|
729
|
+
displayCrossPlatform(extra.perToolScores);
|
|
552
730
|
displayNarratives(metrics, prose);
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
731
|
+
displayProjects(extra.insights);
|
|
732
|
+
displaySignatures(extra.insights);
|
|
733
|
+
displayWatchPoints(extra.insights);
|
|
734
|
+
displayTrajectory(extra.insights);
|
|
735
|
+
displayAssessment(extra.insights);
|
|
736
|
+
displayConfidence(extra.insights, extra.sessionStats);
|
|
737
|
+
displayMethodology();
|
|
738
|
+
displayNextSteps(result);
|
|
556
739
|
}
|
|
557
740
|
|
|
558
741
|
// ── Utility ──
|