| name | optimizexp |
| description | Optimize human-centered experiences (UX, DX, AX) via persona-driven review, Gherkin features, evidence capture, and a dual-regime infinite loop—reduce harms/friction/uncertainty to a floor, then maximize delight (excitement/ease/optimality) under harm non-regression and formal cognitive thresholds until Pareto equilibrium. Personas carry synthetic KYC demographic/psychographic models and cognitive budgets. End-of-run survey turns feedback into ranked experiment backlogs. Default --passes infinite until pareto-equilibrium. Use when the user says optimizexp, optimize experience, experience review, reduce friction, delight metrics, agent experience audit, UX/DX/AX pass, or optimizexp init. |
OptimizeXP
Run multi-objective experience optimization across UX, DX, and AX:
- Regime
harm_reduce: measure and fix harms, friction, uncertainty (lower better) until a harm floor (metrics-zero or irreducible residual with no S/M left).
- Regime
delight_maximize (default next): score excitement, ease-of-use, perceived optimality (higher better) while still measuring harm and cognitive load — reject any experiment that increases harm or breaches persona cognitive thresholds (feature sprawl, clutter, choice overload, …). Continue until Pareto equilibrium (no free lunch on the frontier / inverted-U peak). See references/equilibrium.md.
- Survey + backlog: personas (with formal KYC-lite demographic + psychographic models) answer a pseudo survey → pseudo feature requests → ranked experiment backlog.
Default infinite does not terminate at the harm floor. Only --no-delight / --harm-only opts into that early exit.
Each review pass must apply an experiment (smallest safe change), re-score with evidence — not report-only by default.
Scores are falsifiable, not vibes: evidenceRefs must point at files that exist, optional evidenceChecks rubric entries (exitCode / transcript assertions against captured meta.json) are programmatically enforced, and an iteration scores.json copied from baseline.json fails validation without an explicit justification (see references/metric-scorecard.md).
Uses:
- Global personas/features under repo-root
.optimizexp/ (cross-cutting)
- Project-local personas/features under
<project>/.optimizexp/ (e.g. site/.optimizexp/)
- Schema v2 personas with formal
experiences: [ux, dx, and/or ax] binding, plus segments/demographics/psychographics/cognitive thresholds
- Persona feature folders with Gherkin + evidence
- Write-ahead agent bus + dual-regime loop until pareto-equilibrium (bus/runs stay global)
- Mandatory experiments each pass unless
--report-only
--passes infinite until equilibrium (finite N caps harm cycles only)
- Delight regime after harm floor (
--delight-passes; --no-delight to skip)
- Persona survey + experiment backlog (default on)
- Bus feedback after pass 1; optional PR delivery
First moves
- Bare invocation (no flags): treat as all experiences (
ux + dx + ax) and all projects. First check whether init is needed:
node --import tsx .agents/skills/optimizexp/harness/init.mts --mode needs-init
If needsInit: true, run full init (harness/init.mts, all experiences, all projects), then continue into the review loop with all experiences + all projects. If false, skip init and review immediately. Details: references/init.md § Auto-init on bare run.
- Resolve project flags (default all-projects). List ids:
init.mts --mode list-projects. Resolve experience flags (default ux, dx, ax).
- If
--init only: run repo bootstrap (respect --projects if set); stop unless user also asked to review.
- If
--persona … present: rewrite each seed → formal persona file under the correct scope (references/personas.md): single non-root --project → <project>/.optimizexp/personas/; otherwise global .optimizexp/personas/. Never use the raw seed as the review system prompt.
- Resolve persona set for the run (same set drives feature fan-out) by merging global + selected project scopes (project-local shadows global on same id):
--personas list if set, else
- personas generated this run if any, else
- project
personas.defaultPanel panel list if configured (e.g. Community Web community-competitive), else
- all personas intersecting experiences.
When competitive coverage applies (project
competitive.scorecard or Community Web features), load references/competitive-coverage.md and keep dimension owners in the panel.
- Doctor (preflight): audit structure, personas, feature quality, maps; repair safely; optional snapshot.
invoking OptimizeXP authorizes its safe, in-scope preflight repairs; apply them without asking again. This does not authorize destructive, networked, secret-bearing, or unrelated changes.
See . Doctor exit 0 ≠ optimizexp complete.
Flags
Full grammar: references/flags.md.
| Form | Meaning |
|---|
| (none) | Auto needs-init → init if needed → review all experiences + all projects |
--init | Bootstrap only (unless user also requested review): product personas + features |
--projects all / --all-projects | Evaluate every discovered project (default when omitted) |
--project <id> / --projects a,b | Limit init/review to named projects (list-projects for ids) |
--ux / --dx / --ax | Include only the listed experiences |
--only ux,dx | Include only listed |
--exclude ax / --no-ax | Drop listed from the default set |
bare ux dx after skill name | Same as --only |
--persona "seed" | Seed → formal personas/<id>.md |
--personas id1,id2 | Select existing persona ids (exclusive when set) |
--max-personas N | Cap persona count |
--feature "seed" | Journey seed → feature folder + per-persona .feature files |
--feature-id / --feature-file / --driver | Feature id, seed file, capture driver |
--features id1,id2 | Select existing feature folders for the run |
--passes infinite / passes: infinite | Default. Continue harm → delight until . |
Feature × persona: no persona flags → generate Gherkin for all personas in the resolved set. With --personas / --persona → only those. Echo generatedPersonas + generatedFeatures before reviewing.
Stop policy: harm true plateau only switches to delight. Default infinite ends at pareto-equilibrium (or inverted-U peak / delight ceiling / caps / user / safety / blocked). Survey + backlog by default. No --iterations budget.
Progressive disclosure
Use the reference index to route to the minimum context needed.
Always
references/init.md — --init and bare auto needs-init
references/metrics.md — harm metrics + HCD
references/positive-metrics.md — delight metrics
references/cognitive-thresholds.md — load channels + thresholds
references/equilibrium.md — Pareto / inverted-U stop policy
references/persona-models.md — KYC demographic/psychographic models
references/persona-survey.md — survey + feature requests
references/competitive-coverage.md — competitor gap scorecards, panels, currency (when product has a scorecard)
references/experiment-backlog.md — ranked uplift backlog
references/metric-scorecard.md — formal scores (+ positive, cognitive)
references/agent-bus.md — write-ahead bus
references/review-loop.md — dual-regime orchestration
references/personas.md — persona file contract
references/config.md — global + project config.json
references/features.md — feature folder + Gherkin layout
references/feature-quality.md — critical path: catalog, rubber-duck, adversarial, quality bar
references/app-exploration.md — surface-map probes feeding the catalog
references/doctor.md — doctor check / repair / snapshot preflight
references/evidence.md — capture policy, overwrite, media preference
references/interface-patterns.md — formal API, TUI, and web/mobile/desktop GUI standards + evidence forms
references/harness.md — test harness CLI + drivers
references/workflow-generation.md — host workflows
references/pr-delivery.md — commits, stacked PRs, post evidence to PR
Experience branches (if selected)
| Exp | Load |
|---|
| UX | references/ux/design-systems.md, references/ux/design-md.md |
| DX | references/dx/*.md (build, lint, test, tools, hierarchy, cache, git-hooks) |
| AX | Start at references/ax/index.md, then only needed sections: specs, mcp, agent-skills, harness-clis, model-routing, token-optimization, agents-md, agents-config, hooks-plugins, auth |
Workflows
Hard rules
-
Completion contract (non-negotiable). It is illegal to tell the user optimizexp is done unless:
node --import tsx .agents/skills/optimizexp/workflows/cross-agent/review-loop.mts \
--mode assert-complete --run <runId>
Paste that JSON in the final report. These are NOT completion:
| False complete signal | Reality |
|---|
| Package / unit tests green | Product experiment only |
| Feature wired / bindings pass | Scaffold + implement step |
| One evidence capture | Single act, not dual regime |
Harm should-stop plateau (cycleStop) | Regime switch only |
| Todo list emptied / compaction “done” | Process bookkeeping |
implementationStatus: wired | Feature metadata |
| Verb inventory only (chat/default entry untested) | Missing P0 experience / surface-map |
Handwritten primary.txt without capture stamp | Not harness evidence |
| Template Gherkin (“exercise the surface”) | Failed feature-quality bar |
Open the run before product edits (--mode init). Resume incomplete runs (status: running + INCOMPLETE.md) — never invent a parallel “done” narrative.
-
Apply experiments by default. Each persona review pass must pick the top leveraged finding and land the smallest safe change that can lower friction/uncertainty/harms, then re-capture evidence and re-score. Report-only only with --report-only / --no-reduce (or OPTIMIZEXP_REPORT_ONLY=1). Never game scores without changing the experience.
-
Derive → implement → continue. If you can name a concrete reduction (file, message, preflight, offline path, install, docs, harness), you must apply it in this run (or the current pass) — not park it under “residual / next owners / blocked by env.” Knowing the fix is not a stopping condition; leaving known fixes unapplied is a skill violation. Product implement is always a , never skill completion.
Repo layout (canonical)
Global (repo root) — cross-cutting personas/features and all orchestration state:
.optimizexp/ # GLOBAL scope
config.json # formal monorepo defaults (optional)
.gitignore # managed ignores (runs, bus entries, large media)
personas/*.md # cross-project / monorepo personas
features/<feature-slug>/
feature.json # may set "scope": "global"
*.feature
steps/
evidence/<scenario-slug>/
bus/entries/ # write-ahead bus (global only; entries gitignored)
runs/<run-id>/ # run artifacts (global only; gitignored)
survey/
backlog.json
backlog/experiments.json
init-report.json
cucumber.yaml
Project-local — product-specific personas/features + project config:
site/.optimizexp/ # PROJECT scope (example)
config.json # formal project defaults (optional)
.gitignore # managed (evidence media by default)
personas/*.md
features/<feature-slug>/
feature.json # "scope": "site", "projects": ["site"]
*.feature
evidence/…
packages/cli/.optimizexp/
config.json
.gitignore
personas/
features/
| Content | Global .optimizexp/ | <project>/.optimizexp/ |
|---|
| config.json | Monorepo defaults, safety, prefer lists, gitignore policy | Project surfaces, default experiences/driver, gitignore |
| .gitignore | runs/, bus entries, large evidence media | large evidence media |
| Personas / features / small evidence | Cross-cutting (usually committed) | Project-specific |
| bus / runs / backlog / init-report | Yes (only here) | No |
Root project (--project root) | Uses global | — |
Config merge: skill builtins → global config → project config (single-project focus) → CLI flags win. See references/config.md (includes gitignore categories + extra / negate).
Resolution: reviews merge global + selected project scopes. Same persona/feature id: project-local shadows global when that project is in scope.
Harness (auto-implemented)
node --import tsx .agents/skills/optimizexp/harness/doctor.mts check --project code
node --import tsx .agents/skills/optimizexp/harness/doctor.mts repair --project code
node --import tsx .agents/skills/optimizexp/harness/doctor.mts snapshot --project code --json
node --import tsx .agents/skills/optimizexp/harness/init.mts --mode needs-init
node --import tsx .agents/skills/optimizexp/harness/init.mts --mode list-projects
node --import tsx .agents/skills/optimizexp/harness/init.mts --mode ensure-config
node --import tsx .agents/skills/optimizexp/harness/init.mts --mode validate-config
node --import tsx .agents/skills/optimizexp/harness/init.mts
node --import tsx .agents/skills/optimizexp/harness/init.mts --projects site,cli
node --import tsx .agents/skills/optimizexp/harness/init.mts --dry-run
node --import tsx .agents/skills/optimizexp/harness/explore-app.mts --project code
node --import tsx .agents/skills/optimizexp/harness/generate-persona.mts \
--seed "A junior frontend engineer who panics at monorepo gates" --id junior-frontend
node --import tsx .agents/skills/optimizexp/harness/generate-feature.mts \
--seed "Staged agent check is narrow and actionable" --id agent-check-staged \
--experiences dx --personas developer,coding-agent
node --import tsx .agents/skills/optimizexp/harness/generate-feature.mts --mode implement --id agent-check-staged
node --import tsx .agents/skills/optimizexp/harness/generate-feature.mts --mode validate --id agent-check-staged
pnpm run test:file .optimizexp/features/agent-check-staged/test/agent-check-staged.bindings.test.ts
node --import tsx .agents/skills/optimizexp/harness/capture-evidence.mts --mode capture \
--feature <id> --scenario <title-or-slug> --driver cli|tui|web|native --command '…'
node --import tsx .agents/skills/optimizexp/harness/post-pr-evidence.mts --feature <id> [--pr N]
node --import tsx .agents/skills/optimizexp/harness/survey.mts --mode template --run <runId>
node --import tsx .agents/skills/optimizexp/harness/survey.mts --mode aggregate --run <runId>
node --import tsx .agents/skills/optimizexp/harness/survey.mts --mode rank-backlog --run <runId> --global
Drivers: cli (replayable primary.cast + generated REPLAY.html + transcript), tui (asciinema cast when present, otherwise the same local cast), web (Playwright/browser MCP video), native (computer-use via OPTIMIZEXP_NATIVE_CAPTURE).
Phases
Orchestration
- Scope — flags, personas (prefer v2 models), features; init run (
status: running)
- harm_reduce to floor (true plateau on harm + implementableHarm=0) — cycleStop only
- Switch to delight_maximize (unless
--no-delight): survey → backlog → Pareto-admissible uplifts; return to harm if regression
- Candidate stop via
--mode equilibrium (stop: true) — still not complete
- assert-complete → summary.md → mark-complete (
status: complete)
- PR / user report — paste assert-complete JSON; harm floor, delight, cognitive, stopReason, top backlog
Persona scenario reviews (one cycle → true plateau)
For reviewIteration = 1, 2, … until plateau (each iteration = review and reduce experiment):
- Read bus if
reviewIteration > 1 (or always when correcting)
- Expect → Act + capture → Outcome (scorecards + comparison; optional
scores.positive in Phase 2)
- Rescore — write
iterations/<nnn>/scores.json + findings.md (every finding must include Smallest reduction that is implementable now or explicitly external-blocked with why)
- Reduce (default on) — implement the top finding’s reduction (and any other independent S-effort fixes in the same iteration when cheap). Do not only document.
- Verify — expect → act + capture → outcome on changed surface(s)
- should-stop — true plateau only (flat scores and implementableFindingsRemaining=0). Flat scores + open S/M backlog ⇒ continue.
- Incremental commit when on a delivery branch
After harm floor: delight_maximize until equilibrium (default). --no-delight → stop at floor (harm-only-floor).
Deliverables
.optimizexp/runs/<run-id>/scope.json # status running→complete; stopPolicy; regime
.optimizexp/runs/<run-id>/INCOMPLETE.md # present while open; removed on mark-complete
.optimizexp/runs/<run-id>/COMPLETE.md # after mark-complete
.optimizexp/runs/<run-id>/baseline.json|iterations/|summary.md
.optimizexp/runs/<run-id>/survey/|backlog.json|positive-scores.json
.optimizexp/runs/<run-id>/competitive-scorecard.json # when competitive coverage applies
.optimizexp/competitive/*-dimensions.json # living dimension statuses
.optimizexp/backlog/experiments.json
.optimizexp/bus/entries/*-expect.json|*-outcome.json|*-survey.json
.optimizexp/features/<feature>/evidence/<scenario>/{manifest,meta,primary.*}
# closeout proof (required in agent final message):
# review-loop.mts --mode assert-complete --run <id> → ok:true
Invocation examples
/optimizexp # infinite → pareto-equilibrium (harm then delight)
/optimizexp --init # bootstrap only (all projects)
/optimizexp --dx # dual regime until equilibrium
/optimizexp --ax --passes 3 # cap harm cycles; still delight after
/optimizexp --dx --report-only # measure only
/optimizexp --dx --no-delight # stop at harm floor (opt-out)
/optimizexp --ax --no-survey # skip survey (not default)