@beastmode-develeap/beastmode 0.1.159 → 0.1.160

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__ = "20260502-125142-97d09bd";</script>
18
+ <script>window.__BUILD_STAMP__ = "20260502-170747-d286287";</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">
@@ -1271,6 +1271,24 @@ input[type="range"]::-webkit-slider-thumb {
1271
1271
  color: #38bdf8;
1272
1272
  }
1273
1273
 
1274
+ /* Environment status dot inside the badge — Story 7 */
1275
+ .badge-env-dot {
1276
+ display: inline-block;
1277
+ width: 6px;
1278
+ height: 6px;
1279
+ border-radius: 50%;
1280
+ margin-right: 4px;
1281
+ vertical-align: middle;
1282
+ flex-shrink: 0;
1283
+ }
1284
+ .badge-env-dot-passed { background: #34d399; }
1285
+ .badge-env-dot-failed { background: #f87171; }
1286
+ .badge-env-dot-running,
1287
+ .badge-env-dot-verifying { background: #fbbf24; }
1288
+ .badge-env-dot-deploying { background: #60a5fa; }
1289
+ .badge-env-dot-awaiting_approval { background: #fbbf24; animation: pulse-dot 1.5s ease-in-out infinite; }
1290
+ .badge-env-dot-pending { background: #666666; }
1291
+
1274
1292
  /* Environment Management Panel (Story 9) */
1275
1293
  .env-panel {
1276
1294
  margin-top: 12px;
@@ -5223,6 +5241,7 @@ function PipelineView({
5223
5241
  cycleSort,
5224
5242
  sortColumnItems,
5225
5243
  costsByItem,
5244
+ envVerifyByItem,
5226
5245
  }) {
5227
5246
  const [collapseKey, setCollapseKey] = useState(0);
5228
5247
  const [, setEpicCollapseKey] = useState(0);
@@ -5255,8 +5274,17 @@ function PipelineView({
5255
5274
  ${(() => {
5256
5275
  const env = item.extra && item.extra.current_env;
5257
5276
  if (!env) return null;
5258
- return html`<span class=${'card-badge badge-env badge-env-' + env}
5259
- title=${'Environment: ' + env}>${env}</span>`;
5277
+ const envStatus = envVerifyByItem && envVerifyByItem[String(item.id)];
5278
+ const currentEnvEntry = envStatus && Array.isArray(envStatus.environments)
5279
+ ? envStatus.environments.find(e => e.name === env)
5280
+ : null;
5281
+ const dotStatus = currentEnvEntry ? currentEnvEntry.status : null;
5282
+ const titleText = dotStatus
5283
+ ? 'Environment: ' + env + ' (' + dotStatus + ')'
5284
+ : 'Environment: ' + env;
5285
+ return html`<span class=${'card-badge badge-env badge-env-' + env} title=${titleText}>
5286
+ ${dotStatus ? html`<span class=${'badge-env-dot badge-env-dot-' + dotStatus}></span>` : null}${env}
5287
+ </span>`;
5260
5288
  })()}
5261
5289
  ${(() => {
5262
5290
  const src = item.status_changed_at || item.updated_at || item.created_at;
@@ -5555,6 +5583,7 @@ function BoardPage({ selectedProject }) {
5555
5583
  const [columnSorts, setColumnSorts] = useState({});
5556
5584
  const [epicCollapseKey, setEpicCollapseKey] = useState(0);
5557
5585
  const [costsByItem, setCostsByItem] = useState({});
5586
+ const [envVerifyByItem, setEnvVerifyByItem] = useState({});
5558
5587
  const [viewMode, setViewMode] = useState(() => {
5559
5588
  try {
5560
5589
  const saved = localStorage.getItem('beastmode-view-mode');
@@ -5632,6 +5661,37 @@ function BoardPage({ selectedProject }) {
5632
5661
  .catch(() => {});
5633
5662
  }, [selectedProject]);
5634
5663
 
5664
+ // Story 7: batch-fetch env verify status for items that have a current_env.
5665
+ // The endpoint is per-item, so we issue parallel requests with allSettled
5666
+ // — failed individual fetches don't block the others, and the badge falls
5667
+ // back to "no dot" when data is missing.
5668
+ const fetchEnvStatuses = useCallback((itemList) => {
5669
+ if (!Array.isArray(itemList)) return;
5670
+ const itemsWithEnv = itemList.filter(i => i && i.extra && i.extra.current_env);
5671
+ if (itemsWithEnv.length === 0) {
5672
+ setEnvVerifyByItem({});
5673
+ return;
5674
+ }
5675
+ const proj = localStorage.getItem('beastmode-selected-project') || '';
5676
+ const projParam = (proj && proj !== 'all')
5677
+ ? '&project=' + encodeURIComponent(proj)
5678
+ : '';
5679
+ Promise.allSettled(
5680
+ itemsWithEnv.map(item =>
5681
+ fetch('/api/environments/verify-status?item_id=' + encodeURIComponent(item.id) + projParam)
5682
+ .then(r => r.ok ? r.json() : null)
5683
+ )
5684
+ ).then(results => {
5685
+ const byItem = {};
5686
+ results.forEach((result, idx) => {
5687
+ if (result.status === 'fulfilled' && result.value) {
5688
+ byItem[String(itemsWithEnv[idx].id)] = result.value;
5689
+ }
5690
+ });
5691
+ setEnvVerifyByItem(byItem);
5692
+ }).catch(() => {});
5693
+ }, [selectedProject]);
5694
+
5635
5695
  // Re-fetch whenever the selected project changes — each project
5636
5696
  // has its own SQLite board on the server.
5637
5697
  // Also poll every 10s for live updates from the daemon.
@@ -5648,6 +5708,14 @@ function BoardPage({ selectedProject }) {
5648
5708
  return () => clearInterval(interval);
5649
5709
  }, [selectedProject]);
5650
5710
 
5711
+ // Story 7: refresh env verify status when items change, plus a
5712
+ // 30s background refresh while the page is open.
5713
+ useEffect(() => {
5714
+ fetchEnvStatuses(items);
5715
+ const t = setInterval(() => fetchEnvStatuses(items), 30000);
5716
+ return () => clearInterval(t);
5717
+ }, [items, fetchEnvStatuses]);
5718
+
5651
5719
  // Layout test surface: expose column metrics on window for scenario
5652
5720
  // verification. Guards on !loading and items.length > 0 so metrics are
5653
5721
  // only exposed once the board has actually rendered content.
@@ -6218,6 +6286,7 @@ function BoardPage({ selectedProject }) {
6218
6286
  cycleSort=${cycleSort}
6219
6287
  sortColumnItems=${sortColumnItems}
6220
6288
  costsByItem=${costsByItem}
6289
+ envVerifyByItem=${envVerifyByItem}
6221
6290
  />`
6222
6291
  : html`
6223
6292
  <div class="kanban-wrapper">
@@ -6291,8 +6360,17 @@ function BoardPage({ selectedProject }) {
6291
6360
  ${(() => {
6292
6361
  const env = item.extra && item.extra.current_env;
6293
6362
  if (!env) return null;
6294
- return html`<span class=${'card-badge badge-env badge-env-' + env}
6295
- title=${'Environment: ' + env}>${env}</span>`;
6363
+ const envStatus = envVerifyByItem && envVerifyByItem[String(item.id)];
6364
+ const currentEnvEntry = envStatus && Array.isArray(envStatus.environments)
6365
+ ? envStatus.environments.find(e => e.name === env)
6366
+ : null;
6367
+ const dotStatus = currentEnvEntry ? currentEnvEntry.status : null;
6368
+ const titleText = dotStatus
6369
+ ? 'Environment: ' + env + ' (' + dotStatus + ')'
6370
+ : 'Environment: ' + env;
6371
+ return html`<span class=${'card-badge badge-env badge-env-' + env} title=${titleText}>
6372
+ ${dotStatus ? html`<span class=${'badge-env-dot badge-env-dot-' + dotStatus}></span>` : null}${env}
6373
+ </span>`;
6296
6374
  })()}
6297
6375
  ${(() => {
6298
6376
  const src = item.status_changed_at || item.updated_at || item.created_at;
@@ -1 +1 @@
1
- 97d09bdc40fb20a840f13d4b5bb0364195d6c540
1
+ d28628735a7f09d061b14fb51be8c017eeb56095
@@ -1 +1 @@
1
- 20260502-125142-97d09bd
1
+ 20260502-170747-d286287
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beastmode-develeap/beastmode",
3
- "version": "0.1.159",
3
+ "version": "0.1.160",
4
4
  "description": "BeastMode Dark Factory — turn intent into verified software",
5
5
  "type": "module",
6
6
  "bin": {