@beastmode-develeap/beastmode 0.1.292 → 0.1.294
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/dist/index.js +17 -0
- package/dist/index.js.map +1 -1
- package/dist/web/board.html +53 -9
- package/dist/web/build-commit.txt +1 -1
- package/dist/web/build-stamp.txt +1 -1
- package/package.json +1 -1
package/dist/web/board.html
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
}
|
|
16
16
|
</script>
|
|
17
17
|
<!--BOARD_DATA-->
|
|
18
|
-
<script>window.__BUILD_STAMP__ = "20260517-
|
|
18
|
+
<script>window.__BUILD_STAMP__ = "20260517-084327-d4efb67";</script>
|
|
19
19
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
20
20
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
21
21
|
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
@@ -2504,6 +2504,17 @@ input[type="range"]::-webkit-slider-thumb {
|
|
|
2504
2504
|
letter-spacing: 0.01em;
|
|
2505
2505
|
}
|
|
2506
2506
|
|
|
2507
|
+
/* Forecast badge on card — shown only when no actual cost exists */
|
|
2508
|
+
.card-badge.badge-forecast {
|
|
2509
|
+
background: var(--bg-secondary, #f3f4f6);
|
|
2510
|
+
color: var(--text-secondary, #6b7280);
|
|
2511
|
+
border: 1px dashed var(--border, #d1d5db);
|
|
2512
|
+
font-family: var(--font-mono);
|
|
2513
|
+
font-size: 10px;
|
|
2514
|
+
font-style: italic;
|
|
2515
|
+
letter-spacing: 0.01em;
|
|
2516
|
+
}
|
|
2517
|
+
|
|
2507
2518
|
/* Detail sidebar cost section */
|
|
2508
2519
|
.detail-cost-section {
|
|
2509
2520
|
padding: 12px 24px;
|
|
@@ -6328,6 +6339,7 @@ function PipelineView({
|
|
|
6328
6339
|
globalSort,
|
|
6329
6340
|
sortColumnItems,
|
|
6330
6341
|
costsByItem,
|
|
6342
|
+
forecastsByItem,
|
|
6331
6343
|
envVerifyByItem,
|
|
6332
6344
|
}) {
|
|
6333
6345
|
const [collapseKey, setCollapseKey] = useState(0);
|
|
@@ -6365,7 +6377,16 @@ function PipelineView({
|
|
|
6365
6377
|
${(() => {
|
|
6366
6378
|
const cost = costsByItem && costsByItem[String(item.id)];
|
|
6367
6379
|
const label = cost ? formatCost(cost.total_cost_usd) : null;
|
|
6368
|
-
|
|
6380
|
+
if (label) {
|
|
6381
|
+
return html`<span class="card-badge-wrap"><span class="card-badge badge-cost" title=${'Total cost: ' + label}>${label}</span></span>`;
|
|
6382
|
+
}
|
|
6383
|
+
const fc = forecastsByItem && forecastsByItem[String(item.id)];
|
|
6384
|
+
if (fc && typeof fc.median === 'number') {
|
|
6385
|
+
const flabel = '~' + formatCost(fc.median);
|
|
6386
|
+
const title = 'Forecast: ' + formatCost(fc.low) + ' – ' + formatCost(fc.high) + ' (' + fc.confidence + ')';
|
|
6387
|
+
return html`<span class="card-badge-wrap"><span class="card-badge badge-forecast" title=${title}>${flabel}</span></span>`;
|
|
6388
|
+
}
|
|
6389
|
+
return null;
|
|
6369
6390
|
})()}
|
|
6370
6391
|
${(() => {
|
|
6371
6392
|
const env = item.extra && item.extra.current_env;
|
|
@@ -6712,6 +6733,7 @@ function BoardPage({ selectedProject }) {
|
|
|
6712
6733
|
const [sortOpen, setSortOpen] = useState(false);
|
|
6713
6734
|
const [epicCollapseKey, setEpicCollapseKey] = useState(0);
|
|
6714
6735
|
const [costsByItem, setCostsByItem] = useState({});
|
|
6736
|
+
const [forecastsByItem, setForecastsByItem] = useState({});
|
|
6715
6737
|
const [envVerifyByItem, setEnvVerifyByItem] = useState({});
|
|
6716
6738
|
const [viewMode, setViewMode] = useState(() => {
|
|
6717
6739
|
try {
|
|
@@ -6789,6 +6811,18 @@ function BoardPage({ selectedProject }) {
|
|
|
6789
6811
|
.catch(() => {});
|
|
6790
6812
|
}, [selectedProject]);
|
|
6791
6813
|
|
|
6814
|
+
// Forecast badges: cards without actual cost yet get a predicted
|
|
6815
|
+
// cost range based on historical k-NN over Done items. The endpoint
|
|
6816
|
+
// returns null for items with insufficient neighbor data; those
|
|
6817
|
+
// cards show no forecast badge at all.
|
|
6818
|
+
const fetchForecasts = useCallback(() => {
|
|
6819
|
+
const boardParam = (selectedProject && selectedProject !== 'all') ? '?board=' + encodeURIComponent(selectedProject) : '';
|
|
6820
|
+
fetch('/api/costs/forecasts' + boardParam)
|
|
6821
|
+
.then(r => r.ok ? r.json() : { forecasts: {} })
|
|
6822
|
+
.then(data => setForecastsByItem((data && data.forecasts) || {}))
|
|
6823
|
+
.catch(() => {});
|
|
6824
|
+
}, [selectedProject]);
|
|
6825
|
+
|
|
6792
6826
|
// Story 7: batch-fetch env verify status for items that have a current_env.
|
|
6793
6827
|
// The endpoint is per-item, so we issue parallel requests with allSettled
|
|
6794
6828
|
// — failed individual fetches don't block the others, and the badge falls
|
|
@@ -6826,12 +6860,14 @@ function BoardPage({ selectedProject }) {
|
|
|
6826
6860
|
useEffect(() => {
|
|
6827
6861
|
fetchItems();
|
|
6828
6862
|
fetchCosts();
|
|
6863
|
+
fetchForecasts();
|
|
6829
6864
|
const interval = setInterval(() => {
|
|
6830
6865
|
// Silent refresh — don't show loading spinner on polls
|
|
6831
6866
|
api('GET', '/api/board/items')
|
|
6832
6867
|
.then(data => setItems(data.items || []))
|
|
6833
6868
|
.catch(() => {});
|
|
6834
6869
|
fetchCosts();
|
|
6870
|
+
fetchForecasts();
|
|
6835
6871
|
}, 10000);
|
|
6836
6872
|
return () => clearInterval(interval);
|
|
6837
6873
|
}, [selectedProject]);
|
|
@@ -7499,6 +7535,7 @@ function BoardPage({ selectedProject }) {
|
|
|
7499
7535
|
globalSort=${globalSort}
|
|
7500
7536
|
sortColumnItems=${sortColumnItems}
|
|
7501
7537
|
costsByItem=${costsByItem}
|
|
7538
|
+
forecastsByItem=${forecastsByItem}
|
|
7502
7539
|
envVerifyByItem=${envVerifyByItem}
|
|
7503
7540
|
/>`
|
|
7504
7541
|
: html`
|
|
@@ -7576,7 +7613,16 @@ function BoardPage({ selectedProject }) {
|
|
|
7576
7613
|
${(() => {
|
|
7577
7614
|
const cost = costsByItem && costsByItem[String(item.id)];
|
|
7578
7615
|
const label = cost ? formatCost(cost.total_cost_usd) : null;
|
|
7579
|
-
|
|
7616
|
+
if (label) {
|
|
7617
|
+
return html`<span class="card-badge-wrap"><span class="card-badge badge-cost" title=${'Total cost: ' + label}>${label}</span></span>`;
|
|
7618
|
+
}
|
|
7619
|
+
const fc = forecastsByItem && forecastsByItem[String(item.id)];
|
|
7620
|
+
if (fc && typeof fc.median === 'number') {
|
|
7621
|
+
const flabel = '~' + formatCost(fc.median);
|
|
7622
|
+
const title = 'Forecast: ' + formatCost(fc.low) + ' – ' + formatCost(fc.high) + ' (' + fc.confidence + ')';
|
|
7623
|
+
return html`<span class="card-badge-wrap"><span class="card-badge badge-forecast" title=${title}>${flabel}</span></span>`;
|
|
7624
|
+
}
|
|
7625
|
+
return null;
|
|
7580
7626
|
})()}
|
|
7581
7627
|
${(() => {
|
|
7582
7628
|
const env = item.extra && item.extra.current_env;
|
|
@@ -10982,13 +11028,11 @@ function CostsPage({ selectedProject }) {
|
|
|
10982
11028
|
.map(([cat, amount]) => ({ cat, amount }));
|
|
10983
11029
|
|
|
10984
11030
|
const categoryColors = {
|
|
10985
|
-
|
|
10986
|
-
|
|
10987
|
-
verify: '#f59e0b',
|
|
10988
|
-
review: '#8b5cf6',
|
|
10989
|
-
epic: '#ec4899',
|
|
11031
|
+
productive: '#10b981',
|
|
11032
|
+
retry: '#f59e0b',
|
|
10990
11033
|
heal: '#ef4444',
|
|
10991
|
-
|
|
11034
|
+
wasted_decomposition: '#8b5cf6',
|
|
11035
|
+
bug_gc_followup: '#ec4899',
|
|
10992
11036
|
mixed: 'var(--text-muted)',
|
|
10993
11037
|
};
|
|
10994
11038
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
d4efb676cd5deb3ff779c0a5e48ee581a62bc96d
|
package/dist/web/build-stamp.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
20260517-
|
|
1
|
+
20260517-084327-d4efb67
|