@beastmode-develeap/beastmode 0.1.212 → 0.1.213

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.
@@ -15,7 +15,7 @@
15
15
  }
16
16
  </script>
17
17
  <!--BOARD_DATA-->
18
- <script>window.__BUILD_STAMP__ = "20260509-145929-6395b56";</script>
18
+ <script>window.__BUILD_STAMP__ = "20260509-151332-bb5cfbc";</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">
@@ -1688,6 +1688,29 @@ input[type="range"]::-webkit-slider-thumb {
1688
1688
  color: #f97316;
1689
1689
  border: 1px solid rgba(249, 115, 22, 0.4);
1690
1690
  }
1691
+ .badge-superseded {
1692
+ background: rgba(100, 116, 139, 0.2);
1693
+ color: #94a3b8;
1694
+ border: 1px solid rgba(100, 116, 139, 0.4);
1695
+ text-decoration: line-through;
1696
+ }
1697
+ .kanban-card[data-overlay="superseded"] {
1698
+ opacity: 0.6;
1699
+ }
1700
+ .kanban-card[data-overlay="superseded"] .card-title {
1701
+ text-decoration: line-through;
1702
+ color: var(--text-muted);
1703
+ }
1704
+ .badge-successor {
1705
+ background: rgba(100, 116, 139, 0.15);
1706
+ color: #94a3b8;
1707
+ cursor: pointer;
1708
+ text-decoration: none;
1709
+ }
1710
+ .badge-successor:hover {
1711
+ background: rgba(100, 116, 139, 0.3);
1712
+ color: #cbd5e1;
1713
+ }
1691
1714
 
1692
1715
  /* Card-level visual treatment for overlay statuses */
