}>
diff --git a/apps/ui/src/pages/TaskDetail.tsx b/apps/ui/src/pages/TaskDetail.tsx
index 88227c5..9a9378d 100644
--- a/apps/ui/src/pages/TaskDetail.tsx
+++ b/apps/ui/src/pages/TaskDetail.tsx
@@ -7,9 +7,11 @@ import { formatBytes, formatCount, formatDuration, formatPercent, formatRelative
export function TaskDetail() {
const params = useParams<{ id: string }>()
+ // @solidjs/router gives the raw URL segment; decode for display + API use.
+ const taskId = () => decodeURIComponent(params.id)
const origin = getOriginSignal()
const [detail] = createResource(
- () => ({ id: params.id, o: origin() }),
+ () => ({ id: taskId(), o: origin() }),
(args) => getTaskDetail(args.id),
)
@@ -23,7 +25,7 @@ export function TaskDetail() {
@@ -33,7 +35,7 @@ export function TaskDetail() {
Failed to load: {String(detail.error)}
-
+
diff --git a/apps/ui/src/pages/Trends.tsx b/apps/ui/src/pages/Trends.tsx
index 3d06786..3cdc58e 100644
--- a/apps/ui/src/pages/Trends.tsx
+++ b/apps/ui/src/pages/Trends.tsx
@@ -99,16 +99,16 @@ export function Trends() {
i))].reverse()}
+ xs={[...(parallel() ?? [])].reverse().map((p) => p.startedAt)}
series={[
{
name: 'parallelism',
strokeClass: 'stroke-chart-3',
areaClass: 'fill-chart-3/10',
- data: [...(parallel() ?? []).map((p) => p.factor)].reverse(),
+ data: [...(parallel() ?? [])].reverse().map((p) => p.factor),
},
]}
- formatX={(x) => `#${x}`}
+ formatX={(t) => formatDate(t)}
formatY={(v) => v.toFixed(1) + '×'}
height={140}
/>
diff --git a/apps/ui/uno.config.ts b/apps/ui/uno.config.ts
index d91f451..96e87b8 100644
--- a/apps/ui/uno.config.ts
+++ b/apps/ui/uno.config.ts
@@ -3,6 +3,19 @@ import { defineConfig, presetIcons, presetUno, transformerVariantGroup } from 'u
export default defineConfig({
presets: [presetUno(), presetIcons({ scale: 1.0 })],
transformers: [transformerVariantGroup()],
+ // Chart palette classes are computed from project names at runtime via
+ // `paletteFor()` — UnoCSS's static analyzer can't see them, so we list
+ // them explicitly.
+ safelist: [
+ ...['1', '2', '3', '4', '5', '6', '7', '8'].flatMap((n) => [
+ `bg-chart-${n}`,
+ `text-chart-${n}`,
+ `stroke-chart-${n}`,
+ `fill-chart-${n}`,
+ `fill-chart-${n}/10`,
+ `border-chart-${n}`,
+ ]),
+ ],
theme: {
colors: {
// Surfaces
diff --git a/src/orchestrator/metrics.ts b/src/orchestrator/metrics.ts
index d242eb2..313d0f1 100644
--- a/src/orchestrator/metrics.ts
+++ b/src/orchestrator/metrics.ts
@@ -901,6 +901,9 @@ export interface ParallelismPoint {
/** Per-invocation parallelism, recent first. */
export function getParallelismHistory(db: Database, limit = 50): ParallelismPoint[] {
+ // Filter out trivially-short invocations (wall < 50 ms): the cpu/wall
+ // ratio is dominated by measurement noise there and produces 0.5×/2×
+ // junk that pollutes the chart's average.
const rows = db
.query(
`SELECT run_id AS runId,
@@ -912,7 +915,7 @@ export function getParallelismHistory(db: Database, limit = 50): ParallelismPoin
FROM runs
WHERE run_id IS NOT NULL
GROUP BY run_id
- HAVING taskCount > 0
+ HAVING taskCount > 1 AND (MAX(ended_at) - MIN(started_at)) >= 50
ORDER BY MAX(started_at) DESC
LIMIT ?`,
)