← the whole session plugin/skills/ux-assignment-reasoning-protocol/SKILL.md
MANDATORY reading before creating any UX assignment. Contains the required reasoning structure that MUST be present in every UX assignment, so a reviewer who never saw the code can validate it in under a minute.
UX Assignment Reasoning Protocol
MANDATORY: Read Before Creating ANY UX Assignment
This document defines the REQUIRED reasoning structure for every UX assignment. An assignment without this reasoning is INCOMPLETE and will require 5-10 minutes of detective work by whoever reviews it to understand.
⛔ MANDATORY GUARD: Disambiguate Any Word That Means More Than One Thing In This Codebase
If a project has grown for a while, an everyday word like "trial," "active," "verified," or "pending" often ends up meaning two or more genuinely different system states — checked by different code, with different consequences. If you write such a word in a UX assignment without saying which one you mean, STOP and fix it. An agent reading the ambiguous word will guess, and guessing means the wrong fix gets applied to the wrong users, silently.
How to find out whether a word in your project is ambiguous: grep it across the codebase — do unrelated functions or checks use it for genuinely different things? If two engineers on the project could picture two different systems when they hear it out loud, it's ambiguous, and every assignment must say which one, every time.
Example (real, not hypothetical — the concrete case that produced this rule). In one real codebase, bare "trial" was ambiguous between two completely different systems:
Type What it is Stripe? Card? Check legacy_trialFree trial from an early beta, user.trial[]arrayNo No isUserOnLegacyTrial()cc_trialStripe subscription status = "trialing" Yes Yes user.subscriptionStatus === 'trialing'oreffectiveSubscriptionStatusUsing just "trial" caused agents to apply the wrong fix to the wrong users, so the rule became: never write bare "trial" — always say which one. The same table-and-ban structure applies to whatever ambiguous word your own project has; the mechanics below use those terms as the worked example.
How to identify which one you mean (worked with the example above):
- Is there a Stripe subscription involved? →
cc_trial - Does the test use
subscription=trialingin the simulator? →cc_trial - Is the user activating a "Start Free Trial" button (no card)? →
legacy_trial - Does the code call
isUserOnTrial()/isUserOnLegacyTrial()? →legacy_trial - Does the code check
user.subscriptionStatus === 'trialing'? →cc_trial
Required replacements:
"a trial user"→ "a cc_trial user (Stripe subscription status=trialing)" OR "a legacy_trial user (free trial, no card)""log in as a trial user"→ "log in as a cc_trial user" with?subscription=trialingsimulator path"trial status"→ "cc_trial status" or "legacy_trial status""trial features"→ "cc_trial access" or "legacy_trial access""the trial"→ "the cc_trial" or "the legacy_trial"
When amending an existing assignment you found with ambiguous "trial":
- Read the simulatorPath — if it has
subscription=trialing→ cc_trial - Read the code mentioned — if
isUserOnLegacyTrial()appears → legacy_trial - Read the commit message context — Stripe/customer ID issues → cc_trial; free trial button/no card → legacy_trial
- Update title, uxStory, steps, and notes to use the specific type
- Add a
notesfield:"cc_trial = Stripe subscription trialing. Distinct from legacy_trial (isUserOnLegacyTrial)."OR"legacy_trial = free trial, no card, user.trial[] array, isUserOnLegacyTrial(). Distinct from cc_trial (Stripe)."
The goal: The reviewer reads the assignment → clicks ONE button → sees the state → validates it in 60 seconds
The Six Required Elements
Every UX assignment MUST contain:
0. Code Existence Verification (GATE) — MANDATORY FIRST STEP
Before ANY other reasoning, verify the code you're testing actually exists.
This prevents "Phantom Code Cascades" where agents create assignments for features that were never implemented.
Verification Commands
| Check | Command | If Missing |
|---|---|---|
| File exists? | ls {file_path} |
STOP - mark assignment as blocked |
| Function exists? | grep -r "function {name}|const {name}" src/ |
STOP - mark assignment as blocked |
| Route exists? | Check App.js or routes file |
STOP - mark assignment as blocked |
Also Check for Known Broken Features
If the project tracks known-broken features somewhere — an admin status page, a feature-flag registry, a KNOWN_ISSUES doc — check it before writing the assignment. Don't invent a UX assignment claiming a feature works when the project itself has already recorded it as broken.
Example. One admin app keeps a page of feature conditions, so the check is literally:
grep -A2 "{feature_name}" web-app/src/admin2/pages/atomicConditions.jsand if the feature is marked
BROKENthere, the assignment must not claim it works. If your project has nothing like this, skip the grep and rely on the code-existence checks above instead.
Gate Rule
If ANY of these are true:
- Referenced file does not exist
- Referenced function does not exist
- The project's own broken-feature tracker (if it has one) marks this feature broken
Then the assignment status MUST be blocked with:
{
"status": "blocked",
"blockedReason": "phantom_code",
"missingImplementation": ["PaymentRoute.js", "getAuthFailureRedirect()"],
"notes": "Cannot test - code referenced in this assignment does not exist yet"
}
DO NOT proceed to the other five elements until this gate passes.
1. The Missing Reasoning (WHY)
What user situation creates this state?
Not "we need to test X" - but "when a user does A, and condition B is true, they will be in state C".
Bad:
"Test that the session expiry modal appears"
Good:
"When a cookied user's session token expires (JWT passed expiration timestamp), and they try to access any authenticated route, they should see a modal prompting re-authentication rather than a white screen or confusing error."
2. The Exact UX Context (WHAT)
What specific combination of states must be true?
List every variable that matters:
| Variable | Required Value | Why |
|---|---|---|
| Is logged in? | Yes, via cookie | Must have existing session to expire |
| Session expired? | Yes, token timestamp < now | The trigger condition |
| User type? | Any paid user | Unpaid users redirect differently |
| Page location? | Any authenticated route | Where the check happens |
3. The Simulation Steps (HOW)
How do we create that exact state for testing?
If the project has an admin simulator or preview tool for exercising UI states, use it at its local URL and reference existing helpers or create new ones. If it doesn't, use whatever UI-testing approach the project actually provides — Playwright, Storybook, a seeded local dev server, a feature-flag toggle — and write out the manual steps to reach the same state.
Example:
1. Go to http://localhost:3000/admin2/user-simulator 2. Select "Authentication State" → "Session Expired" 3. The app is now simulating an expired sessionIf no helper for a state exists yet, some projects use a
create-admin-helpers-atomicskill (not shipped with this plugin) to build one. If you have an equivalent, use it; otherwise write the manual steps by hand and treat that as a one-time cost until someone builds a reusable helper.
4. The Modular Helper Functions (TOOLS)
What atomic helpers (or equivalent test fixtures) are being used or need to be created?
List the specific functions/simulators — or, if the project has none, the manual steps this assignment relies on instead.
Example:
CentralizedUserSimulatorPage→session_expiredoptionModalPreviewPage→session-expired-modalentry- OR: "New helper needed at
/admin2/simulator/X"
5. The One-Click URL (ACCESS)
A single URL that creates the state AND redirects to the page being tested — if the project's admin/preview tool supports one. If it doesn't have URL-driven state, give the shortest sequence of manual steps instead, and say so.
Example. One project's User Simulator supports URL parameters that auto-apply simulations:
http://localhost:3000/admin2/user-simulator?auth=session_expired&redirect=/hub&clear=trueURL Parameter Reference:
Param Values Example authlogged_out,session_expired?auth=logged_outsubscriptionactive,trialing,past_due,unpaid,canceled?subscription=trialingaccessTierFULL_ACCESS,LIMITED_ACCESS,NO_ACCESS?accessTier=LIMITED_ACCESSuserTypenew_user,returning_paid,churned_user?userType=churned_userredirectAny path &redirect=/logincleartrue&clear=true(always include)Always include
clear=trueto reset previous simulations. For modals only:http://localhost:3000/admin2/modal-preview?modal=session-expired
Real Example: Session Expiry Modal
Example (opt-in worked example — replace the URLs, component names, and admin tool with your own project's equivalents). This shows the full Six Required Elements filled out for one real bug on a real stack, including that project's specific simulator URLs and component names, so you can see the shape of a complete assignment end to end.
Here's the complete reasoning for the session expiry example from the problem statement:
1. WHY (The Reasoning)
When a user has an active session (logged in, cookie present) and that session expires (JWT timestamp passed), we first attempt automatic re-authentication using stored credentials. If that fails, we must inform the user they need to log in again. We show a modal rather than redirecting immediately because:
- The user might have unsaved work
- A sudden redirect is jarring UX
- The modal explains what happened (transparency)
2. WHAT (The UX Context)
| Variable | Required Value | Why |
|---|---|---|
| Has cookie? | Yes | Must have existing session |
| Cookie valid? | No (expired) | The trigger |
| Auto-reauth attempted? | Yes, failed | We try silent refresh first |
| User type | Paid user (has account) | Unpaid users go to landing instead |
| Current page | Any authenticated route | Where the guard runs |
3. HOW (Simulation Steps)
1. Go to http://localhost:3000/admin2/user-simulator (web-app)
2. In "Authentication State", click "Session Expired"
3. Simulation activates - notice the orange banner at top
4. Navigate to any authenticated page (e.g., /chat)
5. The SessionExpiredModal should appear
4. TOOLS (Atomic Helpers Used)
- CentralizedUserSimulatorPage - Sets
session_expiredsimulation flag - SessionExpiredModal - The component being tested (at
src/modals/SessionExpiredModal.jsx) - ModalPreviewPage - Can also preview at
?modal=session-expired
5. ACCESS (One-Click URL)
Option A (Full flow with redirect):
http://localhost:3000/admin2/user-simulator?auth=session_expired&redirect=/hub&clear=true
Option B (Modal preview only):
http://localhost:3000/admin2/modal-preview?modal=session-expired
Template for Every UX Assignment
Copy this template and fill it in:
## UX Assignment: [Title]
### 1. WHY This State Exists
When a user [does X], and [condition Y is true], they experience [state Z] because [reason].
If we got this wrong, the user would see [bad outcome] instead.
### 2. UX Context Variables
| Variable | Value | Why |
|----------|-------|-----|
| [var1] | [value] | [reason] |
| [var2] | [value] | [reason] |
### 3. Simulation Steps
1. Go to [URL] (repo)
2. Click [button/action]
3. State is now active
### 4. Atomic Helpers Used
- [HelperName] at [path] - [what it does]
- OR: "BLOCKER: Need new helper for [state]"
### 5. One-Click Access
URL: [direct link that creates the state]
### 6. Expected Result
You should see:
- [Specific visual element]
- [Specific behavior]
If you see [wrong thing], this code is broken.
The Decision Tree
Before creating ANY UX assignment:
STEP 0: DOES THE CODE EXIST? (MANDATORY GATE)
│
├── Run: ls {file_path}
├── Run: grep "{function_name}" src/
├── (if the project has a known-broken tracker) check it for "{feature}"
│
├── FILE/FUNCTION MISSING?
│ └── STOP. Create BLOCKED assignment with blockedReason: "phantom_code"
│
├── MARKED BROKEN in the project's own tracker?
│ └── STOP. Create BLOCKED assignment with blockedReason: "known_broken"
│
└── CODE EXISTS + NOT BROKEN → Continue:
│
Can the reviewer reach this state via URL alone (admin simulator, or none needed)?
├── YES → Write the assignment with that URL
└── NO → Does a reusable test helper/fixture exist?
├── YES → Reference it in your assignment
└── NO → If you have a skill for building one (e.g. `create-admin-helpers-atomic`,
not shipped with this plugin), use it. Otherwise, write the manual
steps to reach the state by hand, and note the missing helper.
Then come back and write the assignment.
Enforcement
Agents MUST follow this protocol. UX assignments that are missing:
- No existence verification → Rejected. Creates phantom code cascade.
- References non-existent code → Must be marked
blockedwithblockedReason: "phantom_code". - No reasoning → Rejected. The reviewer doesn't know what they're testing.
- No UX context → Rejected. The reviewer can't recreate the conditions.
- No one-click access → Rejected. The reviewer would need 5+ minutes of setup.
- No expected result → Rejected. The reviewer doesn't know what "working" looks like.
When reviewing your own work before submitting, ask:
"Could a human who has never seen this code click one link, see the state, and know in 60 seconds if it works?"
If NO, your assignment is incomplete.