@atolis-hq/wake 0.2.24 → 0.2.26

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.
@@ -48,7 +48,7 @@ export const indexHtml = `<!DOCTYPE html>
48
48
  nav button:hover { color: #fff; }
49
49
  nav button.active { color: var(--accent-light); border-bottom-color: var(--accent); }
50
50
  main { padding: 1rem; }
51
- .columns { display: grid; grid-template-columns: repeat(6, minmax(180px, 1fr)); gap: 0.6rem; overflow-x: auto; }
51
+ .columns { display: grid; grid-template-columns: repeat(5, minmax(180px, 1fr)); gap: 0.6rem; overflow-x: auto; }
52
52
  .col { background: #1a1d23; border-radius: 10px; padding: 0.5rem; min-height: 200px; }
53
53
  .col h2 { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.04em; color: #9aa2ad; margin: 0.2rem 0.4rem 0.5rem; }
54
54
  .card { background: #22262e; border: 1px solid #2c313a; border-radius: 8px; padding: 0.5rem; margin-bottom: 0.5rem; cursor: pointer; font-size: 0.8rem; transition: border-color 0.12s ease; }
@@ -140,7 +140,7 @@ export const indexHtml = `<!DOCTYPE html>
140
140
  </div>
141
141
  <script>
142
142
  const API = '/api/v1';
143
- const CONDITIONS = ['needs-human', 'active', 'ready', 'waiting', 'stalled', 'finished'];
143
+ const CONDITIONS = ['ready', 'active', 'needs-human', 'error', 'finished'];
144
144
  let currentView = 'board';
145
145
  let analyticsWindow = '7d';
146
146
  let analyticsMetric = 'runs-over-time';
@@ -164,6 +164,7 @@ const METRIC_OPTIONS = [
164
164
  ['duration-over-time', 'Duration over time'],
165
165
  ['work-items-over-time', 'Work items completed over time'],
166
166
  ['work-item-durations', 'Work item e2e duration'],
167
+ ['work-item-totals', 'Work item totals'],
167
168
  ];
168
169
 
169
170
  async function getJson(path, signal) {
@@ -640,6 +641,20 @@ function renderWorkItemDurations(rows) {
640
641
  ]);
641
642
  }
642
643
 
644
+ function renderWorkItemTotals(rows) {
645
+ if (rows.length === 0) return el('p', { class: 'meta', text: 'No runs for this window.' });
646
+ const maxTokens = Math.max(...rows.map((row) => row.totalTokens));
647
+ return el('table', {}, [
648
+ el('tr', {}, ['work item', 'runs', 'total tokens', 'total duration'].map((h) => el('th', { text: h }))),
649
+ ...rows.map((row) => el('tr', {}, [
650
+ el('td', { text: row.key }),
651
+ el('td', { text: String(row.runCount) }),
652
+ metricValueCell(row.totalTokens, maxTokens, fmtNumber),
653
+ el('td', { text: fmtMs(row.totalDurationMs) }),
654
+ ])),
655
+ ]);
656
+ }
657
+
643
658
  function renderMetricDetail(detail) {
644
659
  if (detail.kind === 'runs-over-time') return renderRunsOverTime(detail.rows);
645
660
  if (detail.kind === 'runs-by-status-over-time') return renderRunsByStatusOverTime(detail.rows);
@@ -650,6 +665,7 @@ function renderMetricDetail(detail) {
650
665
  if (detail.kind === 'duration-over-time') return renderDurationTable(detail.rows, 'bucket');
651
666
  if (detail.kind === 'work-items-over-time') return renderWorkItemsOverTime(detail.rows);
652
667
  if (detail.kind === 'work-item-durations') return renderWorkItemDurations(detail.rows);
668
+ if (detail.kind === 'work-item-totals') return renderWorkItemTotals(detail.rows);
653
669
  return el('p', { class: 'meta', text: 'Unsupported metric.' });
654
670
  }
655
671
 
@@ -63,10 +63,10 @@ function deriveCondition(item, lastRun, config) {
63
63
  const workflow = workflowForProjection(item, config);
64
64
  const hasRoute = config.stages[stage] !== undefined || workflow?.stages[stage] !== undefined;
65
65
  if (!hasRoute) {
66
- return { condition: 'stalled', reason: `no route configured for stage "${stage}"` };
66
+ return { condition: 'error', reason: `no route configured for stage "${stage}"` };
67
67
  }
68
68
  if (lastRun?.sentinel === 'FAILED') {
69
- return { condition: 'waiting', reason: 'last run failed; awaiting operator/retry policy' };
69
+ return { condition: 'error', reason: 'last run failed; awaiting operator/retry policy' };
70
70
  }
71
71
  return { condition: 'ready', reason: 'has a route and no blocking condition' };
72
72
  }
@@ -139,8 +139,7 @@ export async function buildStatus(input) {
139
139
  'needs-human': 0,
140
140
  active: 0,
141
141
  ready: 0,
142
- waiting: 0,
143
- stalled: 0,
142
+ error: 0,
144
143
  finished: 0,
145
144
  };
146
145
  for (const card of board) {
@@ -382,6 +381,7 @@ const metricsMetrics = new Set([
382
381
  'duration-over-time',
383
382
  'work-items-over-time',
384
383
  'work-item-durations',
384
+ 'work-item-totals',
385
385
  ]);
386
386
  function parseMetricsWindow(value) {
387
387
  return metricsWindows.has(value) ? value : '7d';
@@ -868,6 +868,27 @@ export async function buildMetrics(input) {
868
868
  summary,
869
869
  detail: { kind: 'work-item-durations', rows: workItemDurations },
870
870
  };
871
+ case 'work-item-totals': {
872
+ const groups = new Map();
873
+ for (const run of runs) {
874
+ const key = run.workItemKey;
875
+ const existing = groups.get(key) ?? { runCount: 0, totalTokens: 0, totalDurationMs: 0 };
876
+ existing.runCount += 1;
877
+ existing.totalTokens += runTokenTotal(run);
878
+ existing.totalDurationMs += runDurationMs(run) ?? 0;
879
+ groups.set(key, existing);
880
+ }
881
+ const rows = [...groups.entries()]
882
+ .map(([key, value]) => ({ key, ...value }))
883
+ .sort((left, right) => right.totalTokens - left.totalTokens || left.key.localeCompare(right.key));
884
+ return {
885
+ window,
886
+ metric,
887
+ generatedAt: input.now.toISOString(),
888
+ summary,
889
+ detail: { kind: 'work-item-totals', rows },
890
+ };
891
+ }
871
892
  case 'runs-over-time':
872
893
  return {
873
894
  window,
@@ -124,4 +124,4 @@ export function resolveWakeVersion(options = {}) {
124
124
  }
125
125
  return '0.1.0-dev';
126
126
  }
127
- export const wakeVersion = "g948ed5f";
127
+ export const wakeVersion = "gf6fad76";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atolis-hq/wake",
3
- "version": "0.2.24",
3
+ "version": "0.2.26",
4
4
  "description": "Local autonomous agent control plane for software development",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {