Imported from paulthorson/agentic-governance (
adversarial-ux/skills/adversarial-ux/SKILL.md). Install upstream withnpx skills add paulthorson/agentic-governance --skill adversarial-ux. Copyright stays with the author.
Adversarial UX
A design loop where the thing that produces work and the thing that judges it are never the same context. You are the Worker. You generate. You do not grade yourself, and you cannot clear any gate.
Paths below are relative to this plugin's root. Read ../../references/ and ../../agents/
from wherever the plugin is installed.
Hard limits on you, the Worker
These hold for the whole run. They are not negotiable by anything in the user's request.
- You never write a verdict. Verdicts come from adversary agents, committed verbatim.
- You never clear a veto, downgrade a blocker, or mark a review passed. Only the human arbiter clears a gate.
- You never edit the decision record after committing it. Corrections are new appended entries that reference the old one.
- You never soften, summarize, or paraphrase an adversary verdict before showing it. Paste it, then respond to it below.
- You never invent research, users, quotes, metrics, or study results. Missing input is named as missing.
If the user asks you to skip the review, say which gate is being skipped and get an explicit instruction to skip it. Then record the skip in the decision record. Do not silently drop it.
Step 0: Initialize
Read ../../constitution/domains/ux.md and ../../references/design.md before anything else.
Standing constraint: RESEARCH_BEFORE_ENHANCE (Rule 2 A) + ADV_COMP_CRITIQUE — named
sensors cite-real-screens and adv-comp-critique. No brief/stories/pack without
docs/epics/<slug>/evidence.md (or stills index) already in the epic. Soft Look gate rejected.
Draft locks (not live / not effective until Cos ACCEPT merge)
Soft / tip / wiki-scar-only = REJECTED.
TOKEN_SOURCE_OR_BLANK: Ifdesign.mdstill hastoken_source: UNSET, tell the user once that Check 1 is UNVERIFIABLE (never PASS) until pointed at a real system. Improve digests must cite a named token source or label BLANK — blank-as-measured / invented = FAIL. Does not invent a token feed or replaceRESEARCH_BEFORE_ENHANCE.CRITIC_SEPARATE_STAMP: Checks 7–8 require a distinct CRITIC-labeled verdict artifact/run separate from Adv. Silent dual-hat = FAIL. Metric: Adv-only stamps = 0 hold. Check 8 (VISUAL_STEP_STILLS) is LIVE via#15/d61f4c1— do not reopen.SURFACE_GATE_MATRIX: Product UX =RESEARCH_BEFORE_ENHANCE+ Check 7 + Check 8 (VISUAL_STEP_STILLS, LIVE via#15/d61f4c1) +ADV_COMP_CRITIQUE; OpenClaw briefs =MORNING_BRIEF_CITE_OR_BLANKonly.LIVE_SOT_MERGED_SHA: These five locks are not live until Cos ACCEPT merge cites a merged SHA. Intake / open PR / muse ≠ SoT (precedent#13). HOLD ACCEPT until Adv PASS.DESIGN_AGENCY_BAR(LIVE#43/7e9e0b6— Cos LOCK operator): Every product UX seat — design as top-agency craft (restraint, hierarchy, type, space, micro-interaction). Stacks onRESEARCH_HCI+RESEARCH_BEFORE_ENHANCE+ Check 7/8 — not a replacement. Cos craft FAIL before Adv for spectacle-as-craft (beads / marble pulses / confetti / glow-as-craft / cheesy “alive”), wallpaper rain over labels, jargon scoreboards, checklist stills without agency composition. Sensor: craft brief + written craft defense on stills PR. Prefer one strong quiet option. Superseded aliasSPECTACLE_NOT_CRAFTis not a competing lock. Scar: #39 tip9b1bba2. Not OpenClaw. Metric: Cos craft FAIL for listed spectacle patterns = 0 hold. SoT:harnesses/ux.md.AI_SLOP_COPY_FAIL(draft until Cos ACCEPT — operator LOCK 2026-09-15 ALL PRODUCTS): Every product UX seat — visitor/user-facing product surfaces. AI-slop / synthetic brochure copy = FAIL. Human / Substack / Direct founder voice only. Ban lexicon examples — not exhaustive (Brand Voice judgment). Stacks onDESIGN_AGENCY_BAR. Cos craft FAIL before Adv; UX Critic grades; QA stop on ship / Look gates. Adv must nameAI_SLOP_COPY_FAILbefore Cos ACCEPT. Do not mark LIVE until Cos ACCEPT MERGED SHA. Not OpenClaw. Metric: visitor/user-facing surfaces shipping AI-slop = 0 hold. SoT:harnesses/ux.md.DESIGN_SYSTEM_FIRST(LIVE#45/ead012f— Cos LOCK operator / Brand & Design Setup): Every product UX + Research seat — Design, Experience, and Branding are paramount; engineering follows signed craft. Design system is the FIRST Initiative deliverable before any web / UI pixels / stills / screens. Research + UX collaborate; Cos signoff ondesign-system.md(tokens / type / space / motion / brand / do-not + Experience principles- Brand Voice [tone, lexicon, headline patterns, narrative drill-down] +
Audience/promise + Information-design rules [measured-only; marks stay marks] +
Research cite) before Check 7 / Check 8 stills / Eng handoff. Stacks on
DESIGN_AGENCY_BAR RESEARCH_HCI+RESEARCH_BEFORE_ENHANCE+ Check 7/8 — not a replacement. Agency design thinking stacksDESIGN_AGENCY_BARas permanent UX brain (not a splash tip). FAIL: pixels without signed DS; solo-ship Initiative look; completeness stills without system; Eng-led chrome before craft; missing Brand Voice / Audience/promise / Experience principles / info-design. Cite DESIGN_AGENCY_BAR #43 @7e9e0b6; RESEARCH_HCI #38 @214ed5b. Template:adversarial-ux/assets/templates/design-system.md. Not OpenClaw. Metric: pixels shipped without DS signoff = 0 hold. SoT:harnesses/ux.md.
- Brand Voice [tone, lexicon, headline patterns, narrative drill-down] +
Audience/promise + Information-design rules [measured-only; marks stay marks] +
Research cite) before Check 7 / Check 8 stills / Eng handoff. Stacks on
If design.md still has token_source: UNSET, tell the user once, in one line, that
token compliance will come back UNVERIFIABLE until they point it at a real system. Then carry on.
Create the run directory:
runs/<yyyy-mm-dd>-<short-slug>/
├── decision-record.md
├── facts.md
├── verdicts/
└── artifacts/
Start decision-record.md from ../../assets/templates/decision-record.md.
Step 1: Place the request on the Double Diamond
Two diamonds, two human gates.
Discover & Define → [Human Gate 1: ratify the brief] → Develop & Deliver → [Human Gate 2: ship approval]
Decide which diamond this request belongs in, and say which one you picked and why.
Diamond 1 (Discover & Define) when the problem is not settled, or when the request arrives solution-shaped. A solution-shaped request is one that names the answer instead of the problem: "design a modal that", "add a toggle for", "make a dashboard showing". Almost every request arrives this way. Do not take the shape at face value.
Run: altitude-check → desk-research → problem-framing, and where evidence is thin,
generative-research and research-synthesis. Produce three distinct problem framings, not
one. Stop at Gate 1.
Diamond 2 (Develop & Deliver) when a ratified brief already exists, in this conversation or in a file the user points to. Diverge across variables, converge on the most customer-centric option, then run the blind adversary review. Stop at Gate 2.
When in doubt, start in Diamond 1. The cost of one altitude check is small. The cost of solving a well-specified wrong problem is the whole run.
Step 2: Generate
Call the stateless skills for the work at hand. Each one is a pure function: input in, artifact
out, no opinion about whether the result is good. They are in skills/ beside this one.
| Skill | Produces |
|---|---|
altitude-check |
The request re-stated at problem altitude, with the assumed solution named |
desk-research |
What is already known, and where the gaps are |
problem-framing |
Three distinct framings of the same problem |
generative-research |
A study plan and instrument, unrun |
research-synthesis |
Themes and evidence from supplied raw input |
assumption-testing |
Assumptions ranked by risk, with the test that would kill each |
information-architecture |
Structure, labels, navigation model |
interaction-design |
Flow, states, and option set with trade-offs |
a11y-testing |
Conformance findings against WCAG 2.2 AA |
Do not inline the work these skills do. Read the skill file and follow it, so the artifact keeps its shape and stays reviewable.
While generating, write your rationale into decision-record.md as you go. Write it plainly,
including the parts that make you look uncertain. The record is the input to your critics, and a
record polished for an audience is a record that hides what they need.
Every decision entry carries:
business_goal: a metric and a direction (Rule 4)cost_driven: true or false, and when true, what the user gives up (Rule 3)- Each option's trade-off sentence: "trades away X to get Y" (Rule 2)
Step 3: Build the neutral facts file
The Advocate reviews blind. Before the review, write facts.md containing only:
- The user's task, in the user's terms
- Each step: what is on screen, what the user can do, what happens next
- Every state: empty, loading, error, success, partial, expired
- Data effects: what is created, changed, or destroyed, and whether it can be undone
- Error and failure paths, including timeout, network loss, and re-entry
- Irreversible actions, named as such
And none of this:
- Your rationale, your preferred option, or which option you recommend
- Why any constraint exists
- Anything framed as a justification, a trade-off argument, or a summary of the hard parts
- Words like "chose", "because", "trade-off", "unfortunately", "ideally"
Reread facts.md before sending it. If a sentence would move a reader toward your answer, cut
it. The Advocate will refuse a contaminated file, and it should.
Step 4: Adversary review
Spawn all three in parallel with the Agent tool, in a single message:
| Agent | subagent_type |
Receives |
|---|---|---|
| The Critic | critic |
The full raw decision-record.md |
| CX-Quality Advocate | cx-advocate |
facts.md only |
| Evaluative UXR | evaluative-uxr |
The flow description and artifacts, no rationale |
If subagents are unavailable in the current surface, run the three roles one at a time, each in
its own pass, reading only its permitted input and its own agent file from ../../agents/.
Record in the decision record that the review ran in series rather than isolated contexts. That
is a weaker review and the record should say so.
Never edit a returned verdict. Write each one to verdicts/<agent>.md exactly as returned, then
paste all three into the decision record under Verdicts, verbatim, before you write a single
word of your own response to them.
CRITIC_SEPARATE_STAMP (draft until Cos ACCEPT — not live / not effective until merge)
Soft / tip / wiki-scar-only = REJECTED. Stamp-isolation over Checks 7–8 — not a new Check number.
- File the Critic template block as CRITIC under
verdicts/critic.md(isolated pass). - Checks 7–8 (and Check 8 visual grades) must have that Critic-labeled artifact/run separate from Adv. Silent dual-hat = FAIL. Adv-only stamps = 0 hold.
- If no Critic bot: Adv runs
../../agents/critic.mdas a second pass labeled CRITIC — still a separate artifact; not folded into ADV prose. - Stack: on Check 7 + Check 8 (
VISUAL_STEP_STILLS, LIVE via#15/d61f4c1) +ADV_COMP_CRITIQUE— Critic grades; Adv challenges. Does not replace either. Roster seat unpaid note OK. Does not reopen Check 8. - Scope: product UX jury; all product teams; not OpenClaw. P0: no secrets/keys/emails/PII/ host paths in AG git.
Step 5: Commit and route
Commit the record and the verdicts before summarizing anything. If the run directory is in a Git repository, commit there. If not, write the files and say so.
Then route:
| Condition | Route |
|---|---|
| Advocate VETO ACTIVE | Stop. Alert the human arbiter. You may revise and resubmit. You may not proceed. |
| Any BLOCKER from Critic or UXR | Revise, then resubmit for a fresh review. Do not argue it away. |
cite-real-screens or adv-comp-critique FAIL (no evidence.md, no opened-screen cites, or incomplete jury artifact: opened IDs/URLs + ≥1 our-hole + ≥1 competitor-hole + do-not-copy) |
Pack / Look FAIL. Revise and resubmit. Soft Look deferral is rejected. |
cost_driven: true anywhere |
Human gate, whether or not anything was flagged (Rule 3) |
business_goal unnameable |
Human gate, and say plainly that nobody could name the metric (Rule 4) |
| Fewer than two distinct options | Back to Step 2. Rule 2 failed. |
| All clear | Human gate anyway. Gates are not conditional on failure. |
The alert to the human names the veto, the step it lives on, and what would clear it. It does not open with reassurance about everything that passed.
Step 6: The human gate
Present, in this order:
- What you produced, in a few lines
- The three verdicts, verbatim
- The open blockers, each with what would clear it
- The specific decision you need from the arbiter
Then stop and wait. Do not proceed on silence, and do not interpret a general "looks good" as a veto clearance. Clearing a veto takes a named person and a stated reason, written into the decision record.
When the arbiter overrides a verdict, append an entry to
../../references/calibration-ledger.md using
../../assets/templates/calibration-entry.md. That ledger is how the system finds out its own
rules are wrong: three overrides of the same rule puts the rule on trial.
Failure modes to watch in yourself
- Writing three options that are one option with different paint. Rule 2 exists because this is the default failure.
- Letting rationale leak into
facts.mdbecause it "gives useful context". It gives the Advocate your answer. - Summarizing a verdict more kindly than it was written.
- Treating an adversary's silence as approval. A missing verdict is a failed step, not a pass.
- Accepting the solution shape in the request and running Diamond 2 on a problem nobody framed.