# Job Taxonomy & Dashboard Grouping Design

**Date**: 2026-03-09
**Status**: Approved
**Scope**: jobs/jobs.yaml, jobs/app_ng.py, jobs/ctl.py

## Problem

The jobs dashboard groups ~35 jobs into tabs using inconsistent principles: domain (Finance), method (YouTube), project (PLTR, VIC), and catch-all (Other). "Longform" and "Research" are meaningless to a returning user. No sub-grouping within large tabs. No group-level operations (pause/run a group). Tags exist but aren't used for cross-cutting queries.

## Design Principles

1. **Group by output domain / intent** — "what knowledge am I getting," not "what API am I calling"
2. **Cross-domain intake is its own group** — channels that feed multiple domains aren't forced into one
3. **Hybrid: explicit groups + tags** — groups for stable nav, tags for cross-cutting ops ("pause all youtube-api")
4. **Sub-groups within big tents** — 1 level deep, by analytical workflow
5. **Group-level ops** — pause/resume/run-now at group and sub-group level

## Taxonomy

### Top-Level Groups

| Group | Description | Jobs |
|---|---|---|
| **Finance** | Markets, companies, investing | ~18 jobs |
| **Research Feeds** | Cross-domain knowledge intake | 4 jobs |
| **People** | VC/investor intelligence | 5 jobs |
| **System** | Codebase health | 9 jobs (autodo_*) |
| **Projects** | Standalone efforts | 2+ jobs |

### Finance Sub-Groups

| Sub-Group | Jobs |
|---|---|
| **Market Monitoring** | newsflow_monitor, newsflow_yt_investors, dumb_money_live |
| **Company Research** | company_analysis, semi_assessment, earnings_backfill_largecap |
| **PLTR** | pltr_discovery, pltr_content_processing |
| **Supply Chain** | supplychain_anchors, supplychain_expand, supplychain_news |
| **Value Investing** | vic_ideas, vic_text_extract, vic_wayback, vic_returns, quantpedia |

### Research Feeds

| Job | Topic |
|---|---|
| a16z | Tech / VC |
| dwarkesh_podcast | Science / History |
| lex_fridman | Science / Tech / Philosophy |
| healthy_gamer_all | Psychology |

Test: "If I turned off all finance work, would I still want this feed running?" Yes → Research Feeds. No → Finance (that's why dumb_money is in Finance).

### People

person_intel, vc_data_bulk, vc_data_openvc, vc_data_signal_nfx, vc_firm_analysis

### Projects

moltbook_monitor, nonprofit_990s, and future standalone efforts that don't fit elsewhere.

## Configuration Format

### jobs.yaml: `group` and `subgroup` fields

```yaml
pltr_discovery:
  group: finance
  subgroup: pltr
  tags: [pltr, youtube-api, monitor]
  # ... rest of config

a16z:
  group: research-feeds
  tags: [yt-channel, youtube-api, tech]
  # ... rest of config
```

Every job has exactly one `group`. `subgroup` is optional (only Finance needs it now). Tags remain for cross-cutting queries.

### Group registry in jobs.yaml

```yaml
groups:
  finance:
    name: Finance
    emoji: "📊"
    subgroups:
      market-monitoring: Market Monitoring
      company-research: Company Research
      pltr: PLTR
      supply-chain: Supply Chain
      value-investing: Value Investing
  research-feeds:
    name: Research Feeds
    emoji: "🎓"
  people:
    name: People
    emoji: "👤"
  system:
    name: System
    emoji: "🔧"
  projects:
    name: Projects
    emoji: "📋"
```

This replaces `JOB_GROUPS` in app_ng.py — the dashboard reads grouping from YAML, not hardcoded Python.

## Dashboard Changes

### Navigation

Current: flat tabs (Finance | Supply Chain | VIC | ...) — 8 tabs
New: 5 top-level tabs, Finance has collapsible sub-groups in the overview grid

```
Finance | Research Feeds | People | System | Projects
```

### Sub-groups in overview grid

Within Finance, the AG Grid shows rows grouped by sub-group using AG Grid's row grouping:

```
▼ Market Monitoring
    newsflow_monitor       📰  ▶  2 pending  140 done
    newsflow_yt_investors  🎬  ▶  0 pending  95 done
    dumb_money_live        📺  ⏸  3 pending  420 done
▼ PLTR
    pltr_discovery         🔎  ▶  0 pending  200 done
    pltr_content_processing 📝  ▶  5 pending  180 done
▼ Supply Chain
    ...
```

Collapsible. Click sub-group header → expand/collapse. Click row → show items (existing behavior).

### Group-level operations

Add to overview header (next to time toggle):

- **⏸ Pause Group** — pauses all jobs in current tab (or selected sub-group)
- **▶ Run Group** — unpause + wake all jobs in group
- **Status badge** — red/yellow/green per group in tab bar

### Tag filtering

Add a tag filter dropdown (multi-select) to the overview:
- Shows all tags used by jobs in current tab
- Filter narrows the grid (e.g., select `youtube-api` → only YT jobs)
- Cross-tab: `jobctl pause --tag youtube-api` pauses across all groups

## CLI Changes

```bash
jobctl pause --group finance              # pause all finance jobs
jobctl pause --group finance/pltr         # pause PLTR sub-group
jobctl run --group research-feeds         # run all research feeds
jobctl pause --tag youtube-api            # pause all youtube jobs (cross-group)
jobctl list --group finance               # list finance jobs only
```

## Migration

1. Add `groups:` registry to top of jobs.yaml
2. Add `group:` and `subgroup:` to each job definition
3. Remove `JOB_GROUPS` from app_ng.py — read from YAML
4. Remove tag-based tab matching logic
5. Update `_build_job_group_tab` to support sub-group row grouping
6. Add group-level pause/run buttons
7. Add tag filter dropdown
8. Update `jobctl` with `--group` and `--tag` flags

Tags like `finance`, `longform`, `vic` that were added purely for tab matching get removed. Real operational tags remain: `yt-channel`, `co-research`, `podcast`, etc.

## Not in Scope

- Nested sub-sub-groups (YAGNI at 35 jobs)
- Drag-and-drop reordering
- User-defined custom views/saved filters (tags cover this for now)
- Group-level scheduling (schedules are inherently per-job)
