// Timeline (Gantt-style swimlanes) + Activity feed views /* ---------------- Timeline ---------------- */ // Window: -75min … +25min relative to "now". 100 units wide, now at 75%. // left% = minutesRelativeToNow + 75 ; width% = durationMinutes const TL_WINDOW = 100; const TL_NOW = 75; // Deterministic timing per task id, in minutes relative to now (neg = past). const TL_TIMING = { // installer-agent 'TSK-3964': { start: -68, end: -54 }, // done · Install Auth 'TSK-3965': { start: -50, end: -40 }, // done · Bump Next 'TSK-3954': { start: -32, end: -20, halt: true }, // failed · Analytics 'TSK-3999': { start: -14, end: 22 }, // running 28% 'TSK-4006': { start: 2, end: 14 }, // ready 'TSK-4012': { start: 16, end: 24 }, // backlog // tester-agent 'TSK-4000': { start: -22, end: 4 }, // running 81% 'TSK-4008': { start: 6, end: 20 }, // ready // migrator-agent 'TSK-3998': { start: -28, end: 12 }, // running 62% 'TSK-4015': { start: 14, end: 24 }, // backlog // reviewer-agent 'TSK-3987': { start: -45, end: -29, await: true }, // review 'TSK-3988': { start: -27, end: -15, await: true }, // review // sentinel-agent 'TSK-3966': { start: -67, end: -53 }, // done · autoscaler 'TSK-4007': { start: 1, end: 9 }, // ready 'TSK-4013': { start: 11, end: 21 }, // backlog }; const TL_LANES = [ { agent: 'installer-agent', kind: 'installer' }, { agent: 'migrator-agent', kind: 'migrator' }, { agent: 'tester-agent', kind: 'tester' }, { agent: 'reviewer-agent', kind: 'reviewer' }, { agent: 'sentinel-agent', kind: 'sentinel' }, ]; const TL_TICKS = [-75, -60, -45, -30, -15, 0, 15, 25]; function tickLabel(m) { if (m === 0) return 'now'; return (m > 0 ? '+' : '') + m + 'm'; } function TimelineBar({ task, project, timing, onSelect, selected }) { const left = timing.start + 75; const width = Math.max(2, timing.end - timing.start); const status = task.column; // For running tasks, split into elapsed (solid) and projected (ghost) const isRunning = status === 'running'; const elapsedW = isRunning ? Math.max(0, 0 - timing.start) : width; const elapsedPct = (elapsedW / width) * 100; return ( ); } function TimelineView({ tasks, onSelect, selectedId }) { const { PROJECTS } = window.ORC_DATA; const projectsById = Object.fromEntries(PROJECTS.map(p => [p.id, p])); const tasksById = Object.fromEntries(tasks.map(t => [t.id, t])); const counts = { running: tasks.filter(t => t.column === 'running').length, review: tasks.filter(t => t.column === 'review').length, queued: tasks.filter(t => t.column === 'ready' || t.column === 'backlog').length, }; return (
Execution timeline window −75m … +25m · projected work shown ghosted {[ { k: 'running', label: 'running' }, { k: 'review', label: 'review' }, { k: 'done', label: 'done' }, { k: 'failed', label: 'failed' }, { k: 'ready', label: 'queued' }, ].map(s => ( {s.label} ))}
{/* Axis header */}
{TL_TICKS.map(m => ( {tickLabel(m)} ))}
{/* Lanes */} {TL_LANES.map(lane => { const laneTasks = tasks .filter(t => t.agent === lane.agent && TL_TIMING[t.id]) .sort((a, b) => TL_TIMING[a.id].start - TL_TIMING[b.id].start); return (
{lane.kind.slice(0, 2).toUpperCase()} {lane.agent} {laneTasks.length}
{/* gridlines */} {TL_TICKS.map(m => ( ))} {laneTasks.map(t => ( ))}
); })} {/* now line spanning lanes */}
{counts.running} running {counts.review} in review {counts.queued} queued
); } /* ---------------- Activity ---------------- */ const ACTIVITY_FULL = [ { id: 'a1', type: 'install', agent: 'installer-agent', project: 'zeny', title: 'Installed auth@2.4.0', detail: 'Applied to prod-us · 4 services restarted · 0 errors', ago: '12s ago', time: '00:14:22', task: 'TSK-3964' }, { id: 'a2', type: 'migrate', agent: 'migrator-agent', project: 'tlsdeck', title: 'Partition rollout on users table', detail: '7 / 12 shards backfilled · shadow read parity 100%', ago: '38s ago', time: '00:13:08', task: 'TSK-3998' }, { id: 'a3', type: 'review', agent: 'reviewer-agent', project: 'vidix', title: 'Requested approval — Stripe v3 webhooks', detail: '+412 / −188 across 6 files · affects payments', ago: '1m ago', time: '00:11:51', task: 'TSK-3987' }, { id: 'a4', type: 'fail', agent: 'installer-agent', project: 'worldtime', title: 'Halted analytics@0.4.0 install', detail: 'dependency conflict: pg-extensions/citext@1.6.3 missing', ago: '4m ago', time: '00:09:42', task: 'TSK-3954' }, { id: 'a5', type: 'test', agent: 'tester-agent', project: 'zeny', title: 'Dispatched regression suite', detail: '218 assertions queued on staging.zeny', ago: '6m ago', time: '00:07:30', task: 'TSK-4008' }, { id: 'a6', type: 'rotate', agent: 'sentinel-agent', project: 'tlsdeck', title: 'Rotated KMS signing keys', detail: 'us-east-2 · propagated to 14 services', ago: '9m ago', time: '00:04:12', task: 'TSK-4007' }, { id: 'a7', type: 'update', agent: 'installer-agent', project: 'zeny', title: 'Applied next@15.3 runtime bump', detail: 'across 3 projects · cold-start −8%', ago: '16m ago', time: '23:58:01', task: 'TSK-3965' }, { id: 'a8', type: 'install', agent: 'installer-agent', project: 'worldtime', title: 'Started blog@0.8.4 install', detail: 'building bundle · 28% · est. 1m 40s', ago: '18m ago', time: '23:55:18', task: 'TSK-3999' }, { id: 'a9', type: 'review', agent: 'reviewer-agent', project: 'tlsdeck', title: 'Requested approval — backfill org_id', detail: '1 migration · affects DB · 41k invoice rows', ago: '24m ago', time: '23:49:30', task: 'TSK-3988' }, { id: 'a10', type: 'install', agent: 'sentinel-agent', project: 'vidix', title: 'Deployed autoscaler config', detail: 'prod-us · min 4 / max 32 replicas', ago: '31m ago', time: '23:42:55', task: 'TSK-3966' }, { id: 'a11', type: 'test', agent: 'tester-agent', project: 'vidix', title: 'Rebuilt knowledge embeddings', detail: '81% · 6,402 docs re-indexed', ago: '40m ago', time: '23:33:12', task: 'TSK-4000' }, ]; const ACT_TYPES = { install: { icon: 'box', color: 'var(--c-status-done)', label: 'Install' }, update: { icon: 'arrowRight', color: 'var(--c-status-running)', label: 'Update' }, migrate: { icon: 'database', color: 'var(--c-status-running)', label: 'Migration' }, review: { icon: 'shield', color: 'var(--c-status-review)', label: 'Approval' }, fail: { icon: 'alert', color: 'var(--c-status-failed)', label: 'Failure' }, test: { icon: 'zap', color: 'var(--c-status-running)', label: 'Test' }, rotate: { icon: 'refresh', color: 'var(--c-status-done)', label: 'Security' }, }; const ACT_FILTERS = [ { id: 'all', label: 'All' }, { id: 'install', label: 'Installs & updates', types: ['install', 'update', 'migrate'] }, { id: 'review', label: 'Approvals', types: ['review'] }, { id: 'fail', label: 'Failures', types: ['fail'] }, { id: 'test', label: 'Tests', types: ['test'] }, ]; function ActivityView({ onSelect }) { const { PROJECTS } = window.ORC_DATA; const projectsById = Object.fromEntries(PROJECTS.map(p => [p.id, p])); const [filter, setFilter] = React.useState('all'); const def = ACT_FILTERS.find(f => f.id === filter); const items = filter === 'all' ? ACTIVITY_FULL : ACTIVITY_FULL.filter(a => def.types.includes(a.type)); // bucket by recency const recent = items.filter(a => a.ago.includes('s ago') || a.ago === '1m ago'); const earlier = items.filter(a => !(a.ago.includes('s ago') || a.ago === '1m ago')); const renderRow = (a) => { const t = ACT_TYPES[a.type]; const project = projectsById[a.project]; return ( ); }; return (
{ACT_FILTERS.map(f => ( ))} live stream
{recent.length > 0 &&
Just now
} {recent.map(renderRow)} {earlier.length > 0 &&
Earlier
} {earlier.map(renderRow)} {items.length === 0 &&
no events match this filter
}
); } window.TimelineView = TimelineView; window.ActivityView = ActivityView;