mcoda 0.1.30 → 0.1.32
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EstimateCommands.d.ts","sourceRoot":"","sources":["../../../src/commands/estimate/EstimateCommands.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,cAAc,EAGf,MAAM,aAAa,CAAC;AAErB,UAAU,UAAU;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,cAAc,CAAC;IAC9B,cAAc,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"EstimateCommands.d.ts","sourceRoot":"","sources":["../../../src/commands/estimate/EstimateCommands.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,cAAc,EAGf,MAAM,aAAa,CAAC;AAErB,UAAU,UAAU;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,cAAc,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB;AAmCD,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,EAAE,KAAG,UA4HlD,CAAC;AA8EF,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,GAAG,IAAI,GAAG,SAAS,KAAG,MAwBjE,CAAC;AA2OF,qBAAa,gBAAgB;WACd,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAkEhD"}
|
|
@@ -11,7 +11,7 @@ const usage = `mcoda estimate \\
|
|
|
11
11
|
[--sp-per-hour-review <FLOAT>] \\
|
|
12
12
|
[--sp-per-hour-qa <FLOAT>] \\
|
|
13
13
|
[--velocity-mode config|empirical|mixed] \\
|
|
14
|
-
[--velocity-window
|
|
14
|
+
[--velocity-window <POSITIVE_INT>] \\
|
|
15
15
|
[--quiet] [--no-color] [--no-telemetry] \\
|
|
16
16
|
[--json]`;
|
|
17
17
|
const parseNumber = (value) => {
|
|
@@ -20,6 +20,12 @@ const parseNumber = (value) => {
|
|
|
20
20
|
const parsed = Number(value);
|
|
21
21
|
return Number.isFinite(parsed) ? parsed : undefined;
|
|
22
22
|
};
|
|
23
|
+
const parsePositiveInteger = (value) => {
|
|
24
|
+
const parsed = parseNumber(value);
|
|
25
|
+
if (parsed === undefined || !Number.isInteger(parsed) || parsed <= 0)
|
|
26
|
+
return undefined;
|
|
27
|
+
return parsed;
|
|
28
|
+
};
|
|
23
29
|
const parseVelocityMode = (value) => {
|
|
24
30
|
if (!value)
|
|
25
31
|
return undefined;
|
|
@@ -99,8 +105,8 @@ export const parseEstimateArgs = (argv) => {
|
|
|
99
105
|
break;
|
|
100
106
|
case "--velocity-window":
|
|
101
107
|
case "--window": {
|
|
102
|
-
const value =
|
|
103
|
-
if (value
|
|
108
|
+
const value = parsePositiveInteger(argv[i + 1]);
|
|
109
|
+
if (value !== undefined) {
|
|
104
110
|
parsed.velocityWindow = value;
|
|
105
111
|
}
|
|
106
112
|
i += 1;
|
|
@@ -146,8 +152,8 @@ export const parseEstimateArgs = (argv) => {
|
|
|
146
152
|
}
|
|
147
153
|
}
|
|
148
154
|
else if (arg.startsWith("--velocity-window=") || arg.startsWith("--window=")) {
|
|
149
|
-
const value =
|
|
150
|
-
if (value
|
|
155
|
+
const value = parsePositiveInteger(arg.split("=")[1]);
|
|
156
|
+
if (value !== undefined) {
|
|
151
157
|
parsed.velocityWindow = value;
|
|
152
158
|
}
|
|
153
159
|
}
|
|
@@ -175,6 +181,10 @@ const padVisible = (value, width) => {
|
|
|
175
181
|
const diff = width - visibleLength(value);
|
|
176
182
|
return diff > 0 ? `${value}${" ".repeat(diff)}` : value;
|
|
177
183
|
};
|
|
184
|
+
const padVisibleStart = (value, width) => {
|
|
185
|
+
const diff = width - visibleLength(value);
|
|
186
|
+
return diff > 0 ? `${" ".repeat(diff)}${value}` : value;
|
|
187
|
+
};
|
|
178
188
|
const colorize = (enabled, code, value) => enabled ? `\x1b[${code}m${value}\x1b[0m` : value;
|
|
179
189
|
const style = {
|
|
180
190
|
bold: (enabled, value) => colorize(enabled, 1, value),
|
|
@@ -196,10 +206,20 @@ const formatPanel = (lines) => {
|
|
|
196
206
|
const formatBoxTable = (headers, rows, options) => {
|
|
197
207
|
const widths = headers.map((header, idx) => Math.max(visibleLength(header), ...rows.map((row) => visibleLength(row[idx] ?? ""))));
|
|
198
208
|
const lineStyle = options?.lineStyle ?? ((value) => value);
|
|
209
|
+
const align = options?.align ?? [];
|
|
199
210
|
const border = (left, join, right) => lineStyle(`${left}${widths.map((width) => "─".repeat(width + 2)).join(join)}${right}`);
|
|
200
211
|
const verticalLine = lineStyle("│");
|
|
201
212
|
const headerLine = `${verticalLine}${headers.map((header, idx) => ` ${padVisible(header, widths[idx])} `).join(verticalLine)}${verticalLine}`;
|
|
202
|
-
const rowLines = rows.map((row) =>
|
|
213
|
+
const rowLines = rows.map((row) => {
|
|
214
|
+
const cells = row.map((cell, idx) => {
|
|
215
|
+
const value = cell ?? "";
|
|
216
|
+
if (align[idx] === "right") {
|
|
217
|
+
return ` ${padVisibleStart(value, widths[idx])} `;
|
|
218
|
+
}
|
|
219
|
+
return ` ${padVisible(value, widths[idx])} `;
|
|
220
|
+
});
|
|
221
|
+
return `${verticalLine}${cells.join(verticalLine)}${verticalLine}`;
|
|
222
|
+
});
|
|
203
223
|
return [
|
|
204
224
|
border("╭", "┬", "╮"),
|
|
205
225
|
headerLine,
|
|
@@ -302,7 +322,7 @@ const renderProgressSection = (result, colorEnabled) => {
|
|
|
302
322
|
const done = result.completion.done;
|
|
303
323
|
const labels = [
|
|
304
324
|
"🛠️ Work on tasks",
|
|
305
|
-
"🧪 Ready to
|
|
325
|
+
"🧪 Ready to QA",
|
|
306
326
|
"✅ Done",
|
|
307
327
|
];
|
|
308
328
|
const maxLabel = Math.max(...labels.map((label) => visibleLength(label)));
|
|
@@ -318,7 +338,7 @@ const renderProgressSection = (result, colorEnabled) => {
|
|
|
318
338
|
partial: (value) => style.blue(colorEnabled, value),
|
|
319
339
|
empty: (value) => style.dim(colorEnabled, value),
|
|
320
340
|
}),
|
|
321
|
-
formatLine("🧪 Ready to
|
|
341
|
+
formatLine("🧪 Ready to QA", qa, {
|
|
322
342
|
full: (value) => style.yellow(colorEnabled, value),
|
|
323
343
|
partial: (value) => style.magenta(colorEnabled, value),
|
|
324
344
|
empty: (value) => style.dim(colorEnabled, value),
|
|
@@ -330,6 +350,10 @@ const renderProgressSection = (result, colorEnabled) => {
|
|
|
330
350
|
}),
|
|
331
351
|
]);
|
|
332
352
|
};
|
|
353
|
+
const formatKeyValueLines = (entries) => {
|
|
354
|
+
const maxLabel = Math.max(0, ...entries.map((entry) => visibleLength(entry.label)));
|
|
355
|
+
return entries.map((entry) => `${padVisible(entry.label, maxLabel)} : ${entry.value}`);
|
|
356
|
+
};
|
|
333
357
|
const renderResult = (result, options) => {
|
|
334
358
|
const { colorEnabled } = options;
|
|
335
359
|
const purpleTableLines = (value) => style.magenta(colorEnabled, value);
|
|
@@ -380,17 +404,20 @@ const renderResult = (result, options) => {
|
|
|
380
404
|
style.bold(colorEnabled, "STORY POINTS"),
|
|
381
405
|
style.bold(colorEnabled, spHeader.toUpperCase()),
|
|
382
406
|
style.bold(colorEnabled, "TIME LEFT"),
|
|
383
|
-
], rows, { lineStyle: purpleTableLines }));
|
|
407
|
+
], rows, { lineStyle: purpleTableLines, align: ["left", "right", "right", "right"] }));
|
|
384
408
|
const counts = result.statusCounts;
|
|
409
|
+
const statusLines = formatKeyValueLines([
|
|
410
|
+
{ label: style.bold(colorEnabled, "Total tasks"), value: `${counts.total}` },
|
|
411
|
+
{ label: style.cyan(colorEnabled, "Ready to code review"), value: `${counts.readyToCodeReview}` },
|
|
412
|
+
{ label: style.yellow(colorEnabled, "Ready to QA"), value: `${counts.readyToQa}` },
|
|
413
|
+
{ label: style.blue(colorEnabled, "In progress"), value: `${counts.inProgress}` },
|
|
414
|
+
{ label: style.red(colorEnabled, "Failed"), value: `${counts.failed}` },
|
|
415
|
+
{ label: style.green(colorEnabled, "Completed"), value: `${counts.completed}` },
|
|
416
|
+
]);
|
|
385
417
|
// eslint-disable-next-line no-console
|
|
386
418
|
console.log(formatPanel([
|
|
387
419
|
style.bold(colorEnabled, "📌 Task Status"),
|
|
388
|
-
|
|
389
|
-
`${style.cyan(colorEnabled, "Ready to code review")} : ${counts.readyToCodeReview}`,
|
|
390
|
-
`${style.yellow(colorEnabled, "Ready to qa")} : ${counts.readyToQa}`,
|
|
391
|
-
`${style.blue(colorEnabled, "In progress")} : ${counts.inProgress}`,
|
|
392
|
-
`${style.red(colorEnabled, "Failed")} : ${counts.failed}`,
|
|
393
|
-
`${style.green(colorEnabled, "Completed")} : ${counts.completed}`,
|
|
420
|
+
...statusLines,
|
|
394
421
|
]));
|
|
395
422
|
// eslint-disable-next-line no-console
|
|
396
423
|
console.log(renderProgressSection(result, colorEnabled));
|
|
@@ -399,11 +426,17 @@ const renderResult = (result, options) => {
|
|
|
399
426
|
const fallbackNote = velocity.requestedMode && velocity.requestedMode !== velocity.source
|
|
400
427
|
? ` (requested ${velocity.requestedMode}; no empirical samples, using config)`
|
|
401
428
|
: "";
|
|
429
|
+
const velocityLines = formatKeyValueLines([
|
|
430
|
+
{ label: style.bold(colorEnabled, "Velocity source"), value: `${velocity.source}${fallbackNote}` },
|
|
431
|
+
{
|
|
432
|
+
label: `${style.bold(colorEnabled, "Samples")}${windowLabel}`,
|
|
433
|
+
value: `impl=${samples.implementation ?? 0}, review=${samples.review ?? 0}, qa=${samples.qa ?? 0}`,
|
|
434
|
+
},
|
|
435
|
+
]);
|
|
402
436
|
// eslint-disable-next-line no-console
|
|
403
437
|
console.log(formatPanel([
|
|
404
438
|
style.bold(colorEnabled, "📈 Velocity"),
|
|
405
|
-
|
|
406
|
-
`${style.bold(colorEnabled, "Samples")}${windowLabel} : impl=${samples.implementation ?? 0}, review=${samples.review ?? 0}, qa=${samples.qa ?? 0}`,
|
|
439
|
+
...velocityLines,
|
|
407
440
|
]));
|
|
408
441
|
// eslint-disable-next-line no-console
|
|
409
442
|
console.log(style.bold(colorEnabled, style.magenta(colorEnabled, "⏱️ ETAs")));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcoda",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.32",
|
|
4
4
|
"description": "Local-first CLI for planning, documentation, and execution workflows with agent assistance.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -45,12 +45,12 @@
|
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"yaml": "^2.4.2",
|
|
48
|
-
"@mcoda/
|
|
49
|
-
"@mcoda/
|
|
48
|
+
"@mcoda/shared": "0.1.32",
|
|
49
|
+
"@mcoda/core": "0.1.32"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@mcoda/
|
|
53
|
-
"@mcoda/
|
|
52
|
+
"@mcoda/db": "0.1.32",
|
|
53
|
+
"@mcoda/integrations": "0.1.32"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
56
56
|
"build": "tsc -p tsconfig.json",
|