// BKS icons & data
// Exposes window.Icon (a component) and window.DATA

const Icon = ({ name, size = 16, strokeWidth = 1.75, style, className }) => {
  const paths = ICON_PATHS[name];
  if (!paths) return null;
  return (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      width={size} height={size}
      viewBox="0 0 24 24" fill="none"
      stroke="currentColor" strokeWidth={strokeWidth}
      strokeLinecap="round" strokeLinejoin="round"
      style={style} className={className}
    >
      {paths}
    </svg>
  );
};

const ICON_PATHS = {
  dashboard: <><rect x="3" y="3" width="7" height="9"/><rect x="14" y="3" width="7" height="5"/><rect x="14" y="12" width="7" height="9"/><rect x="3" y="16" width="7" height="5"/></>,
  issue: <><circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="3"/></>,
  project: <><path d="M4 4h6l2 3h8v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z"/></>,
  team: <><circle cx="9" cy="8" r="3"/><path d="M3 20v-1a6 6 0 0 1 12 0v1"/><circle cx="17" cy="9" r="2.5"/><path d="M15 20v-1a4 4 0 0 1 6-3.5"/></>,
  engine: <><path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/><circle cx="12" cy="12" r="3"/></>,
  skills: <><path d="M12 2L3 7l9 5 9-5-9-5z"/><path d="M3 12l9 5 9-5"/><path d="M3 17l9 5 9-5"/></>,
  diff: <><path d="M3 4h18M3 12h18M3 20h10"/><circle cx="18" cy="20" r="2"/></>,
  search: <><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></>,
  filter: <><path d="M3 6h18M6 12h12M10 18h4"/></>,
  plus: <><path d="M12 5v14M5 12h14"/></>,
  close: <><path d="M18 6 6 18M6 6l12 12"/></>,
  server: <><rect x="2" y="3" width="20" height="8" rx="2"/><rect x="2" y="13" width="20" height="8" rx="2"/><path d="M6 7h.01M6 17h.01"/></>,
  alert: <><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><path d="M12 9v4M12 17h.01"/></>,
  person: <><circle cx="12" cy="8" r="4"/><path d="M4 20v-1a8 8 0 0 1 16 0v1"/></>,
  checkCircle: <><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></>,
  chevDown: <><path d="m6 9 6 6 6-6"/></>,
  chevRight: <><path d="m9 6 6 6-6 6"/></>,
  chevLeft: <><path d="m15 6-6 6 6 6"/></>,
  moon: <><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></>,
  sun: <><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></>,
  globe: <><circle cx="12" cy="12" r="10"/><path d="M2 12h20M12 2a15.3 15.3 0 0 1 0 20M12 2a15.3 15.3 0 0 0 0 20"/></>,
  bell: <><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10 21a2 2 0 0 0 4 0"/></>,
  menu: <><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></>,
  cmd: <><path d="M15 6v12a3 3 0 1 0 3-3H6a3 3 0 1 0 3 3V6a3 3 0 1 0-3 3h12a3 3 0 1 0-3-3"/></>,
  inbox: <><path d="M22 12h-6l-2 3h-4l-2-3H2M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"/></>,
  play: <><polygon points="5 3 19 12 5 21 5 3"/></>,
  pause: <><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></>,
  stop: <><rect x="5" y="5" width="14" height="14" rx="1"/></>,
  dots: <><circle cx="5" cy="12" r="1.5"/><circle cx="12" cy="12" r="1.5"/><circle cx="19" cy="12" r="1.5"/></>,
  check: <><path d="M20 6 9 17l-5-5"/></>,
  message: <><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></>,
  terminal: <><path d="m4 17 6-6-6-6M12 19h8"/></>,
  file: <><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></>,
  folder: <><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></>,
  gitBranch: <><line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/></>,
  clock: <><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></>,
  activity: <><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></>,
  settings: <><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></>,
  zap: <><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></>,
  sparkles: <><path d="M12 3l1.5 5L18 9.5 13.5 11 12 16l-1.5-5L6 9.5 10.5 8z"/><path d="M18 3v3M19.5 4.5h-3"/><path d="M5 17v3M6.5 18.5h-3"/></>,
  database: <><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/></>,
  lock: <><rect x="3" y="11" width="18" height="10" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></>,
  link: <><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></>,
  tag: <><path d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z"/><line x1="7" y1="7" x2="7.01" y2="7"/></>,
  arrowUp: <><path d="M12 19V5M5 12l7-7 7 7"/></>,
  arrowDown: <><path d="M12 5v14M19 12l-7 7-7-7"/></>,
  trending: <><polyline points="23 6 13.5 15.5 8.5 10.5 1 18"/><polyline points="17 6 23 6 23 12"/></>,
  upload: <><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></>,
  send: <><path d="M22 2 11 13M22 2l-7 20-4-9-9-4z"/></>,
  edit: <><path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"/></>,
  archive: <><rect x="2" y="4" width="20" height="5" rx="1"/><path d="M4 9v11a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1V9"/><line x1="10" y1="14" x2="14" y2="14"/></>,
  mic: <><rect x="9" y="2" width="6" height="12" rx="3"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" y1="19" x2="12" y2="22"/></>,
  heart: <><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></>,
  external: <><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></>,
  cpu: <><rect x="4" y="4" width="16" height="16" rx="2"/><rect x="9" y="9" width="6" height="6"/><path d="M9 1v3M15 1v3M9 20v3M15 20v3M20 9h3M20 14h3M1 9h3M1 14h3"/></>,
  layers: <><polygon points="12 2 2 7 12 12 22 7 12 2"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/></>,
  flash: <><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></>,
  flag: <><path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"/><line x1="4" y1="22" x2="4" y2="15"/></>,
  mergeReq: <><circle cx="18" cy="18" r="3"/><circle cx="6" cy="6" r="3"/><path d="M6 21V9a9 9 0 0 0 9 9"/></>,
  moreH: <><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></>,
  bolt: <><path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z"/></>,
  refresh: <><polyline points="23 4 23 10 17 10"/><polyline points="1 20 1 14 7 14"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></>,
  shield: <><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></>,
  bot: <><rect x="4" y="8" width="16" height="11" rx="2.5"/><path d="M12 4v4"/><circle cx="12" cy="3" r="1"/><circle cx="9" cy="13" r="1.2"/><circle cx="15" cy="13" r="1.2"/><path d="M9 17h6"/><path d="M2 13v3M22 13v3"/></>,
  puzzle: <><path d="M19.4 7H17c0-1.1-.9-2-2-2s-2 .9-2 2h-2.4C9.7 7 9 7.7 9 8.6V11c-1.1 0-2 .9-2 2s.9 2 2 2v2.4c0 .9.7 1.6 1.6 1.6H13c0-1.1.9-2 2-2s2 .9 2 2h2.4c.9 0 1.6-.7 1.6-1.6V15c1.1 0 2-.9 2-2s-.9-2-2-2V8.6c0-.9-.7-1.6-1.6-1.6z"/></>,
  beaker: <><path d="M9 3h6v5l5 10a2 2 0 0 1-2 3H6a2 2 0 0 1-2-3L9 8V3z"/><path d="M9 3h6"/></>,
  box: <><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/></>,
  codeIcon: <><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></>,
  pin: <><path d="M12 17v5M8 11h8l-2-7h-4l-2 7z"/><path d="M5 11h14v3H5z"/></>,
  ram: <><rect x="2" y="8" width="20" height="8" rx="1"/><path d="M6 12h.01M10 12h.01M14 12h.01M18 12h.01M6 16v2M10 16v2M14 16v2M18 16v2"/></>,
  cloud: <><path d="M17.5 19a4.5 4.5 0 1 0-1.4-8.78A6 6 0 0 0 4 13a4 4 0 0 0 2 7.5h11.5z"/></>,
  'chevron-right': <><polyline points="9 18 15 12 9 6"/></>,
  panelLeft: <><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="9" y1="3" x2="9" y2="21"/></>,
  panelLeftClose: <><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="9" y1="3" x2="9" y2="21"/><polyline points="16 15 13 12 16 9"/></>,
  panelLeftOpen: <><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="9" y1="3" x2="9" y2="21"/><polyline points="14 9 17 12 14 15"/></>,
  eye: <><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></>,
  book: <><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></>,
  bookmark: <><path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/></>,
  quote: <><path d="M3 21c3-1 4-3 4-6V5h6v10"/><path d="M14 21c3-1 4-3 4-6V5h-3"/></>,
  users: <><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></>,
  trash: <><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6M14 11v6"/><path d="M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"/></>,
};

