How automatable is your job? The Messiness Index scores jobs across 6 dimensions of task complexity. Higher messiness = harder to automate.
---
format: typebulb/v1
name: Messiness
---
**code.tsx**
```tsx
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
interface JobAnalysis {
job: string;
scores: {
coordination: number;
knowledge: number;
exceptions: number;
feedback: number;
environment: number;
adversarial: number;
};
notes: string;
}
interface Insight {
jobs: JobAnalysis[];
}
const DIMENSIONS = [
{ key: "coordination", label: "Coord", full: "Coordination", desc: "People, sync, time pressure, relationship depth" },
{ key: "knowledge", label: "Know", full: "Knowledge", desc: "Domains touched, depth required" },
{ key: "exceptions", label: "Except", full: "Exceptions", desc: "Frequency, cost, novelty" },
{ key: "feedback", label: "Feed", full: "Feedback", desc: "Measurability, speed, agreement" },
{ key: "environment", label: "Env", full: "Environment", desc: "Physical variability, accessibility, precision" },
{ key: "adversarial", label: "Adver", full: "Adversarial", desc: "Active opposition, stakes, adaptiveness" },
] as const;
type DimKey = typeof DIMENSIONS[number]["key"];
const SCORE_LABELS: Record<number, string> = {
0: "N/A",
1: "V.Low",
2: "Low",
3: "Medium",
4: "High",
5: "V.High",
};
function scoreColor(score: number): string {
if (score === 0) return "#333";
const colors = ["", "#2d5a27", "#4a7c3f", "#c9a227", "#c46210", "#a82a2a"];
return colors[score] || "#333";
}
function totalMessiness(scores: JobAnalysis["scores"]): number {
return Object.values(scores).reduce((sum, v) => sum + (v || 0), 0);
}
function App() {
const [insight, setInsight] = useState<Insight | null>(() => {
try { return tb.insight<Insight>(); } catch { return null; }
});
const [isGenerating, setIsGenerating] = useState(false);
const [selectedJob, setSelectedJob] = useState<JobAnalysis | null>(null);
const [sortBy, setSortBy] = useState<DimKey | "total" | "name">("total");
const [sortAsc, setSortAsc] = useState(false);
const handleAnalyze = async () => {
setIsGenerating(true);
try {
const result = await tb.infer<Insight>();
if (result) {
setInsight(result);
setSelectedJob(null);
}
} finally {
setIsGenerating(false);
}
};
const sortedJobs = insight?.jobs.slice().sort((a, b) => {
let cmp = 0;
if (sortBy === "name") {
cmp = a.job.localeCompare(b.job);
} else if (sortBy === "total") {
cmp = totalMessiness(b.scores) - totalMessiness(a.scores);
} else {
cmp = (b.scores[sortBy] || 0) - (a.scores[sortBy] || 0);
}
return sortAsc ? -cmp : cmp;
});
const handleSort = (key: DimKey | "total" | "name") => {
if (sortBy === key) {
setSortAsc(!sortAsc);
} else {
setSortBy(key);
setSortAsc(false);
}
};
return (
<div className="app">
<header>
<h1>How Automatable Is Your Job?</h1>
<p className="brand">The Messiness Index</p>
<p className="tagline">Higher messiness = harder to automate</p>
<button className={`analyze-btn ${isGenerating ? "loading" : ""}`} onClick={handleAnalyze}>
{isGenerating ? "Analyzing..." : "Analyze Jobs"}
</button>
</header>
{insight && (
<>
<div className="table-wrap">
<table className="matrix">
<thead>
<tr>
<th className={`sortable ${sortBy === "name" ? "active" : ""}`} onClick={() => handleSort("name")}>
Job {sortBy === "name" && (sortAsc ? "↑" : "↓")}
</th>
{DIMENSIONS.map(d => (
<th
key={d.key}
className={`sortable dim-header ${sortBy === d.key ? "active" : ""}`}
onClick={() => handleSort(d.key)}
title={`${d.full}: ${d.desc}`}
>
<span className="dim-label">{d.full}</span>
{sortBy === d.key && <span className="sort-arrow">{sortAsc ? "↑" : "↓"}</span>}
</th>
))}
<th
className={`sortable ${sortBy === "total" ? "active" : ""}`}
onClick={() => handleSort("total")}
>
Total {sortBy === "total" && (sortAsc ? "↑" : "↓")}
</th>
</tr>
</thead>
<tbody>
{sortedJobs?.map(job => (
<tr
key={job.job}
className={selectedJob?.job === job.job ? "selected" : ""}
onClick={() => setSelectedJob(selectedJob?.job === job.job ? null : job)}
>
<td className="job-name">{job.job}</td>
{DIMENSIONS.map(d => {
const score = job.scores[d.key] ?? 0;
return (
<td key={d.key} className="score-cell" style={{ background: scoreColor(score) }}>
{SCORE_LABELS[score]}
</td>
);
})}
<td className="total-cell">{totalMessiness(job.scores)}</td>
</tr>
))}
</tbody>
</table>
</div>
{selectedJob && (
<div className="detail-panel">
<h3>{selectedJob.job}</h3>
<p className="notes">{selectedJob.notes}</p>
<div className="radar-wrap">
<RadarChart scores={selectedJob.scores} />
</div>
</div>
)}
</>
)}
{!insight && (
<div className="empty">
<p>Add any jobs to the Data tab, then click "Analyze Jobs".</p>
<p className="hint">We'll score each one across 6 dimensions of task complexity.</p>
</div>
)}
</div>
);
}
function RadarChart({ scores }: { scores: JobAnalysis["scores"] }) {
const size = 200;
const cx = size / 2;
const cy = size / 2;
const r = 70;
const dims = DIMENSIONS.filter(d => scores[d.key] > 0);
if (dims.length < 3) return <div className="radar-empty">Not enough dimensions for radar</div>;
const points = dims.map((d, i) => {
const angle = (Math.PI * 2 * i) / dims.length - Math.PI / 2;
const val = scores[d.key] / 5;
return {
x: cx + Math.cos(angle) * r * val,
y: cy + Math.sin(angle) * r * val,
lx: cx + Math.cos(angle) * (r + 20),
ly: cy + Math.sin(angle) * (r + 20),
label: d.label,
};
});
const pathD = points.map((p, i) => `${i === 0 ? "M" : "L"} ${p.x} ${p.y}`).join(" ") + " Z";
const gridLevels = [0.2, 0.4, 0.6, 0.8, 1];
return (
<svg width={size} height={size} className="radar">
{gridLevels.map(level => {
const gridPath = dims.map((_, i) => {
const angle = (Math.PI * 2 * i) / dims.length - Math.PI / 2;
const x = cx + Math.cos(angle) * r * level;
const y = cy + Math.sin(angle) * r * level;
return `${i === 0 ? "M" : "L"} ${x} ${y}`;
}).join(" ") + " Z";
return <path key={level} d={gridPath} className="radar-grid" />;
})}
{dims.map((_, i) => {
const angle = (Math.PI * 2 * i) / dims.length - Math.PI / 2;
return (
<line
key={i}
x1={cx}
y1={cy}
x2={cx + Math.cos(angle) * r}
y2={cy + Math.sin(angle) * r}
className="radar-axis"
/>
);
})}
<path d={pathD} className="radar-area" />
{points.map((p, i) => (
<text key={i} x={p.lx} y={p.ly} className="radar-label" textAnchor="middle" dominantBaseline="middle">
{p.label}
</text>
))}
</svg>
);
}
createRoot(document.getElementById("root")!).render(<App />);
```
**styles.css**
```css
:root {
--bg: #0d1117;
--panel: #161b22;
--border: #30363d;
--text: #c9d1d9;
--dim: #8b949e;
--accent: #58a6ff;
}
html[data-theme="light"] {
--bg: #f6f8fa;
--panel: #ffffff;
--border: #d0d7de;
--text: #24292f;
--dim: #57606a;
--accent: #0969da;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body {
font: 13px/1.5 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: var(--bg);
color: var(--text);
padding: 16px;
}
.app { max-width: 900px; margin: 0 auto; }
header { text-align: center; margin-bottom: 24px; }
h1 { font-size: 32px; font-weight: 600; margin-bottom: 8px; }
.brand { font-size: 24px; color: var(--accent); font-weight: 500; margin-bottom: 8px; }
.tagline { color: var(--dim); font-size: 18px; margin-bottom: 20px; }
.analyze-btn {
background: var(--accent);
color: #fff;
border: none;
padding: 10px 24px;
border-radius: 6px;
font: inherit;
font-weight: 500;
cursor: pointer;
transition: opacity 0.2s;
}
.analyze-btn:hover { opacity: 0.9; }
.analyze-btn.loading { opacity: 0.6; cursor: wait; }
.summary {
background: var(--panel);
border: 1px solid var(--border);
border-radius: 6px;
padding: 12px 16px;
margin-bottom: 16px;
font-size: 14px;
line-height: 1.6;
}
.table-wrap { overflow-x: auto; margin-bottom: 16px; }
.matrix {
width: 100%;
border-collapse: collapse;
background: var(--panel);
border: 1px solid var(--border);
border-radius: 6px;
overflow: hidden;
font-size: 12px;
}
.matrix th, .matrix td {
padding: 8px 10px;
text-align: center;
border-bottom: 1px solid var(--border);
}
.matrix th {
background: var(--bg);
font-weight: 600;
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.matrix th.sortable { cursor: pointer; user-select: none; }
.matrix th.sortable:hover { color: var(--accent); }
.matrix th.active { color: var(--accent); }
.dim-header { position: relative; }
.dim-label {
display: inline-block;
max-width: 45px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: middle;
}
.sort-arrow { margin-left: 2px; }
@media (min-width: 700px) {
.dim-label { max-width: none; }
}
.matrix tbody tr { cursor: pointer; transition: background 0.15s; }
.matrix tbody tr:hover { background: rgba(88, 166, 255, 0.1); }
.matrix tbody tr.selected { background: rgba(88, 166, 255, 0.15); }
.job-name { text-align: left; font-weight: 500; white-space: nowrap; }
.score-cell { color: #fff; font-weight: 500; min-width: 50px; }
.total-cell { font-weight: 600; background: var(--bg); }
.detail-panel {
background: var(--panel);
border: 1px solid var(--border);
border-radius: 6px;
padding: 16px;
margin-bottom: 16px;
}
.detail-panel h3 { font-size: 16px; margin-bottom: 8px; }
.detail-panel .notes { color: var(--dim); margin-bottom: 16px; }
.radar-wrap { display: flex; justify-content: center; }
.radar-empty { color: var(--dim); font-style: italic; }
.radar .radar-grid { fill: none; stroke: var(--border); stroke-width: 1; }
.radar .radar-axis { stroke: var(--border); stroke-width: 1; }
.radar .radar-area { fill: rgba(88, 166, 255, 0.3); stroke: var(--accent); stroke-width: 2; }
.radar .radar-label { fill: var(--dim); font-size: 10px; }
.empty {
text-align: center;
padding: 48px;
color: var(--dim);
}
.empty .hint { margin-top: 8px; font-size: 12px; }
```
**index.html**
```html
<div id="root"></div>
```
**data.txt**
```txt
Nurse
Programmer
Quant (finance)
Plumber
Litigation lawyer
ER Doctor
Factory assembly worker
Teacher (K-12)
CEO
Security researcher
Radiologist
Graphic designer
Therapist
Truck driver
Journalist
Real estate agent
Paralegal
Cashier
```
**infer.md**
```md
Analyze each job in the input data using the Task Messiness Framework.
## The Six Dimensions
Score each dimension from 0-5:
- **0 = N/A** - Dimension doesn't apply
- **1 = Very Low** - Negligible factor
- **2 = Low** - Minor factor
- **3 = Medium** - Meaningful factor
- **4 = High** - Major factor
- **5 = Very High** - Dominant factor
### Dimensions:
1. **Coordination** (people × synchronization × time pressure × relationship depth)
- How many people involved? How tightly synchronized? Real-time pressure? Deep relationships needed?
2. **Knowledge** (domains × depth)
- How many domains? How deep in each?
3. **Exceptions** (frequency × cost × novelty)
- How often do things go wrong? How costly? How unprecedented?
4. **Feedback** (measurability × speed × agreement)
- How clear is success? How fast do you know? Do stakeholders agree?
5. **Environment** (variability × accessibility × precision)
- Physical space unpredictability? Access constraints? Dexterity required?
- Score 0 for pure knowledge work with no physical component.
6. **Adversarial** (active opposition × stakes × adaptiveness)
- Is someone actively working against you? High stakes? Do they adapt?
- Score 0 if no adversarial dynamics.
## Output Format
Return a JSON object with:
- `jobs`: Array of job analyses, each with `job`, `scores` (object with all 6 dimension keys), and `notes` (1-2 sentence rationale)
```
**insight.json**
```json
{
"jobs": [
{
"job": "Nurse",
"scores": { "coordination": 5, "knowledge": 4, "exceptions": 5, "feedback": 4, "environment": 4, "adversarial": 1 },
"notes": "Extreme coordination with doctors, patients, families. Every patient is different. Physical care on variable human bodies. Patients may resist but aren't adversarial."
},
{
"job": "Programmer",
"scores": { "coordination": 4, "knowledge": 3, "exceptions": 4, "feedback": 3, "environment": 0, "adversarial": 1 },
"notes": "Works with PMs, designers, other devs. Multiple domains at moderate depth. Bugs and edge cases are frequent. Feedback is mixed (fast for correctness, slow for quality)."
},
{
"job": "Quant (finance)",
"scores": { "coordination": 3, "knowledge": 4, "exceptions": 4, "feedback": 3, "environment": 0, "adversarial": 4 },
"notes": "Deep multi-domain expertise. Markets are adversarial - others exploit your edge. P&L is measurable but attribution (skill vs luck) is contested."
},
{
"job": "Plumber",
"scores": { "coordination": 2, "knowledge": 3, "exceptions": 4, "feedback": 2, "environment": 4, "adversarial": 0 },
"notes": "Often solo. Every building is different with hidden conditions. High environmental variability - crawl spaces, behind walls. No adversarial dynamics."
},
{
"job": "Litigation lawyer",
"scores": { "coordination": 5, "knowledge": 4, "exceptions": 4, "feedback": 2, "environment": 1, "adversarial": 5 },
"notes": "Coordinates with courts, clients, experts. Opposing counsel is explicitly adversarial and adapts to your strategy. Outcomes take years."
},
{
"job": "ER Doctor",
"scores": { "coordination": 5, "knowledge": 5, "exceptions": 5, "feedback": 3, "environment": 4, "adversarial": 1 },
"notes": "Extreme time pressure, coordination with entire hospital. Deep expertise across emergencies. Physical intervention on critical patients. Life-or-death stakes."
},
{
"job": "Factory assembly worker",
"scores": { "coordination": 2, "knowledge": 2, "exceptions": 2, "feedback": 1, "environment": 2, "adversarial": 0 },
"notes": "Structured, repetitive tasks. Clear success criteria. Controlled environment. Already heavily automated."
},
{
"job": "Teacher (K-12)",
"scores": { "coordination": 4, "knowledge": 3, "exceptions": 4, "feedback": 2, "environment": 3, "adversarial": 2 },
"notes": "30 unique students, parents, administrators. Behavioral exceptions are constant. Outcomes take years to measure. Students may actively resist learning."
},
{
"job": "CEO",
"scores": { "coordination": 5, "knowledge": 4, "exceptions": 4, "feedback": 2, "environment": 1, "adversarial": 4 },
"notes": "All coordination, all the time. Competitors, activist investors, market forces are adversarial. Feedback is slow and contested by stakeholders."
},
{
"job": "Security researcher",
"scores": { "coordination": 2, "knowledge": 4, "exceptions": 4, "feedback": 3, "environment": 0, "adversarial": 5 },
"notes": "Deep technical expertise. Attackers actively evolve to bypass your defenses. The adversarial dimension is the core challenge - the problem resists being solved."
},
{
"job": "Radiologist",
"scores": { "coordination": 2, "knowledge": 4, "exceptions": 3, "feedback": 3, "environment": 0, "adversarial": 0 },
"notes": "Deep imaging expertise, but mostly independent reading. AI makes inroads on pattern recognition, but rare conditions, atypical presentations, and clinical context integration remain challenging."
},
{
"job": "Graphic designer",
"scores": { "coordination": 3, "knowledge": 3, "exceptions": 3, "feedback": 2, "environment": 0, "adversarial": 0 },
"notes": "Client coordination and iteration cycles. Design judgment and brand consistency. AI generates images but client relationships, revision loops, and taste remain human."
},
{
"job": "Therapist",
"scores": { "coordination": 3, "knowledge": 4, "exceptions": 4, "feedback": 1, "environment": 0, "adversarial": 1 },
"notes": "Deep relationship over months/years. Each patient unique. Feedback is extremely slow (therapeutic outcomes) and subjective. Patient resistance isn't adversarial but adds complexity."
},
{
"job": "Truck driver",
"scores": { "coordination": 2, "knowledge": 2, "exceptions": 3, "feedback": 2, "environment": 4, "adversarial": 0 },
"notes": "Self-driving's target, but environment is the barrier: weather, construction, rural roads, loading docks, mechanical issues. Highway driving is easier than last-mile."
},
{
"job": "Journalist",
"scores": { "coordination": 4, "knowledge": 3, "exceptions": 3, "feedback": 2, "environment": 2, "adversarial": 3 },
"notes": "Source relationships, editor coordination, deadline pressure. Sources may deceive, subjects may stonewall or sue. Quality is subjective; engagement metrics are gameable."
},
{
"job": "Real estate agent",
"scores": { "coordination": 4, "knowledge": 3, "exceptions": 3, "feedback": 2, "environment": 3, "adversarial": 2 },
"notes": "Coordinates buyers, sellers, lenders, inspectors. Local market knowledge. Physical property showings. Competing agents and negotiation dynamics. Zillow hasn't killed this yet."
},
{
"job": "Paralegal",
"scores": { "coordination": 3, "knowledge": 3, "exceptions": 2, "feedback": 2, "environment": 0, "adversarial": 1 },
"notes": "Supports attorneys with document prep and research. More routine than attorney work. AI document review is making inroads on the lower-complexity portions."
},
{
"job": "Cashier",
"scores": { "coordination": 1, "knowledge": 1, "exceptions": 2, "feedback": 1, "environment": 1, "adversarial": 0 },
"notes": "Minimal coordination, simple knowledge. Self-checkout has largely automated this. Remaining value is handling exceptions (returns, ID checks) and human presence preference."
}
]
}
```
**config.json**
```json
{
"dependencies": {
"react": "^19.2.0",
"react-dom": "^19.2.0"
},
"description": "How automatable is your job? The Messiness Index scores jobs across 6 dimensions of task complexity. Higher messiness = harder to automate.",
"inference": {
"title": "Analyze Jobs",
"dataTitle": "Jobs to Analyze",
"submitTitle": "Run Analysis"
}
}
```
**notes.md**
```md
# Task Messiness Framework
A framework for quantifying the complexity of tasks/jobs as it relates to automation potential.
## The Six Dimensions
1. **Coordination** - people × synchronization × time pressure × relationship depth
2. **Knowledge** - domains × depth
3. **Exceptions** - frequency × cost × novelty
4. **Feedback** - measurability × speed × agreement
5. **Environment** - variability × accessibility × precision
6. **Adversarial** - active opposition × stakes × adaptiveness
## Key Insights
- **Low messiness = automatable now**: Jobs scoring Low/Very Low across all dimensions are already automated or nearly extinct.
- **Environment is the robotics barrier**: Physical jobs persist even when cognitively "simpler" than knowledge work.
- **Coordination × Exceptions = human core**: Very High on both = furthest from automation.
- **Adversarial domains are moving targets**: The solution changes the problem.
- **Slow feedback = hard to train**: Can't efficiently learn what works.
## Scoring Guide
- 0 = N/A (dimension doesn't apply)
- 1 = Very Low
- 2 = Low
- 3 = Medium
- 4 = High
- 5 = Very High
```