@beastmode-develeap/beastmode 0.1.206 → 0.1.207
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/web/board.html +97 -3
- 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__ = "20260509-
|
|
18
|
+
<script>window.__BUILD_STAMP__ = "20260509-122800-7350789";</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">
|
|
@@ -1522,6 +1522,37 @@ input[type="range"]::-webkit-slider-thumb {
|
|
|
1522
1522
|
margin: 0 -8px;
|
|
1523
1523
|
padding: 8px;
|
|
1524
1524
|
}
|
|
1525
|
+
/* Audit Trail — Superseded transition history (Story 6) */
|
|
1526
|
+
.audit-timeline { display: flex; flex-direction: column; gap: 8px; }
|
|
1527
|
+
.audit-entry {
|
|
1528
|
+
background: var(--bg-input);
|
|
1529
|
+
border-radius: 8px;
|
|
1530
|
+
padding: 10px 12px;
|
|
1531
|
+
border-left: 3px solid var(--accent);
|
|
1532
|
+
}
|
|
1533
|
+
.audit-entry-header {
|
|
1534
|
+
display: flex;
|
|
1535
|
+
justify-content: space-between;
|
|
1536
|
+
align-items: center;
|
|
1537
|
+
margin-bottom: 4px;
|
|
1538
|
+
}
|
|
1539
|
+
.audit-actor { font-weight: 600; font-size: 13px; }
|
|
1540
|
+
.audit-time { color: var(--text-muted); font-size: 12px; }
|
|
1541
|
+
.audit-entry-body { font-size: 13px; display: flex; flex-direction: column; gap: 4px; }
|
|
1542
|
+
.audit-from { color: var(--text-muted); }
|
|
1543
|
+
.audit-successor a, .audit-cascade a {
|
|
1544
|
+
color: var(--accent);
|
|
1545
|
+
text-decoration: none;
|
|
1546
|
+
}
|
|
1547
|
+
.audit-successor a:hover, .audit-cascade a:hover { text-decoration: underline; }
|
|
1548
|
+
.audit-reason {
|
|
1549
|
+
margin-top: 4px;
|
|
1550
|
+
padding: 6px 8px;
|
|
1551
|
+
background: var(--bg-secondary);
|
|
1552
|
+
border-radius: 4px;
|
|
1553
|
+
font-style: italic;
|
|
1554
|
+
color: var(--text-secondary);
|
|
1555
|
+
}
|
|
1525
1556
|
.btn-env-deploy {
|
|
1526
1557
|
display: inline-flex;
|
|
1527
1558
|
align-items: center;
|
|
@@ -5172,7 +5203,7 @@ function SupersededModal({ item, onConfirm, onCancel }) {
|
|
|
5172
5203
|
|
|
5173
5204
|
// ── Item Detail Sidebar ──
|
|
5174
5205
|
|
|
5175
|
-
function ItemDetailSidebar({ item, onClose, onStatusChange, selectedProject }) {
|
|
5206
|
+
function ItemDetailSidebar({ item, onClose, onStatusChange, selectedProject, allItems, onSelectItem }) {
|
|
5176
5207
|
const [updates, setUpdates] = useState([]);
|
|
5177
5208
|
const [loadingUpdates, setLoadingUpdates] = useState(true);
|
|
5178
5209
|
const [sortNewest, setSortNewest] = useState(true);
|
|
@@ -5187,6 +5218,7 @@ function ItemDetailSidebar({ item, onClose, onStatusChange, selectedProject }) {
|
|
|
5187
5218
|
const [phaseData, setPhaseData] = useState([]);
|
|
5188
5219
|
const [envTimeline, setEnvTimeline] = useState(null);
|
|
5189
5220
|
const [deployModal, setDeployModal] = useState(null);
|
|
5221
|
+
const [auditEvents, setAuditEvents] = useState([]);
|
|
5190
5222
|
const sidebarRef = useRef(null);
|
|
5191
5223
|
const topCommentRef = useRef(null);
|
|
5192
5224
|
|
|
@@ -5208,6 +5240,25 @@ function ItemDetailSidebar({ item, onClose, onStatusChange, selectedProject }) {
|
|
|
5208
5240
|
.catch(() => setEnvTimeline(null));
|
|
5209
5241
|
}, [item && item.id, item && item.extra && item.extra.current_env]);
|
|
5210
5242
|
|
|
5243
|
+
// FR-4: Fetch SupersededTransition audit events for the selected item.
|
|
5244
|
+
// Only fires when the item is in Superseded status — non-Superseded items
|
|
5245
|
+
// never have audit entries and the section is hidden anyway (NFR-4).
|
|
5246
|
+
useEffect(() => {
|
|
5247
|
+
if (!item || item.status !== 'Superseded') {
|
|
5248
|
+
setAuditEvents([]);
|
|
5249
|
+
return;
|
|
5250
|
+
}
|
|
5251
|
+
const proj = selectedProject && selectedProject !== 'all' ? selectedProject : null;
|
|
5252
|
+
const qs = proj ? '?board=' + encodeURIComponent(proj) : '';
|
|
5253
|
+
const sep = qs ? '&' : '?';
|
|
5254
|
+
const url = '/api/events' + qs + sep + 'item_id=' + encodeURIComponent(item.id) +
|
|
5255
|
+
'&type=SupersededTransition';
|
|
5256
|
+
fetch(url)
|
|
5257
|
+
.then(r => r.ok ? r.json() : [])
|
|
5258
|
+
.then(events => setAuditEvents(Array.isArray(events) ? events : []))
|
|
5259
|
+
.catch(() => setAuditEvents([]));
|
|
5260
|
+
}, [item && item.id, item && item.status]);
|
|
5261
|
+
|
|
5211
5262
|
// Cost summary fetch — keyed on item.id, refreshed alongside the
|
|
5212
5263
|
// 10-second updates/attachments poll below. The api() helper only
|
|
5213
5264
|
// auto-scopes /api/board/*, so append ?board=<proj> manually.
|
|
@@ -5535,6 +5586,49 @@ function ItemDetailSidebar({ item, onClose, onStatusChange, selectedProject }) {
|
|
|
5535
5586
|
</div>
|
|
5536
5587
|
</div>
|
|
5537
5588
|
`}
|
|
5589
|
+
${item && item.status === 'Superseded' && auditEvents.length > 0 && html`
|
|
5590
|
+
<div class="detail-section" style="padding:12px 24px 0;" data-testid="audit-trail-section">
|
|
5591
|
+
<h4 class="detail-section-title" style="margin:0 0 8px 0;font-size:13px;font-weight:600;">Audit Trail</h4>
|
|
5592
|
+
<div class="audit-timeline">
|
|
5593
|
+
${auditEvents.map(ev => {
|
|
5594
|
+
const payload = (ev && ev.payload) || {};
|
|
5595
|
+
const isCascade = ev.actor === 'cascade';
|
|
5596
|
+
return html`
|
|
5597
|
+
<div class="audit-entry" key=${ev.id} data-testid="audit-entry">
|
|
5598
|
+
<div class="audit-entry-header">
|
|
5599
|
+
<span class="audit-actor" data-testid="audit-actor">${isCascade ? 'Auto-cascaded' : 'Status changed'}</span>
|
|
5600
|
+
<span class="audit-time" data-testid="audit-time">${timeAgo(ev.timestamp)}</span>
|
|
5601
|
+
</div>
|
|
5602
|
+
<div class="audit-entry-body">
|
|
5603
|
+
<span class="audit-from" data-testid="audit-from-status">From: <strong>${payload.from_status || ''}</strong></span>
|
|
5604
|
+
${payload.superseded_by && html`
|
|
5605
|
+
<span class="audit-successor">
|
|
5606
|
+
Successor: <a href="#" data-testid="audit-successor-link" onClick=${(e) => {
|
|
5607
|
+
e.preventDefault();
|
|
5608
|
+
const target = allItems && allItems.find ? allItems.find(i => String(i.id) === String(payload.superseded_by)) : null;
|
|
5609
|
+
if (target && onSelectItem) onSelectItem(target);
|
|
5610
|
+
}}>#${payload.superseded_by}</a>
|
|
5611
|
+
</span>
|
|
5612
|
+
`}
|
|
5613
|
+
${payload.cascade_source && html`
|
|
5614
|
+
<span class="audit-cascade">
|
|
5615
|
+
Cascaded from parent: <a href="#" data-testid="audit-cascade-source" onClick=${(e) => {
|
|
5616
|
+
e.preventDefault();
|
|
5617
|
+
const target = allItems && allItems.find ? allItems.find(i => String(i.id) === String(payload.cascade_source)) : null;
|
|
5618
|
+
if (target && onSelectItem) onSelectItem(target);
|
|
5619
|
+
}}>#${payload.cascade_source}</a>
|
|
5620
|
+
</span>
|
|
5621
|
+
`}
|
|
5622
|
+
${payload.superseded_reason && html`
|
|
5623
|
+
<div class="audit-reason" data-testid="audit-reason">${payload.superseded_reason}</div>
|
|
5624
|
+
`}
|
|
5625
|
+
</div>
|
|
5626
|
+
</div>
|
|
5627
|
+
`;
|
|
5628
|
+
})}
|
|
5629
|
+
</div>
|
|
5630
|
+
</div>
|
|
5631
|
+
`}
|
|
5538
5632
|
${(loadingAttachments || attachments.length > 0) && html`
|
|
5539
5633
|
<div style="padding:12px 24px 0;">
|
|
5540
5634
|
<h4 style="margin:0 0 8px 0;font-size:13px;font-weight:600;">
|
|
@@ -6931,7 +7025,7 @@ function BoardPage({ selectedProject }) {
|
|
|
6931
7025
|
`}
|
|
6932
7026
|
|
|
6933
7027
|
${showCreateDialog && html`<${CreateTaskDialog} onClose=${() => setShowCreateDialog(false)} onCreated=${fetchItems} />`}
|
|
6934
|
-
${selectedItem && html`<${ItemDetailSidebar} item=${selectedItem} selectedProject=${selectedProject} onClose=${() => setSelectedItem(null)} onStatusChange=${() => { fetchItems(); setSelectedItem(null); }} />`}
|
|
7028
|
+
${selectedItem && html`<${ItemDetailSidebar} item=${selectedItem} selectedProject=${selectedProject} allItems=${items} onSelectItem=${setSelectedItem} onClose=${() => setSelectedItem(null)} onStatusChange=${() => { fetchItems(); setSelectedItem(null); }} />`}
|
|
6935
7029
|
</div>
|
|
6936
7030
|
`;
|
|
6937
7031
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
7350789bf2ce5bca2ca226ac0e7e8f656012caf4
|
package/dist/web/build-stamp.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
20260509-
|
|
1
|
+
20260509-122800-7350789
|