// ---------------------- DATA ----------------------
const PROJECTS = [
  { id: 'ATLAS', name: 'Atlas API', slug: 'atlas-api', color: '#3D63FF',  desc: 'Rate-limited JSON API gateway with streaming support', issues: 128, done: 74, members: 9, lang: 'TypeScript' },
  { id: 'HELIX', name: 'Helix Billing', slug: 'helix-billing', color: '#8B5CF6', desc: 'Usage-metered billing engine — invoices, dunning, proration', issues: 87, done: 52, members: 6, lang: 'Go' },
  { id: 'NOVA',  name: 'Nova Dashboard', slug: 'nova-dashboard', color: '#E8A317', desc: 'Analytics UI for platform usage and cost observability', issues: 54, done: 31, members: 5, lang: 'React' },
  { id: 'CORE',  name: 'Core Auth', slug: 'core-auth', color: '#00A870',  desc: 'OAuth + SSO provider, SCIM sync, audit logs', issues: 41, done: 30, members: 4, lang: 'Rust' },
  { id: 'EDGE',  name: 'Edge Workers', slug: 'edge-workers', color: '#E5484D',  desc: 'CDN worker runtime for per-region request handling', issues: 33, done: 14, members: 3, lang: 'TypeScript' },
  { id: 'PULSE', name: 'Pulse Telemetry', slug: 'pulse-telemetry', color: '#10A37F',  desc: 'OpenTelemetry ingest + cardinality guard', issues: 29, done: 19, members: 4, lang: 'Go' },
];

const ENGINES = [
  { id: 'claude', name: 'Claude Code', vendor: 'Anthropic', status: 'ready', latency: 420, success: 94, runs: 1847, models: [
    { name: 'claude-sonnet-4.5', usage: 72 },
    { name: 'claude-opus-4', usage: 18 },
    { name: 'claude-haiku-4.5', usage: 10 },
  ]},
  { id: 'codex', name: 'Codex', vendor: 'OpenAI', status: 'ready', latency: 510, success: 89, runs: 1132, models: [
    { name: 'gpt-5-codex', usage: 64 },
    { name: 'o4-mini', usage: 28 },
    { name: 'gpt-4.1', usage: 8 },
  ]},
  { id: 'gemini', name: 'Gemini CLI', vendor: 'Google', status: 'degraded', latency: 680, success: 82, runs: 604, models: [
    { name: 'gemini-2.5-pro', usage: 58 },
    { name: 'gemini-2.5-flash', usage: 42 },
  ]},
];

// Nodes — execution hosts. Engines are capabilities installed on a node.
// Projects are bound to exactly one node.
const NODES = [
  {
    id: 'laptop-ming',
    name: 'laptop-ming',
    kind: 'local',
    region: 'local · zh-sz',
    status: 'online',
    uptime: '2d 14h',
    specs: { cpu: 'M3 Max · 12-core', ram: '64 GB', disk: '1 TB SSD' },
    load: { cpu: 18, ram: 34, disk: 42 },
    engines: [
      { id: 'claude', version: '0.8.2', status: 'ready', latency: 380 },
      { id: 'codex',  version: '1.2.0', status: 'ready', latency: 490 },
      { id: 'gemini', version: '0.4.1', status: 'ready', latency: 610 },
    ],
    projects: ['NOVA', 'EDGE'],
    runs7d: 284,
  },
  {
    id: 'node-prod-west',
    name: 'node-prod-west',
    kind: 'cloud',
    region: 'aws · us-west-2',
    status: 'online',
    uptime: '47d 3h',
    specs: { cpu: 'c7i.4xlarge · 16 vCPU', ram: '32 GB', disk: '512 GB NVMe' },
    load: { cpu: 64, ram: 58, disk: 71 },
    engines: [
      { id: 'claude', version: '0.8.2', status: 'ready', latency: 420 },
      { id: 'codex',  version: '1.2.0', status: 'ready', latency: 510 },
    ],
    projects: ['ATLAS', 'HELIX'],
    runs7d: 1842,
  },
  {
    id: 'node-prod-east',
    name: 'node-prod-east',
    kind: 'cloud',
    region: 'aws · us-east-1',
    status: 'online',
    uptime: '12d 8h',
    specs: { cpu: 'c7i.2xlarge · 8 vCPU', ram: '16 GB', disk: '256 GB NVMe' },
    load: { cpu: 41, ram: 47, disk: 52 },
    engines: [
      { id: 'claude', version: '0.8.2', status: 'ready', latency: 440 },
      { id: 'gemini', version: '0.4.1', status: 'degraded', latency: 820 },
    ],
    projects: ['CORE'],
    runs7d: 417,
  },
  {
    id: 'node-eu-central',
    name: 'node-eu-central',
    kind: 'cloud',
    region: 'gcp · eu-central-1',
    status: 'online',
    uptime: '5h 22m',
    specs: { cpu: 'n2-standard-8 · 8 vCPU', ram: '32 GB', disk: '200 GB SSD' },
    load: { cpu: 12, ram: 19, disk: 8 },
    engines: [
      { id: 'codex',  version: '1.2.0', status: 'ready', latency: 560 },
      { id: 'gemini', version: '0.4.1', status: 'ready', latency: 640 },
    ],
    projects: ['PULSE'],
    runs7d: 73,
  },
];

// Attach node to each project for quick lookup
PROJECTS.forEach(p => {
  const node = NODES.find(n => n.projects.includes(p.id));
  p.nodeId = node ? node.id : null;
});

const AGENTS_BY_ENGINE = {
  claude: [
    { name: 'sonnet-primary', handle: '@claude/sonnet', runs: 412, success: 96, avgMin: 3.8, active: true },
    { name: 'opus-review', handle: '@claude/opus', runs: 87, success: 93, avgMin: 9.2, active: true },
    { name: 'haiku-triage', handle: '@claude/haiku', runs: 1348, success: 92, avgMin: 0.9, active: true },
  ],
  codex: [
    { name: 'codex-impl', handle: '@codex/primary', runs: 640, success: 90, avgMin: 4.1, active: true },
    { name: 'o4-planner', handle: '@codex/o4', runs: 312, success: 88, avgMin: 1.7, active: true },
    { name: 'gpt-linter', handle: '@codex/lint', runs: 180, success: 94, avgMin: 0.6, active: false },
  ],
  gemini: [
    { name: 'gemini-pro', handle: '@gemini/pro', runs: 342, success: 84, avgMin: 5.2, active: true },
    { name: 'gemini-flash', handle: '@gemini/flash', runs: 262, success: 79, avgMin: 1.2, active: true },
  ],
  human: [
    { name: 'Xie Ming',    handle: '@xieming',   role: 'Platform Lead',      title: 'Engineering · Owner', tz: 'Asia/Shanghai · UTC+8',  projects: ['ATLAS','CORE','HELIX'], active: true,  status: 'Online',                   lastSeen: 'now',      avatar: 'XM', color: 'linear-gradient(135deg,#F59E0B,#D97706)', runs: 42, reviews: 18, shipped: 9 },
    { name: 'Rita Chen',   handle: '@rita',      role: 'Senior Engineer',    title: 'API & Gateway',       tz: 'Asia/Shanghai · UTC+8',  projects: ['ATLAS','NOVA'],         active: true,  status: 'Reviewing HLX-218',       lastSeen: '2m ago',   avatar: 'RC', color: 'linear-gradient(135deg,#EC4899,#DB2777)', runs: 38, reviews: 24, shipped: 12 },
    { name: 'Jordan Park', handle: '@jordan',    role: 'Senior Engineer',    title: 'Billing & Payments',  tz: 'America/Los_Angeles · UTC-7', projects: ['HELIX'],           active: true,  status: 'Pairing with agent',      lastSeen: 'now',      avatar: 'JP', color: 'linear-gradient(135deg,#3D63FF,#1E40AF)', runs: 31, reviews: 15, shipped: 7 },
    { name: 'Sam Ortega',  handle: '@sam',       role: 'SRE',                title: 'Infrastructure',      tz: 'Europe/Madrid · UTC+2',  projects: ['CORE','EDGE','PULSE'], active: false, status: 'Off — back tomorrow',      lastSeen: '11h ago',  avatar: 'SO', color: 'linear-gradient(135deg,#10A37F,#047857)', runs: 26, reviews: 9,  shipped: 5 },
    { name: 'Ren Chao',    handle: '@ren',       role: 'Reviewer',           title: 'Security · Risk',     tz: 'Asia/Shanghai · UTC+8',  projects: ['ATLAS','HELIX','CORE'], active: true, status: 'Online',                   lastSeen: '6m ago',   avatar: 'RN', color: 'linear-gradient(135deg,#8B5CF6,#6D28D9)', runs: 12, reviews: 47, shipped: 2 },
    { name: 'Lea Morgan',  handle: '@lea',       role: 'Product',            title: 'Nova Dashboard',      tz: 'Europe/London · UTC+1',  projects: ['NOVA'],                 active: true,  status: 'In planning',             lastSeen: '15m ago',  avatar: 'LM', color: 'linear-gradient(135deg,#06B6D4,#0891B2)', runs: 4,  reviews: 11, shipped: 3 },
  ],
};