1693
1716
  .kanban-card[data-overlay="stuck"] {
@@ -4382,7 +4405,9 @@ function isOverlayStatus(status) {
4382
4405
  const overlays = (typeof PIPELINE_CONFIG !== 'undefined' && PIPELINE_CONFIG && PIPELINE_CONFIG.overlay_statuses)
4383
4406
  ? PIPELINE_CONFIG.overlay_statuses
4384
4407
  : ['Stuck', 'Awaiting Input'];
4385
- return overlays.includes(status);
4408
+ if (overlays.includes(status)) return true;
4409
+ if (status === 'Superseded') return true;
4410
+ return false;
4386
4411
  }
4387
4412
 
4388
4413
  function overlayBadgeClass(status) {
@@ -4390,6 +4415,7 @@ function overlayBadgeClass(status) {
4390
4415
  const s = status.toLowerCase();
4391
4416
  if (s === 'stuck') return 'badge-overlay-stuck';
4392
4417
  if (s === 'awaiting input') return 'badge-overlay-awaiting';
4418
+ if (s === 'superseded') return 'badge-superseded';
4393
4419
  return '';
4394
4420
  }
4395
4421
 
@@ -4398,6 +4424,7 @@ function overlayBadgeLabel(status) {
4398
4424
  const s = status.toLowerCase();
4399
4425
  if (s === 'stuck') return '\u26A0 Stuck';
4400
4426
  if (s === 'awaiting input') return '\u23F3 Awaiting Input';
4427
+ if (s === 'superseded') return 'Superseded';
4401
4428
  return status;
4402
4429
  }
4403
4430
 
@@ -4406,6 +4433,7 @@ function overlayKey(status) {
4406
4433
  const s = status.toLowerCase();
4407
4434
  if (s === 'stuck') return 'stuck';
4408
4435
  if (s === 'awaiting input') return 'awaiting-input';
4436
+ if (s === 'superseded') return 'superseded';
4409
4437
  return null;
4410
4438
  }
4411
4439
 
@@ -4414,6 +4442,7 @@ function overlayTooltip(status) {
4414
4442
  const s = status.toLowerCase();
4415
4443
  if (s === 'stuck') return 'Task is stuck after max retries. Comment \'reset\' to restart or investigate the failure.';
4416
4444
  if (s === 'awaiting input') return 'BeastMode needs your answer to a question before continuing. Check the task updates.';
4445
+ if (s === 'superseded') return 'This item has been superseded by another item. It is terminal and cannot be reactivated.';
4417
4446
  return '';
4418
4447
  }
4419
4448
 
@@ -4566,6 +4595,32 @@ function partitionByEpic(columnItems, allItems) {
4566
4595
  groups[epicId].epicName = groups[epicId].epic.name;
4567
4596
  groups[epicId].epicStatus = groups[epicId].epic.status;
4568
4597
  }
4598
+ const allChildren = allItems.filter(i => String(i.parent_epic) === String(epicId));
4599
+ let doneCount = 0;
4600
+ let supersededCount = 0;
4601
+ let activeCount = 0;
4602
+ let mostCommonSuccessor = null;
4603
+ const successorCounts = {};
4604
+ for (const child of allChildren) {
4605
+ if (child.status === 'Done') {
4606
+ doneCount++;
4607
+ } else if (child.status === 'Superseded') {
4608
+ supersededCount++;
4609
+ const sby = child.extra && child.extra.superseded_by;
4610
+ if (sby) {
4611
+ successorCounts[sby] = (successorCounts[sby] || 0) + 1;
4612
+ }
4613
+ } else {
4614
+ activeCount++;
4615
+ }
4616
+ }
4617
+ if (supersededCount > 0) {
4618
+ let maxCount = 0;
4619
+ for (const [id, count] of Object.entries(successorCounts)) {
4620
+ if (count > maxCount) { maxCount = count; mostCommonSuccessor = id; }
4621
+ }
4622
+ }
4623
+ groups[epicId].breakdown = { doneCount, supersededCount, activeCount, mostCommonSuccessor };
4569
4624
  }
4570
4625
 
4571
4626
  const sortedGroupKeys = Object.keys(groups).sort((a, b) => {
@@ -5419,7 +5474,23 @@ function ItemDetailSidebar({ item, onClose, onStatusChange, selectedProject, all
5419
5474
  <aside class="detail-sidebar open" ref=${sidebarRef}>
5420
5475
  <div class="detail-resize-handle" onMouseDown=${onResizeStart}></div>
5421
5476
  <div class="detail-header">
5422
- <h3>${item.name || item.title}</h3>
5477
+ <h3 style=${item.status === 'Superseded' ? 'text-decoration:line-through;color:var(--text-muted);' : ''}>${item.name || item.title}</h3>
5478
+ ${item.status === 'Superseded' && html`
5479
+ <div class="detail-superseded-info" data-testid="sidebar-superseded-info"
5480
+ style="display:flex;align-items:center;gap:8px;padding:4px 0 8px;font-size:13px;color:var(--text-muted);">
5481
+ <span class="badge-superseded" style="font-size:11px;padding:2px 8px;border-radius:4px;">Superseded</span>
5482
+ ${item.extra && item.extra.superseded_by && html`
5483
+ <span>\u2192</span>
5484
+ <a href="#" data-testid="sidebar-successor-link"
5485
+ style="color:var(--accent);text-decoration:none;font-family:var(--font-mono);font-size:12px;"
5486
+ onClick=${(e) => {
5487
+ e.preventDefault();
5488
+ const target = allItems && allItems.find ? allItems.find(i => String(i.id) === String(item.extra.superseded_by)) : null;
5489
+ if (target && onSelectItem) onSelectItem(target);
5490
+ }}>#${item.extra.superseded_by}</a>
5491
+ `}
5492
+ </div>
5493
+ `}
5423
5494
  <button class="detail-close" onClick=${onClose}>\u00d7</button>
5424
5495
  </div>
5425
5496
  <div class="detail-meta">
@@ -5849,6 +5920,15 @@ function PipelineView({
5849
5920
  <div class="card-title" style="cursor:pointer;" onClick=${() => setSelectedItem(item)} title=${item.name || item.title}>${item.name || item.title}</div>
5850
5921
  <div class="card-footer">
5851
5922
  ${isOverlayStatus(item.status) && html`<span class=${'card-badge badge-overlay ' + overlayBadgeClass(item.status)} title=${overlayTooltip(item.status)}>${overlayBadgeLabel(item.status)}</span>`}
5923
+ ${item.extra && item.extra.superseded_by && html`<a class="card-badge badge-successor"
5924
+ href="#" data-testid="card-successor-link"
5925
+ title=${'Superseded by #' + item.extra.superseded_by}
5926
+ onClick=${(e) => {
5927
+ e.preventDefault();
5928
+ e.stopPropagation();
5929
+ const target = filteredItems.find(i => String(i.id) === String(item.extra.superseded_by));
5930
+ if (target) setSelectedItem(target);
5931
+ }}>→ #${item.extra.superseded_by}</a>`}
5852
5932
  ${!isParentEpic && item.parent_epic && html`<span class="card-badge badge-epic">epic:${item.parent_epic}</span>`}
5853
5933
  ${item.priority && html`<span class=${'card-badge ' + priorityBadgeClass(item.priority)}>${item.priority}</span>`}
5854
5934
  ${item.task_type && html`<span class="card-badge badge-type">${item.task_type}</span>`}
@@ -5957,6 +6037,19 @@ function PipelineView({
5957
6037
  <span class="epic-group-color" style="background: var(--accent)"></span>
5958
6038
  <span class="epic-group-name">${group.epicName}</span>
5959
6039
  <span class="epic-group-count">${totalCount}</span>
6040
+ ${(() => {
6041
+ const bd = group.breakdown;
6042
+ if (!bd || (bd.doneCount === 0 && bd.supersededCount === 0)) return null;
6043
+ const parts = [];
6044
+ if (bd.doneCount > 0) parts.push(bd.doneCount + ' Done');
6045
+ if (bd.supersededCount > 0) parts.push(bd.supersededCount + ' Superseded');
6046
+ if (bd.activeCount > 0) parts.push(bd.activeCount + ' Active');
6047
+ return html`<span class="epic-group-breakdown" data-testid="epic-group-breakdown"
6048
+ style="font-size:10px;color:var(--text-muted);margin-left:4px;">(${parts.join(', ')}${bd.mostCommonSuccessor ? html` → <a href="#" data-testid="epic-breakdown-successor-link" style="color:var(--accent);text-decoration:none;" onClick=${(e) => {
6049
+ e.preventDefault();
6050
+ e.stopPropagation();
6051
+ }}>#${bd.mostCommonSuccessor}</a>` : ''})</span>`;
6052
+ })()}
5960
6053
  </div>
5961
6054
  <div class="epic-group-body" id=${egBodyId}>
5962
6055
  ${group.epic && renderCard(group.epic, meta.status, true)}
@@ -6957,6 +7050,15 @@ function BoardPage({ selectedProject }) {
6957
7050
  <div class="card-title" style="cursor:pointer;" onClick=${() => setSelectedItem(item)} title=${item.name || item.title}>${item.name || item.title}</div>
6958
7051
  <div class="card-footer">
6959
7052
  ${isOverlayStatus(item.status) && html`<span class=${'card-badge badge-overlay ' + overlayBadgeClass(item.status)} title=${overlayTooltip(item.status)}>${overlayBadgeLabel(item.status)}</span>`}
7053
+ ${item.extra && item.extra.superseded_by && html`<a class="card-badge badge-successor"
7054
+ href="#" data-testid="card-successor-link"
7055
+ title=${'Superseded by #' + item.extra.superseded_by}
7056
+ onClick=${(e) => {
7057
+ e.preventDefault();
7058
+ e.stopPropagation();
7059
+ const target = swimlaneFilteredItems.find(i => String(i.id) === String(item.extra.superseded_by));
7060
+ if (target) setSelectedItem(target);
7061
+ }}>→ #${item.extra.superseded_by}</a>`}
6960
7062
  ${!isParentEpic && item.parent_epic && html`<span class="card-badge badge-epic">epic:${item.parent_epic}</span>`}
6961
7063
  ${item.priority && html`<span class=${'card-badge ' + priorityBadgeClass(item.priority)}>${item.priority}</span>`}
6962
7064
  ${item.task_type && html`<span class="card-badge badge-type">${item.task_type}</span>`}
@@ -7006,6 +7108,19 @@ function BoardPage({ selectedProject }) {
7006
7108
  <span class="epic-group-color" style="background: var(--accent)"></span>
7007
7109
  <span class="epic-group-name">${group.epicName}</span>
7008
7110
  <span class="epic-group-count">${totalCount}</span>
7111
+ ${(() => {
7112
+ const bd = group.breakdown;
7113
+ if (!bd || (bd.doneCount === 0 && bd.supersededCount === 0)) return null;
7114
+ const parts = [];
7115
+ if (bd.doneCount > 0) parts.push(bd.doneCount + ' Done');
7116
+ if (bd.supersededCount > 0) parts.push(bd.supersededCount + ' Superseded');
7117
+ if (bd.activeCount > 0) parts.push(bd.activeCount + ' Active');
7118
+ return html`<span class="epic-group-breakdown" data-testid="epic-group-breakdown"
7119
+ style="font-size:10px;color:var(--text-muted);margin-left:4px;">(${parts.join(', ')}${bd.mostCommonSuccessor ? html` → <a href="#" data-testid="epic-breakdown-successor-link" style="color:var(--accent);text-decoration:none;" onClick=${(e) => {
7120
+ e.preventDefault();
7121
+ e.stopPropagation();
7122
+ }}>#${bd.mostCommonSuccessor}</a>` : ''})</span>`;
7123
+ })()}
7009
7124
  </div>
7010
7125
  <div class="epic-group-body" id=${bodyId}>
7011
7126
  ${group.epic && renderCard(group.epic, true)}
@@ -1 +1 @@
1
- 6395b562346253985efd5667de1e2809baa36bf0
1
+ bb5cfbcb14116ecf6845a1f8dd4282def11ac1a5
@@ -1 +1 @@
1
- 20260509-145929-6395b56
1
+ 20260509-151332-bb5cfbc
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beastmode-develeap/beastmode",
3
- "version": "0.1.212",
3
+ "version": "0.1.213",
4
4
  "description": "BeastMode Dark Factory — turn intent into verified software",
5
5
  "type": "module",
6
6
  "bin": {