---
title: "The CUJ Engineering Framework: Eliminating Speculative Code Through Autonomous Agent Workflows"
description: "A product-driven engineering framework and agentic skill that captures real-world user friction via standardized Mad Libs formulas and autonomously translates them into secure, verified production pull requests."
url: "https://herrington.ai/cujs/cuj-engineering-framework/"
markdown_url: "https://herrington.ai/cujs/cuj-engineering-framework/index.md"
author: "Daniel Herrington"
date: "2026-09-02"
updated: "2026-10-31"
markdown_tokens: 2868
content_signal: "ai-train=yes, search=yes, ai-input=yes"
mcp_endpoint: "https://herrington.ai/mcp"
---
# The CUJ Engineering Framework: Eliminating Speculative Code Through Autonomous Agent Workflows

*A product-driven engineering framework and agentic skill that captures real-world user friction via standardized Mad Libs formulas and autonomously translates them into secure, verified production pull requests.*

---

## The Problem Space

### Context
Modern software engineering has reached unprecedented development velocity through LLMs and AI coding assistants. However, while generating syntax is now near-instant, the bottleneck has violently shifted upstream to **product discovery, user intent capture, and validation**.

Engineering teams oscillate between two failure modes:
1. **The Speculative PRD Trap**: Product managers spend 3–4 weeks drafting 25-page Product Requirement Documents (PRDs) packed with assumptions, edge-case conjecture, and bloated roadmap items that are obsolete before the first sprint concludes.
2. **Ungrounded "Vibe Coding"**: Developers rapidly spin up prototypes based on internal gut feeling or vague feedback, producing technical solutions to problems no real user actually experiences.

### The Core Friction
Traditional telemetry and bug trackers (Sentry, Jira, Datadog) capture **system crashes and HTTP 500s**, but they are fundamentally blind to **user intent blockages**:
- When a user gets frustrated by an awkward 5-step workflow, high token costs, or lack of cross-device sync, no error is logged.
- The user simply abandons the product, hacks together an inefficient spreadsheet workaround, or cancels their subscription.
- Without a structured mechanism to capture user intent, agents and engineers build the wrong features faster.

---

## The Meta Critical User Journey (CUJ)

Applying the CUJ methodology recursively to product engineering itself reveals the core journey required to bridge user pain and software delivery:

### CUJ 1: Autonomous Translation of Friction to Verified Code
* **Statement**: I want to **transform unformatted end-user friction reports into verified production pull requests** while avoiding **speculative PRDs, hallucinated agent scope creep, and prompt injection vulnerabilities** so that **engineering teams ship software that measurably eliminates user pain on day one**.
* **User Scenario**: A user hits an annoying friction point in a web app or media tool (e.g., manually cross-referencing TV season release dates). They report it in 15 seconds using a structured Mad Libs prompt. An autonomous agent ingests the report, audits it against security guardrails, creates a sandboxed git branch, writes the feature, tests it against regression suites, and opens a clean pull request linking back to the user's report.

### CUJ 2: Frictionless Drop-In Intake Across Any Project
* **Statement**: I want to **install drop-in CUJ capture widgets, GitHub Issue templates, and backend route handlers into any software codebase within 60 seconds** while avoiding **framework lock-in or heavy telemetry SDK bloat** so that **my product continuously captures ground-truth user intent**.
* **User Scenario**: A developer initializes a new repository (or adds to an existing service like Plex or an AI search tool). By running a single agent skill (`cuj init`), the repo receives standardized GitHub Issue forms, an in-app `/cuj` feedback widget, and an API handler that funnels customer friction directly into agentic triage.

---

## The Ideal Flow

```mermaid
sequenceDiagram
    autonumber
    actor User as End User
    participant App as Web App / /cuj Widget
    participant API as /api/cuj Endpoint
    participant GH as GitHub Issues (cuj-report)
    participant Agent as CDD Autonomous Agent
    participant Sec as Security Evaluator
    participant Git as Git Repo / Branch

    User->>App: Submits Mad Libs ("I want to [X] while avoiding [Y] so that [Z]")
    App->>API: POST /api/cuj (payload)
    API->>GH: Creates Issue with [cuj-report] label
    Agent->>GH: Ingests open CUJ issue
    Agent->>Sec: Runs Machine Review (Prompt injection & Auth checks)
    alt Security Pass & Feasibility >= 80%
        Agent->>Git: Checkouts branch: cuj/issue-42-feature
        Agent->>Git: Writes code, tests, & verifies locally
        Agent->>GH: Opens Draft Pull Request ("Closes #42")
    else Security Flagged
        Agent->>GH: Labels [cuj:security-flagged] + posts threat audit
    end
```

---

## The CUJ-Driven Development (CDD) Agent Skill