const ISSUES = [
  { id: 'ATL-412', proj: 'ATLAS', title: 'Add streaming responses to /v1/completions gateway', status: 'working', priority: 'urgent', assignee: { kind: 'agent', engine: 'claude', handle: 'sonnet-primary' }, labels: ['api','streaming'], updated: '2m', eta: '18m' },
  { id: 'ATL-411', proj: 'ATLAS', title: 'Rate-limit bypass when X-Priority: high header is present', status: 'review', priority: 'high', assignee: { kind: 'agent', engine: 'codex', handle: 'codex-impl' }, labels: ['security'], updated: '8m' },
  { id: 'ATL-409', proj: 'ATLAS', title: 'Cache revalidation fires twice on edge cold-start', status: 'todo', priority: 'high', assignee: { kind: 'human', name: 'Rita', avatar: 'RC' }, labels: ['bug','edge'], updated: '1h' },
  { id: 'HLX-218', proj: 'HELIX', title: 'Prorate mid-cycle plan downgrades with credit memo', status: 'working', priority: 'high', assignee: { kind: 'agent', engine: 'claude', handle: 'opus-review' }, labels: ['billing'], updated: '4m', eta: '22m' },
  { id: 'HLX-217', proj: 'HELIX', title: 'Invoice PDF misaligns tax row for EU VAT', status: 'done', priority: 'med', assignee: { kind: 'agent', engine: 'claude', handle: 'sonnet-primary' }, labels: ['pdf','eu'], updated: '3h' },
  { id: 'NOV-56',  proj: 'NOVA',  title: 'Add cost-attribution donut to team overview', status: 'todo', priority: 'med', assignee: { kind: 'human', name: 'Xie Ming', avatar: 'XM' }, labels: ['charts'], updated: '2h' },
  { id: 'NOV-55',  proj: 'NOVA',  title: 'Sparkline re-renders loop on tab focus', status: 'review', priority: 'low', assignee: { kind: 'agent', engine: 'gemini', handle: 'gemini-pro' }, labels: ['bug','ui'], updated: '26m' },
  { id: 'COR-103', proj: 'CORE',  title: 'SCIM sync drops group memberships beyond 1000', status: 'working', priority: 'urgent', assignee: { kind: 'agent', engine: 'codex', handle: 'o4-planner' }, labels: ['scim','scale'], updated: '6m', eta: '41m' },
  { id: 'COR-102', proj: 'CORE',  title: 'Audit log retention job silently OOMs at 30d', status: 'todo', priority: 'high', assignee: null, labels: ['infra'], updated: '1d' },
  { id: 'EDG-44',  proj: 'EDGE',  title: 'Per-region worker deploy status missing in API', status: 'working', priority: 'med', assignee: { kind: 'agent', engine: 'gemini', handle: 'gemini-flash' }, labels: ['api'], updated: '12m', eta: '6m' },
  { id: 'EDG-43',  proj: 'EDGE',  title: 'Add KV namespace binding to worker metadata', status: 'done', priority: 'med', assignee: { kind: 'human', name: 'Jordan', avatar: 'JP' }, labels: ['kv'], updated: '5h' },
  { id: 'PUL-31',  proj: 'PULSE', title: 'Cardinality guard false-positives on high-traffic tenant', status: 'review', priority: 'high', assignee: { kind: 'agent', engine: 'claude', handle: 'sonnet-primary' }, labels: ['telemetry'], updated: '18m' },
  // Short one-line issues — test how the page renders terse titles
  { id: 'ATL-415', proj: 'ATLAS', title: 'Fix typo', status: 'todo', priority: 'low', assignee: null, labels: ['docs'], updated: '3m' },
  { id: 'ATL-416', proj: 'ATLAS', title: '500 on /health', status: 'working', priority: 'urgent', assignee: { kind: 'agent', engine: 'claude', handle: 'haiku-triage' }, labels: ['bug'], updated: '1m', eta: '4m' },
  { id: 'HLX-220', proj: 'HELIX', title: 'Bump stripe-node', status: 'todo', priority: 'low', assignee: null, labels: ['deps'], updated: '14m' },
  { id: 'NOV-58',  proj: 'NOVA',  title: 'Dark mode', status: 'todo', priority: 'med', assignee: { kind: 'human', name: 'Xie Ming', avatar: 'XM' }, labels: ['ui'], updated: '32m' },
  { id: 'COR-105', proj: 'CORE',  title: 'Add /metrics', status: 'review', priority: 'med', assignee: { kind: 'agent', engine: 'codex', handle: 'codex-impl' }, labels: ['observability'], updated: '9m' },
  { id: 'EDG-46',  proj: 'EDGE',  title: 'Drop IE11', status: 'done', priority: 'low', assignee: { kind: 'human', name: 'Jordan', avatar: 'JP' }, labels: ['chore'], updated: '2h' },
  { id: 'PUL-32',  proj: 'PULSE', title: 'OOM on boot', status: 'todo', priority: 'urgent', assignee: null, labels: ['bug','infra'], updated: '7m' },
  // Archived — closed / shipped / wontfix, kept for searchability
  { id: 'ATL-388', proj: 'ATLAS', title: 'Migrate legacy /v0 endpoints to /v1 schema', status: 'archived', priority: 'med', assignee: { kind: 'agent', engine: 'claude', handle: 'sonnet-primary' }, labels: ['migration'], updated: '6d', archivedAt: '6d', archivedReason: 'shipped' },
  { id: 'HLX-201', proj: 'HELIX', title: 'Retry Stripe webhooks with exponential backoff', status: 'archived', priority: 'high', assignee: { kind: 'human', name: 'Rita', avatar: 'RC' }, labels: ['webhook','billing'], updated: '8d', archivedAt: '8d', archivedReason: 'shipped' },
  { id: 'NOV-48',  proj: 'NOVA',  title: 'Experiment: stacked chart colour palette', status: 'archived', priority: 'low', assignee: { kind: 'human', name: 'Xie Ming', avatar: 'XM' }, labels: ['design','experiment'], updated: '2w', archivedAt: '2w', archivedReason: 'wontfix' },
  { id: 'COR-91',  proj: 'CORE',  title: 'Duplicate SSO certificates cause sign-in loop', status: 'archived', priority: 'urgent', assignee: { kind: 'agent', engine: 'codex', handle: 'o4-planner' }, labels: ['sso','bug'], updated: '11d', archivedAt: '11d', archivedReason: 'duplicate' },
  { id: 'EDG-38',  proj: 'EDGE',  title: 'Benchmark: KV read latency across regions', status: 'archived', priority: 'med', assignee: { kind: 'agent', engine: 'gemini', handle: 'gemini-pro' }, labels: ['benchmark'], updated: '3w', archivedAt: '3w', archivedReason: 'shipped' },
];

const SKILLS = [
  { id: 'skl-01', name: 'Write PR description', icon: 'edit', desc: 'Summarize a diff into a PR description with rationale, test plan, and risks.', runs: 2847, engines: ['claude','codex'] },
  { id: 'skl-02', name: 'Generate test plan', icon: 'check', desc: 'Read an issue + diff, produce a risk-ranked test plan with concrete checks.', runs: 1412, engines: ['claude'] },
  { id: 'skl-03', name: 'Port snippet to TS', icon: 'codeIcon', desc: 'Convert a JS/Python snippet to typed TypeScript, matching project conventions.', runs: 984, engines: ['claude','codex','gemini'] },
  { id: 'skl-04', name: 'Triage bug report', icon: 'flag', desc: 'Classify severity, find related issues, suggest reproduction steps.', runs: 652, engines: ['claude','codex'] },
  { id: 'skl-05', name: 'Schema migration', icon: 'database', desc: 'Diff SQL schemas and generate safe forward/backward migrations.', runs: 428, engines: ['codex'] },
  { id: 'skl-06', name: 'API endpoint scaffold', icon: 'zap', desc: 'Spin up a typed endpoint with handler, validator, and tests.', runs: 1184, engines: ['claude','codex'] },
  { id: 'skl-07', name: 'i18n extraction', icon: 'globe', desc: 'Extract hard-coded strings into locale files and swap to the i18n helper.', runs: 367, engines: ['claude','gemini'] },
  { id: 'skl-08', name: 'Dep security audit', icon: 'shield', desc: 'Scan lockfile for CVEs, propose upgrade or pin, check changelog.', runs: 213, engines: ['claude','codex'] },
  { id: 'skl-09', name: 'Type-only refactor', icon: 'puzzle', desc: 'Tighten types without changing runtime behavior — narrows unknowns.', runs: 501, engines: ['claude','codex'] },
];

// Timeline activity (human + agent mixed)
const ACTIVITY = [
  { t: '14:02', tag: 'agent', who: 'sonnet-primary', engine: 'claude', verb: 'opened PR', what: 'feat(gateway): streaming completions passthrough', target: 'ATL-412' },
  { t: '14:01', tag: 'human', who: 'Rita Chen',    verb: 'assigned', what: 'ATL-409 to @claude/haiku for triage' },
  { t: '13:58', tag: 'agent', who: 'codex-impl',    engine: 'codex', verb: 'ran tests', what: '128 passed, 2 failed — retry with --bail' },
  { t: '13:52', tag: 'human', who: 'Xie Ming',     verb: 'commented', what: '"Let\'s split the donut into a separate PR so we can ship the KPI cards today."' },
  { t: '13:49', tag: 'agent', who: 'gemini-flash',  engine: 'gemini', verb: 'edited 3 files', what: 'apps/api/src/regions/*.ts' },
  { t: '13:44', tag: 'agent', who: 'opus-review',   engine: 'claude', verb: 'approved review', what: 'HLX-217 — LGTM, ship it' },
  { t: '13:40', tag: 'human', who: 'Jordan Park',  verb: 'merged', what: 'EDG-43 (KV namespace binding)' },
  { t: '13:36', tag: 'agent', who: 'sonnet-primary', engine: 'claude', verb: 'created issue', what: 'ATL-414 — investigate duplicate revalidation' },
  { t: '13:30', tag: 'agent', who: 'o4-planner',   engine: 'codex', verb: 'drafted plan', what: 'SCIM large-group sync — 4 steps, 2 migrations' },
  { t: '13:22', tag: 'human', who: 'Sam Ortega',  verb: 'closed', what: 'NOV-52 as duplicate of NOV-55' },
];

// Inbox — human-in-the-loop queue: agents paused waiting for human decision
const INBOX = [
  {
    id: 'ib-01',
    kind: 'approval',
    priority: 'high',
    issue: 'ATL-412',
    title: 'Approve: drop column `users.legacy_token`',
    agent: 'sonnet-primary', engine: 'claude',
    pausedFor: '4m',
    blurb: 'Migration 0042 includes a destructive column drop. Policy requires human approval for DROP on tables with >10k rows (affected: 487,204).',
    context: [
      { label: 'Rows affected', value: '487,204' },
      { label: 'Reversible', value: 'With backup' },
      { label: 'Blast radius', value: 'prod.users' },
    ],
    actions: [
      { kind: 'primary', label: 'Approve once' },
      { kind: 'bordered', label: 'Approve & remember' },
      { kind: 'ghost', label: 'Deny' },
    ],
  },
  {
    id: 'ib-02',
    kind: 'clarification',
    priority: 'med',
    issue: 'HLX-218',
    title: 'Clarify: how to handle partial mid-cycle credits?',
    agent: 'opus-review', engine: 'claude',
    pausedFor: '12m',
    blurb: 'Spec says "prorate" but doesn\'t specify rounding. I need to pick one before writing the calc. Picked option is captured in the PR description.',
    choices: [
      { key: 'A', label: 'Round to nearest cent (banker\'s rounding)' },
      { key: 'B', label: 'Always round down — finance-safe' },
      { key: 'C', label: 'Always round up — customer-friendly' },
    ],
    actions: [
      { kind: 'ghost', label: 'Reply with custom' },
    ],
  },
  {
    id: 'ib-03',
    kind: 'review',
    priority: 'med',
    issue: 'ATL-412',
    title: 'PR ready: streaming /v1/completions passthrough',
    agent: 'sonnet-primary', engine: 'claude',
    pausedFor: '18m',
    blurb: '14 files changed · +428 −112 · all tests pass, coverage 87% → 89%. Linked issue has 2 acceptance criteria — both checked off.',
    preview: [
      '+ apps/api/src/gateway/stream.ts       (new)',
      '+ apps/api/src/gateway/completions.ts  (+84 −12)',
      '+ apps/api/test/stream.spec.ts         (new)',
      '  … 11 more',
    ],
    actions: [
      { kind: 'primary', label: 'Open diff' },
      { kind: 'bordered', label: 'Approve & merge' },
      { kind: 'ghost', label: 'Request changes' },
    ],
  },
  {
    id: 'ib-04',
    kind: 'conflict',
    priority: 'high',
    issue: 'COR-183',
    title: 'Conflict: two agents edited `schemas/scim.ts`',
    agent: 'o4-planner', engine: 'codex',
    pausedFor: '2m',
    blurb: 'codex-impl and gemini-flash both modified the SCIMUser schema on overlapping lines. Neither branch is merged yet.',
    diffs: [
      { who: 'codex-impl', note: 'added `externalId?: string` (line 34)' },
      { who: 'gemini-flash', note: 'added `nickName?: string` (line 34)' },
    ],
    actions: [
      { kind: 'primary', label: 'Keep both' },
      { kind: 'bordered', label: 'Pick codex' },
      { kind: 'bordered', label: 'Pick gemini' },
    ],
  },
  {
    id: 'ib-05',
    kind: 'policy',
    priority: 'high',
    issue: 'NOV-55',
    title: 'Policy block: write to `config/prod.yaml`',
    agent: 'gemini-flash', engine: 'gemini',
    pausedFor: '23m',
    blurb: 'Agent attempted to modify a prod config file. Workspace policy `prod-config-readonly` blocks writes without human override.',
    context: [
      { label: 'Policy', value: 'prod-config-readonly' },
      { label: 'File', value: 'config/prod.yaml' },
      { label: 'Diff size', value: '3 lines' },
    ],
    actions: [
      { kind: 'primary', label: 'Override & allow' },
      { kind: 'ghost', label: 'Deny & explain' },
    ],
  },
  {
    id: 'ib-06',
    kind: 'budget',
    priority: 'med',
    issue: 'ATL-409',
    title: 'Budget exceeded: $4.80 / $3.00 cap',
    agent: 'claude-haiku', engine: 'claude',
    pausedFor: '31m',
    blurb: 'Triage loop on noisy test failures — 184 tool calls, 47 file reads. Likely cycling between two fixes. Recommend switching to opus.',
    context: [
      { label: 'Spent', value: '$4.80' },
      { label: 'Cap', value: '$3.00' },
      { label: 'Tool calls', value: '184' },
    ],
    actions: [
      { kind: 'primary', label: 'Raise to $10' },
      { kind: 'bordered', label: 'Switch to opus' },
      { kind: 'ghost', label: 'Stop' },
    ],
  },
  {
    id: 'ib-07',
    kind: 'mention',
    priority: 'low',
    issue: 'ATL-412',
    title: 'Rita Chen mentioned you',
    agent: null, engine: null,
    who: 'Rita Chen',
    pausedFor: '1h',
    blurb: '"@Xie can you sanity-check the streaming backpressure approach before the agent auto-merges? I want another pair of eyes on the chunk size."',
    actions: [
      { kind: 'primary', label: 'Reply' },
      { kind: 'ghost', label: 'Mark read' },
    ],
  },
  {
    id: 'ib-08',
    kind: 'approval',
    priority: 'low',
    issue: 'HLX-217',
    title: 'Approve: add `stripe` dependency',
    agent: 'opus-review', engine: 'claude',
    pausedFor: '2h',
    blurb: 'Policy requires approval for new runtime deps. `stripe@^15.2` — MIT license, 14 transitive deps, no known CVEs.',
    context: [
      { label: 'Package', value: 'stripe@^15.2' },
      { label: 'License', value: 'MIT' },
      { label: 'CVE check', value: 'Clean' },
    ],
    actions: [
      { kind: 'primary', label: 'Approve' },
      { kind: 'ghost', label: 'Deny' },
    ],
  },
];

// ---------------------- KNOWLEDGE BASE ----------------------
// Curated knowledge extracted from issues/PRs/agent runs.
// Each entry points back to the issue(s) it came from.
const KNOWLEDGE_CATEGORIES = [
  { id: 'convention', label: 'Conventions',  color: '#3D63FF', desc: 'Team-wide rules · style · patterns' },
  { id: 'gotcha',     label: 'Gotchas',      color: '#F59E0B', desc: 'Non-obvious pitfalls · edge cases' },
  { id: 'pattern',    label: 'Patterns',     color: '#10A37F', desc: 'Proven solutions · reusable recipes' },
  { id: 'decision',   label: 'Decisions',    color: '#8B5CF6', desc: 'ADRs · why we chose X over Y' },
  { id: 'runbook',    label: 'Runbooks',     color: '#EF4444', desc: 'Step-by-step ops procedures' },
];

const KNOWLEDGE = [
  {
    id: 'kb-001', category: 'convention', title: 'All timestamps stored as UTC ISO-8601 strings',
    summary: 'Never store local time, epoch ints, or DB-native datetimes. Parse at the edge, format at the edge. Zod schema `z.string().datetime()` enforces this API-side.',
    body: 'Observed inconsistency between `helix-billing` (epoch ms) and `atlas-api` (ISO). Caused a 2h outage during DST transition. All new code MUST use ISO-8601 UTC.',
    tags: ['timestamps','serialization','api'],
    projects: ['ATLAS','HELIX','CORE'],
    sources: [{issue:'ATL-188', title:'DST transition broke invoice range'}, {issue:'HLX-94', title:'Normalize time serialization'}],
    author: { kind:'agent', name:'opus-review', engine:'claude' },
    verified: true, verifiedBy: 'Ren Chao', pinned: true,
    created: '12d ago', updated: '3d ago', uses: 47,
  },
  {
    id: 'kb-002', category: 'gotcha', title: 'Stripe webhook retries are NOT idempotent by default',
    summary: 'Stripe sends the same event up to 16 times over 3 days on 5xx. Must dedupe by `event.id` before processing — duplicate invoices were created twice during an incident.',
    body: 'Use Redis SETNX on `stripe:event:{id}` with 72h TTL. Reject as 200 if key exists. This is the billing-team canonical pattern.',
    tags: ['stripe','webhooks','idempotency','billing'],
    projects: ['HELIX'],
    sources: [{issue:'HLX-217', title:'Approve: add stripe dependency'}, {issue:'HLX-143', title:'Duplicate invoice bug'}],
    author: { kind:'human', name:'Ren Chao', avatar:'RC', color:'linear-gradient(135deg,#F59E0B,#EA580C)' },
    verified: true, verifiedBy: 'Ren Chao',
    created: '18d ago', updated: '5d ago', uses: 23,
  },
  {
    id: 'kb-003', category: 'pattern', title: 'Rate-limit buckets via Redis sliding-window log',
    summary: 'For < 10k req/s, store request timestamps in a sorted set keyed by `rl:{user}:{route}`. Trim on each request. Scales to 100k keys per node with < 2ms p99.',
    body: 'Full implementation in atlas-api/src/ratelimit.ts. Tested to 14k RPS on a single c7i.4xlarge. For higher throughput, shift to token-bucket with Lua script.',
    tags: ['rate-limiting','redis','performance'],
    projects: ['ATLAS'],
    sources: [{issue:'ATL-412', title:'Rate-limit under load'}, {issue:'ATL-389', title:'Sliding window implementation'}],
    author: { kind:'agent', name:'sonnet-dev', engine:'claude' },
    verified: true, verifiedBy: 'Xie Ming',
    created: '9d ago', updated: '2d ago', uses: 31,
  },
  {
    id: 'kb-004', category: 'decision', title: 'ADR-007: We use Fastify, not Express',
    summary: 'Decision owner: Xie Ming · 2025-09 · Fastify chosen for schema-first validation, 2.3× throughput on our benchmarks, and first-class TypeScript types. Express migration complete.',
    body: 'Trade-offs: smaller ecosystem, plugin API learning curve. Accepted because perf + DX on API surface outweigh. Revisit 2026 if Fastify stalls.',
    tags: ['adr','framework','typescript'],
    projects: ['ATLAS','CORE'],
    sources: [{issue:'ATL-24', title:'ADR-007 framework selection'}],
    author: { kind:'human', name:'Xie Ming', avatar:'XM', color:'linear-gradient(135deg,#3D63FF,#1E40AF)' },
    verified: true, verifiedBy: 'Xie Ming', pinned: true,
    created: '47d ago', updated: '47d ago', uses: 18,
  },
  {
    id: 'kb-005', category: 'runbook', title: 'Recover from engine degradation (`gemini` latency > 500ms)',
    summary: '1. Check node health on /nodes. 2. If single-node, shift workloads with `bks route --from gemini --to claude`. 3. File incident if > 15min. 4. Post-incident: capture root cause here.',
    body: 'Known triggers: regional gcp slowness, model API throttling, node resource pressure. First-response SLA: 5 min.',
    tags: ['ops','engines','incident'],
    projects: ['CORE','PULSE'],
    sources: [{issue:'CORE-72', title:'Gemini degraded — eu-central'}, {issue:'PLS-18', title:'Engine fallback policy'}],
    author: { kind:'human', name:'Sam Ortega', avatar:'SO', color:'linear-gradient(135deg,#10A37F,#047857)' },
    verified: true, verifiedBy: 'Sam Ortega',
    created: '6d ago', updated: '1d ago', uses: 9,
  },
  {
    id: 'kb-006', category: 'gotcha', title: 'pnpm workspace hoisting breaks vitest globals',
    summary: 'When `vitest` is hoisted to root but test files import from package, `describe`/`it` globals leak. Add `test.globals = false` per-package or set `.npmrc shamefully-hoist=false`.',
    tags: ['pnpm','vitest','monorepo'],
    projects: ['NOVA','EDGE'],
    sources: [{issue:'NOV-61', title:'Flaky tests in nova ui'}],
    author: { kind:'agent', name:'codex-tests', engine:'codex' },
    verified: false,
    created: '4d ago', updated: '4d ago', uses: 4,
  },
  {
    id: 'kb-007', category: 'convention', title: 'Error responses: RFC 7807 problem+json',
    summary: 'All 4xx/5xx MUST follow { type, title, status, detail, instance }. No raw stack traces. Use `@bks/problem` helper. Enforced by middleware in all API services.',
    tags: ['errors','api','http'],
    projects: ['ATLAS','HELIX','CORE'],
    sources: [{issue:'ATL-301', title:'Standardize error envelope'}],
    author: { kind:'agent', name:'opus-review', engine:'claude' },
    verified: true, verifiedBy: 'Xie Ming',
    created: '22d ago', updated: '11d ago', uses: 38,
  },
  {
    id: 'kb-008', category: 'pattern', title: 'Feature-flag rollout: 1% → 10% → 50% → 100%',
    summary: 'Every user-facing change ships behind a LaunchDarkly flag. Minimum 24h per step. Cancel on any SLO regression > 1%.',
    tags: ['rollout','flags','safety'],
    projects: ['ATLAS','HELIX','NOVA'],
    sources: [{issue:'NOV-55', title:'Policy block: write to config/prod.yaml'}, {issue:'ATL-412', title:'Rate-limit under load'}],
    author: { kind:'human', name:'Xie Ming', avatar:'XM', color:'linear-gradient(135deg,#3D63FF,#1E40AF)' },
    verified: true, verifiedBy: 'Xie Ming',
    created: '31d ago', updated: '7d ago', uses: 26,
  },
  {
    id: 'kb-009', category: 'decision', title: 'ADR-012: All agent runs must be bound to a node',
    summary: 'Every issue execution is scheduled onto a specific node. No floating runs. This gives us deterministic resource accounting, auditable logs, and policy enforcement.',
    tags: ['adr','agents','nodes'],
    projects: ['CORE'],
    sources: [{issue:'CORE-40', title:'ADR-012 node binding'}],
    author: { kind:'human', name:'Xie Ming', avatar:'XM', color:'linear-gradient(135deg,#3D63FF,#1E40AF)' },
    verified: true, verifiedBy: 'Xie Ming', pinned: true,
    created: '35d ago', updated: '35d ago', uses: 12,
  },
  {
    id: 'kb-010', category: 'gotcha', title: 'Node.js `fetch` does NOT honor `NO_PROXY` env var',
    summary: 'Undici (node\u2019s fetch) ignores NO_PROXY. Must configure `ProxyAgent` explicitly or use `got`/`axios` for services behind corporate proxy.',
    tags: ['node','networking','proxy'],
    projects: ['EDGE'],
    sources: [{issue:'EDGE-18', title:'Fetch hangs on internal service'}],
    author: { kind:'agent', name:'sonnet-dev', engine:'claude' },
    verified: false,
    created: '2d ago', updated: '2d ago', uses: 2,
  },
];

// Auto-generated "extraction candidates" — agent-proposed knowledge pending review
const KNOWLEDGE_PENDING = [
  {
    id: 'kbp-01', source: {issue:'ATL-412', title:'Rate-limit under load'},
    proposed: 'Always pipeline Redis ZADD + ZREMRANGEBYSCORE in a MULTI to keep sliding-window atomic.',
    category: 'pattern', confidence: 0.91, extractedBy: 'opus-review',
  },
  {
    id: 'kbp-02', source: {issue:'HLX-217', title:'Approve: add stripe dependency'},
    proposed: 'New runtime deps with > 10 transitive packages require security review, not just license check.',
    category: 'convention', confidence: 0.74, extractedBy: 'opus-review',
  },
  {
    id: 'kbp-03', source: {issue:'CORE-72', title:'Gemini degraded — eu-central'},
    proposed: 'Auto-failover to sibling region after 90s of p95 > 800ms, not 15min as docs suggest.',
    category: 'runbook', confidence: 0.62, extractedBy: 'sonnet-dev',
  },
];

// Roles = global, reusable agent personas.
// A role bundles { system prompt, default engine, allowed engines } and is
// referenced by project capabilities. Editing a role's prompt updates every
// project that points to it. Built-in roles can be cloned but not deleted.
const OPERATORS = [
  { id: 'greenfield-builder', name: 'Greenfield Builder', icon: 'zap', color: '#7C5CFF',
    capabilities: ['feature'], defaultEngine: 'claude', allowedEngines: ['claude','codex'], builtIn: true,
    desc: 'Plans then ships net-new functionality end-to-end.',
    prompt: `You are a feature implementation agent.
Goal: ship the described functionality end-to-end on this node.
Plan briefly, then: scaffold the module, wire it into existing entry points, add unit + integration tests, run the suite, and open a PR with a concise rationale.
Constraints: keep public APIs stable unless the issue says otherwise. Stop and ask if the scope is ambiguous.` },
  { id: 'incremental-shipper', name: 'Incremental Shipper', icon: 'gitBranch', color: '#22C55E',
    capabilities: ['feature'], defaultEngine: 'codex', allowedEngines: ['claude','codex'], builtIn: true,
    desc: 'Splits features into small, mergeable PRs behind flags.',
    prompt: `You are an incremental delivery agent.
Decompose the feature into the smallest mergeable steps. Each step: a single PR, behind a feature flag, with tests, that ships independently.
Open the first PR only. Leave a checklist in the issue for follow-ups.` },
  { id: 'root-cause-investigator', name: 'Root-cause Investigator', icon: 'alert', color: '#FF7A45',
    capabilities: ['bug'], defaultEngine: 'claude', allowedEngines: ['claude','codex','gemini'], builtIn: true,
    desc: 'Reproduces, isolates, patches with regression test.',
    prompt: `You are a bug-fix agent.
Step 1: reproduce the issue from the report (write the failing test first).
Step 2: isolate the root cause — state it in one sentence before patching.
Step 3: apply the minimum viable patch, confirm the regression test passes and no other tests break.
Leave a changelog line and link to the reproduction commit.` },
  { id: 'quick-patcher', name: 'Quick Patcher', icon: 'zap', color: '#F59E0B',
    capabilities: ['bug'], defaultEngine: 'codex', allowedEngines: ['claude','codex','gemini'], builtIn: true,
    desc: 'For obvious bugs — patch first, document second.',
    prompt: `You are a quick-patch agent.
The bug is small or obvious. Patch it, add a smoke test, ship.
Skip the deep root-cause writeup. Note in the PR if you suspect a deeper issue worth filing separately.` },
  { id: 'surgical-refactorer', name: 'Surgical Refactorer', icon: 'gitBranch', color: '#06B6D4',
    capabilities: ['refactor'], defaultEngine: 'claude', allowedEngines: ['claude'], builtIn: true,
    desc: 'Behavior-preserving structural cleanup.',
    prompt: `You are a refactoring agent.
Preserve observable behavior exactly. Tests must stay green throughout — run them after every logical step, not just at the end.
Favor small commits: one named transformation per commit (extract, inline, rename, move).
Produce a before/after summary noting any accidental API surface changes.` },
  { id: 'senior-reviewer', name: 'Senior Reviewer', icon: 'checkCircle', color: '#A855F7',
    capabilities: ['review'], defaultEngine: 'claude', allowedEngines: ['claude'], builtIn: true,
    desc: 'Deep PR review — correctness, security, perf.',
    prompt: `You are a senior code reviewer.
Review for: correctness, edge cases, security (injection, authz, secrets), performance hotspots, API ergonomics, test coverage, and naming.
Leave inline comments, suggest concrete diffs where useful, and end with a verdict: approve / request changes / block + reason.` },
  { id: 'docs-curator', name: 'Docs Curator', icon: 'book', color: '#0EA5E9',
    capabilities: ['docs'], defaultEngine: 'gemini', allowedEngines: ['claude','gemini'], builtIn: true,
    desc: 'Audience-first docs with runnable examples.',
    prompt: `You are a documentation agent.
Audience first: state who the reader is in one line before writing.
Prefer examples over prose. Include a runnable snippet for every public API touched.
Update any adjacent READMEs, changelogs, and inline comments that reference the changed code.` },
  { id: 'decision-researcher', name: 'Decision Researcher', icon: 'search', color: '#EC4899',
    capabilities: ['research'], defaultEngine: 'gemini', allowedEngines: ['gemini','claude'], builtIn: true,
    desc: 'Produces decision docs with trade-off tables.',
    prompt: `You are a research agent.
Produce a decision doc: problem statement, 2–4 viable options, trade-offs table (cost, risk, maintenance, perf), and a recommendation with rationale.
Cite sources inline. Flag anything you couldn't verify.` },
  { id: 'cautious-operator', name: 'Cautious Operator', icon: 'settings', color: '#64748B',
    capabilities: ['ops'], defaultEngine: 'codex', allowedEngines: ['codex'], builtIn: true,
    desc: 'Plan-first ops; treats prod as read-only by default.',
    prompt: `You are an ops / infra agent.
Treat production as read-only unless the issue explicitly grants write. Always show the plan (terraform plan, diff, dry-run) before applying.
Roll out behind a flag if the change is user-visible. Leave a runbook entry for on-call.` },
  { id: 'manual-handoff', name: 'Manual Handoff', icon: 'person', color: '#6B7280',
    capabilities: ['manual'], defaultEngine: 'human', allowedEngines: ['human'], builtIn: true,
    desc: "Routes to the node's default human assignee.",
    prompt: `Assigned to a human. No system prompt is injected — the assignee works the issue directly.
Add context notes here to brief them (scope, constraints, gotchas, links to prior art).` },
  // Custom (user-defined) example
  { id: 'security-auditor', name: 'Security Auditor', icon: 'shield', color: '#DC2626',
    capabilities: ['review','research'], defaultEngine: 'claude', allowedEngines: ['claude','gemini'], builtIn: false,
    desc: 'Threat-models the change before approving.',
    prompt: `You are a security review agent.
Threat-model the change: list trust boundaries crossed, data classes touched, and authn/authz paths affected.
Flag injection vectors, secret exposure, and missing rate limits. End with a CVSS-style severity if any issue is found.` },
];

