diff --git a/internal/server/static/index.html b/internal/server/static/index.html
index 536e0a0..273c592 100644
--- a/internal/server/static/index.html
+++ b/internal/server/static/index.html
@@ -1685,16 +1685,16 @@
Why calculate PR costs?
// Delay Costs
output += ' Delay Costs\n';
output += ' ───────────\n';
- output += ` Workstream blockage ${formatCurrency(avgDeliveryDelayCost).padStart(15)} ${formatTimeUnit(avgDeliveryDelayHours)} (${e.human_prs} PRs)\n`;
+ output += formatItemLine("Workstream blockage", avgDeliveryDelayCost, formatTimeUnit(avgDeliveryDelayHours), `(${e.human_prs} PRs)`);
const avgAutomatedUpdatesCost = e.automated_updates_cost / totalPRs;
const avgAutomatedUpdatesHours = e.automated_updates_hours / totalPRs;
const avgPRTrackingCost = e.pr_tracking_cost / totalPRs;
const avgPRTrackingHours = e.pr_tracking_hours / totalPRs;
if (avgAutomatedUpdatesCost > 0.01) {
- output += ` Automated Updates ${formatCurrency(avgAutomatedUpdatesCost).padStart(15)} ${formatTimeUnit(avgAutomatedUpdatesHours)} (${e.bot_prs} PRs)\n`;
+ output += formatItemLine("Automated Updates", avgAutomatedUpdatesCost, formatTimeUnit(avgAutomatedUpdatesHours), `(${e.bot_prs} PRs)`);
}
if (avgPRTrackingCost > 0.01) {
- output += ` PR Tracking ${formatCurrency(avgPRTrackingCost).padStart(15)} ${formatTimeUnit(avgPRTrackingHours)} (${e.open_prs} open PRs)\n`;
+ output += formatItemLine("PR Tracking", avgPRTrackingCost, formatTimeUnit(avgPRTrackingHours), `(${e.open_prs} open PRs)`);
}
const avgMergeDelayCost = avgDeliveryDelayCost + avgCodeChurnCost + avgAutomatedUpdatesCost + avgPRTrackingCost;
const avgMergeDelayHours = avgDeliveryDelayHours + avgCodeChurnHours + avgAutomatedUpdatesHours + avgPRTrackingHours;
@@ -1710,17 +1710,17 @@ Why calculate PR costs?
if (e.code_churn_cost > 0.01) {
const avgReworkPct = e.avg_rework_percentage || 0;
const label = avgReworkPct > 0 ? `Code Churn (${avgReworkPct.toFixed(0)}% drift)` : 'Code Churn';
- output += ` ${label.padEnd(26)} ${formatCurrency(avgCodeChurnCost).padStart(15)} ${formatTimeUnit(avgCodeChurnHours)} (${e.code_churn_pr_count} PRs)\n`;
+ output += formatItemLine(label, avgCodeChurnCost, formatTimeUnit(avgCodeChurnHours), `(${e.code_churn_pr_count} PRs)`);
}
if (e.future_review_cost > 0.01) {
- output += ` Review ${formatCurrency(avgFutureReviewCost).padStart(15)} ${formatTimeUnit(avgFutureReviewHours)} (${e.future_review_pr_count} PRs)\n`;
+ output += formatItemLine("Review", avgFutureReviewCost, formatTimeUnit(avgFutureReviewHours), `(${e.future_review_pr_count} PRs)`);
}
if (e.future_merge_cost > 0.01) {
- output += ` Merge ${formatCurrency(avgFutureMergeCost).padStart(15)} ${formatTimeUnit(avgFutureMergeHours)} (${e.future_merge_pr_count} PRs)\n`;
+ output += formatItemLine("Merge", avgFutureMergeCost, formatTimeUnit(avgFutureMergeHours), `(${e.future_merge_pr_count} PRs)`);
}
if (e.future_context_cost > 0.01) {
const avgFutureContextSessions = e.future_context_sessions / totalPRs;
- output += ` Context Switching ${formatCurrency(avgFutureContextCost).padStart(15)} ${formatTimeUnit(avgFutureContextHours)} (${avgFutureContextSessions.toFixed(1)} sessions)\n`;
+ output += formatItemLine("Context Switching", avgFutureContextCost, formatTimeUnit(avgFutureContextHours), `(${avgFutureContextSessions.toFixed(1)} sessions)`);
}
const avgFutureCost = avgCodeChurnCost + avgFutureReviewCost + avgFutureMergeCost + avgFutureContextCost;
const avgFutureHours = avgCodeChurnHours + avgFutureReviewHours + avgFutureMergeHours + avgFutureContextHours;
@@ -1794,13 +1794,13 @@ Why calculate PR costs?
output += ' ' + '─'.repeat(delayCostsHeader.length - 2) + '\n';
if ((e.delivery_delay_cost || 0) > 0) {
- output += ` Workstream blockage ${formatCurrency(e.delivery_delay_cost).padStart(15)} ${formatTimeUnit(e.delivery_delay_hours)} (${e.human_prs || 0} PRs)\n`;
+ output += formatItemLine("Workstream blockage", e.delivery_delay_cost, formatTimeUnit(e.delivery_delay_hours), `(${e.human_prs || 0} PRs)`);
}
if ((e.automated_updates_cost || 0) > 0) {
- output += ` Automated Updates ${formatCurrency(e.automated_updates_cost).padStart(15)} ${formatTimeUnit(e.automated_updates_hours)} (${e.bot_prs || 0} PRs)\n`;
+ output += formatItemLine("Automated Updates", e.automated_updates_cost, formatTimeUnit(e.automated_updates_hours), `(${e.bot_prs || 0} PRs)`);
}
if ((e.pr_tracking_cost || 0) > 0) {
- output += ` PR Tracking ${formatCurrency(e.pr_tracking_cost).padStart(15)} ${formatTimeUnit(e.pr_tracking_hours)} (${e.open_prs || 0} open PRs)\n`;
+ output += formatItemLine("PR Tracking", e.pr_tracking_cost, formatTimeUnit(e.pr_tracking_hours), `(${e.open_prs || 0} open PRs)`);
}
const mergeDelayCost = (e.delivery_delay_cost || 0) + (e.code_churn_cost || 0) + (e.automated_updates_cost || 0) + (e.pr_tracking_cost || 0);
@@ -1815,18 +1815,18 @@ Why calculate PR costs?
output += ' Future Costs\n';
output += ' ────────────\n';
if ((e.code_churn_cost || 0) > 0.01) {
- output += ` Code Churn ${formatCurrency(e.code_churn_cost).padStart(15)} ${formatTimeUnit(e.code_churn_hours)}\n`;
+ output += formatItemLine("Code Churn", e.code_churn_cost, formatTimeUnit(e.code_churn_hours), "");
}
if ((e.future_review_cost || 0) > 0.01) {
const openPRs = e.open_prs || 0;
- output += ` Review ${formatCurrency(e.future_review_cost).padStart(15)} ${formatTimeUnit(e.future_review_hours)} (${openPRs} PRs)\n`;
+ output += formatItemLine("Review", e.future_review_cost, formatTimeUnit(e.future_review_hours), `(${openPRs} PRs)`);
}
if ((e.future_merge_cost || 0) > 0.01) {
const openPRs = e.open_prs || 0;
- output += ` Merge ${formatCurrency(e.future_merge_cost).padStart(15)} ${formatTimeUnit(e.future_merge_hours)} (${openPRs} PRs)\n`;
+ output += formatItemLine("Merge", e.future_merge_cost, formatTimeUnit(e.future_merge_hours), `(${openPRs} PRs)`);
}
if ((e.future_context_cost || 0) > 0.01) {
- output += ` Context Switching ${formatCurrency(e.future_context_cost).padStart(15)} ${formatTimeUnit(e.future_context_hours)} (${e.future_context_sessions || 0} sessions)\n`;
+ output += formatItemLine("Context Switching", e.future_context_cost, formatTimeUnit(e.future_context_hours), `(${e.future_context_sessions || 0} sessions)`);
}
const futureCost = (e.code_churn_cost || 0) + (e.future_review_cost || 0) + (e.future_merge_cost || 0) + (e.future_context_cost || 0);
const futureHours = (e.code_churn_hours || 0) + (e.future_review_hours || 0) + (e.future_merge_hours || 0) + (e.future_context_hours || 0);