To operationalize this framework across repositories, we formalized **CUJ-Driven Development** into a reusable agent skill ([`.agents/skills/cuj-driven-development/`](https://github.com/danielherrington)).

### The Standardized Intake Formula
Every piece of user friction is reduced to the canonical Mad Libs structure:

> **"I want to [Do X] while avoiding [Friction Y] so that I can [Benefit Z]."**

This prevents feature dictation ("Add a drop-down menu here") and forces the focus onto **Action, Pain, and Desired Outcome**.

### Three Execution Modes

| Execution Mode | Target Use Case | Automation Level | Security & Approval Gate |
| :--- | :--- | :--- | :--- |
| ⚡ **`Turbo Mode`** | Internal tools, rapid hackathons, local scripts | 100% Autonomous | Baseline sandbox isolation; immediate branch & PR generation. |
| 🛡️ **`Machine Review Mode`** | Default production web apps, OSS repos | Multi-Agent Guardrails | Evaluates prompt injection, auth bypass, and privilege escalation. Auto-opens PR if Safety = 100%. |
| 👤 **`Manual Review Mode`** | Regulated industries, fintech, core infrastructure | Human-in-the-Loop | Generates Threat & Architecture spec, comments on GitHub Issue, and pauses for human confirmation. |

---

## Real-World Implementations

We use the CUJ framework across multiple production systems and open-source tools:

1. **[Plex Media Hub Hub](https://github.com/danielherrington/plex-watchlist-availability-checker)**: Installed the `.agents/skills/cuj-driven-development/` skill, `/api/cuj` FastAPI backend, and in-app modal to capture library and watchlist gap friction.
2. **[Local Meeting Scribe](/cujs/local-meeting-scribe/)**: Solved the multi-meeting speaker diarization gap with 256-dimensional acoustic voiceprints, local privacy, and zero API token costs.
3. **[American Airlines Household Loyalty](/cujs/airline-household-loyalty/)**: Addressed the single-earner spend bias in co-branded credit card programs.
4. **[Google Calendar Schedule Helper](/cujs/google-calendar-schedule-helper/)**: Automated zero-latency cross-timezone meeting slot proposal generation.

---

## Try It Live: Submit a CUJ on This Framework

Test our live CUJ intake component directly below. Submissions demonstrate how raw user friction is captured in standardized format:

<div style="background: var(--surface); border: 1px solid var(--border); border-radius: 16px; padding: 28px; margin: 32px 0; box-shadow: 0 8px 24px rgba(0,0,0,0.08);">
    <div style="display: inline-block; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 700; color: var(--accent); background: var(--accent-glow, rgba(37,99,235,0.1)); padding: 4px 10px; border-radius: 99px; margin-bottom: 12px;">Live Interactive Widget</div>
    <h3 style="font-family: var(--font-heading); font-size: 1.35rem; font-weight: 700; margin: 0 0 8px 0; color: var(--text);">How is our CUJ Framework or Site Underserving You?</h3>
    <p style="color: var(--text-muted); font-size: 0.95rem; margin-bottom: 20px;">Share where you experience friction in AI product workflows or this site:</p>

    <form id="liveCujForm" onsubmit="handleLiveCujSubmit(event)" style="display: flex; flex-direction: column; gap: 14px;">
        <div>
            <label style="font-size: 0.85rem; font-weight: 600; color: var(--accent); display: block; margin-bottom: 4px;">1. I want to...</label>
            <input type="text" id="live_action" required placeholder="e.g. export CUJ case studies directly to GitHub Issue templates" style="width: 100%; box-sizing: border-box; background: var(--bg); border: 1px solid var(--border); border-radius: 8px; color: var(--text); padding: 10px 14px; font-size: 0.95rem; outline: none;" />
        </div>
        <div>
            <label style="font-size: 0.85rem; font-weight: 600; color: var(--accent); display: block; margin-bottom: 4px;">2. while avoiding...</label>
            <input type="text" id="live_avoiding" required placeholder="e.g. manually copying and pasting markdown across repos" style="width: 100%; box-sizing: border-box; background: var(--bg); border: 1px solid var(--border); border-radius: 8px; color: var(--text); padding: 10px 14px; font-size: 0.95rem; outline: none;" />
        </div>
        <div>
            <label style="font-size: 0.85rem; font-weight: 600; color: var(--accent); display: block; margin-bottom: 4px;">3. so that I can...</label>
            <input type="text" id="live_outcome" required placeholder="e.g. immediately bootstrap agentic workflows in new projects" style="width: 100%; box-sizing: border-box; background: var(--bg); border: 1px solid var(--border); border-radius: 8px; color: var(--text); padding: 10px 14px; font-size: 0.95rem; outline: none;" />
        </div>
        <button type="submit" id="live_submit_btn" class="btn btn-primary" style="padding: 12px 20px; font-size: 0.95rem; font-weight: 600; border-radius: 8px; border: none; cursor: pointer; align-self: flex-start; margin-top: 6px;">
            Submit Critical User Journey
        </button>
    </form>

    <div id="liveCujSuccess" style="display: none; background: rgba(48,209,88,0.1); border: 1px solid rgba(48,209,88,0.25); border-radius: 12px; padding: 20px; margin-top: 16px; text-align: center;">
        <div style="font-size: 1.8rem; margin-bottom: 6px;">🎉</div>
        <h4 style="color: #30d158; margin: 0 0 6px 0; font-size: 1.15rem;">Journey Captured!</h4>
        <p id="liveCujStatement" style="color: var(--text); font-size: 0.95rem; font-style: italic; margin: 0 0 12px 0;"></p>
        <span style="font-size: 0.85rem; color: var(--text-muted);">This friction report has been structured into our agentic engineering pipeline.</span>
    </div>
</div>

<script>
function handleLiveCujSubmit(e) {
    e.preventDefault();
    const action = document.getElementById('live_action').value.trim();
    const avoiding = document.getElementById('live_avoiding').value.trim();
    const outcome = document.getElementById('live_outcome').value.trim();
    const statement = "I want to " + action + " while avoiding " + avoiding + " so that I can " + outcome + ".";
    
    document.getElementById('liveCujForm').style.display = 'none';
    document.getElementById('liveCujStatement').textContent = '"' + statement + '"';
    document.getElementById('liveCujSuccess').style.display = 'block';
}
</script>