// Capabilities = intents you can pick when creating an issue.
// Each capability lists its default role and which other roles can serve it.
// Engines come from the role; capability is the intent layer.
const CAPABILITIES = [
  { id: 'feature',   icon: 'zap',         label: 'Feature',        desc: 'Add new functionality — scaffold, wire, test',          engines: ['claude','codex'],         defaultOperator: 'greenfield-builder' },
  { id: 'bug',       icon: 'alert',       label: 'Bug fix',        desc: 'Reproduce, isolate, patch with regression test',        engines: ['claude','codex','gemini'],defaultOperator: 'root-cause-investigator' },
  { id: 'refactor',  icon: 'gitBranch',   label: 'Refactor',       desc: 'Improve structure without changing behavior',           engines: ['claude'],                 defaultOperator: 'surgical-refactorer' },
  { id: 'review',    icon: 'checkCircle', label: 'Code review',    desc: 'Deep PR review — correctness, security, perf',         engines: ['claude'],                 defaultOperator: 'senior-reviewer' },
  { id: 'docs',      icon: 'book',        label: 'Docs',           desc: 'Write or update docs, comments, READMEs',               engines: ['claude','gemini'],        defaultOperator: 'docs-curator' },
  { id: 'research',  icon: 'search',      label: 'Research',       desc: 'Investigate options, compare libs, summarize',          engines: ['gemini','claude'],        defaultOperator: 'decision-researcher' },
  { id: 'ops',       icon: 'settings',    label: 'Ops / infra',    desc: 'Runtime, deploy, env, CI changes',                      engines: ['codex'],                  defaultOperator: 'cautious-operator' },
  { id: 'manual',    icon: 'person',      label: 'Manual · Human', desc: "Node's default agent — a human handles it",             engines: ['human'],                  defaultOperator: 'manual-handoff' },
];

// Personal & shared notes — quick scratchpads, decisions, drafts.
// Distinct from KNOWLEDGE (curated rules) — these are work-in-progress thinking.
const NOTES = [
  {
    id: 'n-001', title: 'Q2 platform roadmap thoughts', updated: '2h', pinned: true,
    tags: ['planning', 'roadmap'], shared: false, author: 'XM',
    body: `## Themes\n- Migrate gateway from buffered to streaming (ATL-412 in flight)\n- Tighten cost ceiling — engine spend hit 14% over budget last sprint\n- Multi-tenant routing for Helix billing\n\n## Open questions\n- Do we keep Gemini as fallback or drop?\n- node-eu-central is at 12% load — kill or retain for compliance?`,
  },
  {
    id: 'n-002', title: 'Sonnet vs Codex review notes', updated: '5h', pinned: true,
    tags: ['operators', 'evaluation'], shared: true, author: 'XM',
    body: `Comparing review quality across our two main reviewer operators.\n\n**Sonnet (opus-review)**\n- Better at architectural critique\n- Misses ~15% of obvious style issues\n- Avg 3.8 min per PR\n\n**Codex (codex-review)**\n- Tighter style enforcement\n- Sometimes overly pedantic\n- Avg 2.1 min per PR\n\nLeaning toward Sonnet for design-review capability, Codex for stylistic reviews.`,
  },
  {
    id: 'n-003', title: 'Standup — Apr 23', updated: '1d', pinned: false,
    tags: ['standup'], shared: true, author: 'XM',
    body: `## Yesterday\n- Reviewed ATL-411 rate-limit bypass fix\n- Approved 3 deps bumps in HLX\n\n## Today\n- ATL-412 streaming — finalize TransformStream wiring\n- Pair with Rita on EDGE-46\n\n## Blocked\n- Waiting on Helix Stripe creds rotation`,
  },
  {
    id: 'n-004', title: 'Operator prompt tweaks', updated: '2d', pinned: false,
    tags: ['operators', 'prompts'], shared: false, author: 'XM',
    body: `Things to try:\n- Add "prefer named exports" to engineer-impl prompt\n- Tighten haiku-triage to skip security issues (escalate to senior reviewer)\n- Test deepseek-doc with our existing API ref style guide\n\nAlso — operators page should let you A/B test prompts side-by-side.`,
  },
  {
    id: 'n-005', title: 'Incident: Apr 19 cache thrash', updated: '5d', pinned: false,
    tags: ['incident', 'postmortem'], shared: true, author: 'RC',
    body: `Edge cold-start fired cache revalidation twice → 2x upstream load for 4 min.\n\nRoot cause: missing dedup token in revalidation key.\n\nFix tracked in ATL-409. Adding to knowledge base as a gotcha pattern.`,
  },
  {
    id: 'n-006', title: 'Hiring pipeline draft', updated: '1w', pinned: false,
    tags: ['hiring', 'draft'], shared: false, author: 'XM',
    body: `Senior platform engineer JD draft.\n\n## Must-have\n- Distributed systems, multi-region\n- Edge runtime experience\n- Comfortable owning on-call\n\n## Nice-to-have\n- Prior agent/LLM infra work\n- Open source contributions to gateway/proxy projects`,
  },
];


