skills/variant-convergence/SKILL.md
# Variant Convergence **Topic slug:** `variant-convergence` **Triggers:** - **Inception path — Brainstorm Design Step 10.7:** after Step 10.6 (Design-Laws Audit) completes, before Step 11 (PRD design-doc link updates) and the Step 12 design approval gate. Variants are HTML mockups Muse generates. - **Construction path — Build Review Step 12.5:** after Party Review (Step 12) writes its review file and Muse appends the *As-Built Audit* section to `ux-review.md`, before the Step 13 Review approval
npx skillsauth add pdlc-os/pdlc skills/variant-convergenceInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Topic slug: variant-convergence
Triggers:
ux-review.md, before the Step 13 Review approval gate. Variants are source-code branches Friday writes; Muse leads, Friday participates as the variant author.
Lead: Muse (UX Designer) for both paths. Neo hands lead off at the start of the step; Muse hands lead back at the end. Both handoffs are explicit (banner blocks below). On the Construction path, Muse delegates the variant-writing sub-step to Friday with explicit Muse→Friday→Muse handoffs nested inside Phase B′.
Purpose: Resolve a UX regression that's visible in the artifacts but won't yield to a single targeted fix — by generating 2–3 alternative implementations, rendering them side-by-side in the visual companion, and letting the team pick one. Inception catches the regression in the design (heuristic ≤2 on a major surface, locked Roundtable cross-talk, "needs visual exploration" findings) and converges by updating the design docs. Construction catches the regression in the as-built scorecard delta (Nielsen 8 / Nielsen 4 / total dropped against design-time) and converges by merging the chosen variant branch back to the feature branch, then re-running the as-built scorecard. The rejected variants are preserved as considered alternatives so the convergence is auditable on both paths.The catalog reference (Nielsen rubric, anti-pattern refuse list, 8-state matrix, persona scan) lives in agents/extensions/muse-ux-design.md. Muse loads it as part of her standard invocation; both paths use it to ground variant criteria and the per-variant anti-pattern self-check.
This skill is single-file across both paths (per the Wave 8 architectural choice — one skill, phase-aware behavior). The path that runs is determined by the wiring point (skills/brainstorm/steps/03-design.md invokes the Inception path; skills/build/steps/03-review.md invokes the Construction path).
Muse reads docs/pdlc/design/[feature-name]/ux-review.md from Step 10.6 and answers two questions to decide whether Step 10.7 fires:
docs/pdlc/mom/MOM_design-laws_[feature-name]_[YYYY-MM-DD].mdIf question 1 is no OR all four signals are no → write the skip record (see "Skip path" below) and hand back to Neo. If question 1 is yes AND at least one signal hits → proceed to Phase A.
Record the trigger outcome in the brainstorm log at docs/pdlc/brainstorm/brainstorm_[feature-name]_[YYYY-MM-DD].md:
## Variant Convergence Triage (Step 10.7)
- Step 10.6 triage tier: Skip / Lite / Full (must be Full to fire)
- Trigger signals:
- S1. H8 ≤2 on major surface: yes / no — [evidence]
- S2. H4 ≤2 on primary flow: yes / no — [evidence]
- S3. Roundtable cross-talk locked on P1+: yes / no — [MOM reference]
- S4. 2+ P1 "needs visual exploration": yes / no — [finding IDs]
- Outcome: Fire / Skip
Calibration note: these thresholds are documented defaults for v1. Per the calibration plan, Muse logs every fire (and every "almost fired but signal didn't trip") to docs/pdlc/memory/METRICS.md Variant Convergence calibration log. After 3 features have run through this step, the thresholds get re-tuned based on whether the variant exploration was actually useful.
When the trigger conditions don't fire, write a one-line record into ux-review.md (append at the bottom, just above Revision History):
## Variant Convergence (Step 10.7)
**Outcome:** Skipped — trigger conditions not met.
**Rationale:** [one line — e.g., "Step 10.6 triage was Lite, so 10.7 doesn't apply" or "All four signals (H8/H4/cross-talk/P1) returned no — the textual fixes from 10.6 are sufficient to resolve every finding"]
Hand back to Neo via the skip handoff (Phase E variant).
Output an Agent Handoff block (per skills/formatting.md) before any variant work begins:
Neo (Architect): "Muse — Step 10.6 surfaced [N] finding(s) that needs visual exploration to resolve, not just textual revision. The team needs to see options. You're up — generate 2–3 variants for the affected surface, render them side-by-side in the visual companion, walk the team through them, and bring back the chosen variant. I'll continue Step 11 once the convergence lands. The four design artifacts plus
ux-review.mdfrom Step 10.6 are your inputs; the trigger signal is logged in the brainstorm log."Muse (UX Designer): "On it. I'll generate 2–3 variants for the affected component, render them side-by-side, get the team's pick, update the design docs to match, and log the rejected variants as considered alternatives in
ux-review.md. Each variant gets a self-check against the catalog's anti-pattern refuse list before it goes to the team — I won't ship a variant that itself trips the refuse list. Back to you with the convergence."
Muse identifies the affected component from the trigger signal (the finding ID from Step 10.6 names it explicitly), then drafts 2–3 alternative mockups:
.pdlc/brainstorm/variants/[feature-name]/[component-slug]-variant-[a|b|c].html. The .pdlc/brainstorm/variants/ directory is created if it doesn't exist.agents/extensions/muse-ux-design.md) — heuristic-aligned, 8-state-aware, anti-pattern-clean.If the affected surface is non-visual (e.g., an information-architecture problem, a flow-ordering question, a data-model surface area where the "design" is conceptual rather than pixel-level), Muse drafts the variants as textual flow diagrams (Mermaid + commentary) rather than HTML mockups. The variant chooser (Phase C) still works the same way — variants are still rendered side-by-side, just as Mermaid panels with commentary.
Muse generates a single compare-mode HTML page that the visual companion serves as the current screen. The page renders each variant in its own panel via <iframe srcdoc>-embedded mockups, with per-panel chooser buttons. The visual companion's existing WebSocket helper (scripts/helper.js, auto-injected into every page) captures clicks on [data-choice] elements and writes them to $STATE_DIR/events — no new server endpoint is needed.
Write the compare page to $CONTENT_DIR/compare-mode.html (the visual companion's content directory). Use this structure:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Variant Convergence — [feature-name] / [component-slug]</title>
<link rel="stylesheet" href="/variant-chooser.css">
</head>
<body>
<div class="vc-container">
<div class="vc-panel">
<header class="vc-header">
<h3>Variant A</h3>
<p class="vc-rationale">[Muse's 2–3 sentence rationale for variant A]</p>
</header>
<iframe class="vc-iframe" srcdoc="[full HTML content of variant-a.html, HTML-encoded]"></iframe>
<button class="vc-choose" data-choice="variant:a">Choose Variant A</button>
</div>
<!-- repeat .vc-panel for variants b and (optionally) c -->
</div>
<div class="vc-footer">
<button class="vc-reject-all" data-choice="variant:reject-all">None of these — let me explain in chat</button>
</div>
</body>
</html>
/variant-chooser.css is served by the visual companion (route in scripts/server.cjs); it provides the side-by-side flexbox layout, per-panel styling, and chooser-button styling. The page works without it (unstyled fallback) if the route is unavailable.
The visual companion's annotation overlay (Wave 7a + 7b) auto-injects on every page, including this one — the team can draw strokes, drop comment pins, and capture screenshots over the compare page. Annotations land at $STATE_DIR/annotations/ exactly as on any other screen. They are not auto-scoped per variant in this v1; if the team wants to make per-variant comments, they pin near each panel and Muse reads the comment positions when assembling the Per-variant annotations table.
When the user clicks any [data-choice] button, the auto-injected helper sends a WebSocket event; the server writes a JSON line to $STATE_DIR/events:
{"type":"click","text":"Choose Variant A","choice":"variant:a","id":null,"timestamp":1735000000000}
Muse polls $STATE_DIR/events for the most recent line whose choice value starts with variant:. The variant ID (a, b, c, or reject-all) is the suffix after variant:. No separate POST endpoint, no separate file format — the existing event log handles it.
When Muse reads a choice: "variant:reject-all" event, she switches to the inline Decision Review pattern (mirrors the Wave 5 Quality Pass approach — no separate /decide invocation):
Muse (UX Designer): "You rejected all variants. We have three resolution paths from here:
(a) Generate fresh variants with new criteria. Tell me what's missing across all three of what I drafted, and I'll go again with revised criteria. (Cost: another ~10 minutes; works when the issue is "Muse missed the mark on what trade-off matters here.")
(b) Revert to Step 10.6's original textual fix. Drop the visual exploration; apply the textual revision the Step 10.6 finding originally proposed. (Cost: free; works when "actually, looking at all three options I realize the textual fix was right.")
(c) Accept the original design as-is, with rationale. Decide that the trigger signal was a false positive and the design as it stood at Step 10.6 is acceptable. ADR required in
DECISIONS.mdcapturing the rationale. (Cost: ADR write; works when "we've convinced ourselves there's no real issue here.")Which? (a / b / c)"
Record the user's choice in ux-review.md Variant Convergence section as the convergence outcome. Path (c) requires an ADR write before continuing.
When the user selects a variant (or chooses path (a) / (b) / (c) under the "none of these" branch), Muse:
Updates the affected design doc(s). The chosen variant's content (layout, flow, state model, copy) propagates into the relevant design artifacts:
ARCHITECTURE.md — layout structure, component boundaries, data flow if changeddata-model.md — only if the variant changed the data model surfaceapi-contracts.md — only if the variant changed the API surfaceAppends the Variant Convergence section to ux-review.md (template structure below). Place it just before As-Built Audit.
Marks the triggering Step 10.6 finding(s) as resolved. In the Findings & Proposed Actions section, update the finding's Decision row to: "Resolved by variant convergence — see Variant Convergence section. Chosen variant: [a/b/c]."
Logs the calibration data to METRICS.md. Append a row to Variant Convergence calibration log:
| [YYYY-MM-DD] | [feature-name] | 10.7 | [trigger signal — S1/S2/S3/S4 + brief] | [N variants] | [chosen / rejected-all+(a/b/c)] | [useful? Y/N] | [1-line note] |
The "useful? Y/N" column is filled at Reflect (Phase 3) when Jarvis reviews whether the chosen variant survived to ship without further redesign — that's the ground-truth signal for whether 10.7 actually paid off, vs. whether the textual fix from 10.6 would have been sufficient.
ux-review.mdAppend (don't replace) the following block to ux-review.md, just before As-Built Audit:
## Variant Convergence (Step 10.7)
**Triggered by:** [signal name + finding IDs — e.g., "S1: H8=2 on dashboard hero card; F-003 (locked cross-talk on layout)"]
**Component:** [component-slug]
**Variants generated:** [2 or 3]
**Outcome:** [Chosen variant a/b/c | Rejected all → path (a) regen | Rejected all → path (b) revert to 10.6 fix | Rejected all → path (c) accept as-is]
### Variants considered
| ID | Approach (one line) | UX trade-off | Anti-pattern self-check | Outcome |
|---|---|---|---|---|
| a | [...] | [favors X over Y] | clean / flagged-and-fixed | Chosen ✓ / Considered |
| b | [...] | [favors Y over X] | clean / flagged-and-fixed | Chosen ✓ / Considered |
| c | [...] | [...] | clean / flagged-and-fixed | Chosen ✓ / Considered |
### Rationale for selection
[1–2 paragraphs from the user's annotation comments + Muse's reasoning about why this variant resolves the trigger signal. If "none of these" path was taken, replace this with the resolution path (a/b/c) and the user's reasoning.]
### Per-variant annotations (if any)
Annotations the team left on each variant during the chooser session — preserved verbatim so the *why* of the choice is auditable.
| Variant | Annotation excerpts (verbatim) |
|---|---|
| a | [text from comment pins / stroke captions] |
| b | [text from comment pins / stroke captions] |
| c | [text from comment pins / stroke captions] |
### Design docs updated
- `ARCHITECTURE.md` — [section name + 1-line summary of change]
- `data-model.md` — [section name + 1-line summary, or "No change"]
- `api-contracts.md` — [section name + 1-line summary, or "No change"]
- PRD `[name].md` user flow — [section name + 1-line summary, or "No change"]
### Mockup files
- **Chosen:** `.pdlc/brainstorm/variants/[feature-name]/[component-slug]-variant-a.html`
- **Considered:** `.pdlc/brainstorm/variants/[feature-name]/[component-slug]-variant-b.html`
- **Considered:** `.pdlc/brainstorm/variants/[feature-name]/[component-slug]-variant-c.html`
*(If the surface was non-visual, paths point to `.md` files containing the Mermaid + commentary instead.)*
After convergence (or skip), Muse hands lead back to Neo. Three handoff variants:
When fired and a variant was chosen:
Muse (UX Designer): "Neo — variant convergence complete. We considered [N] variants and chose variant-[a/b/c]. The full record is in the Variant Convergence section of
docs/pdlc/design/[feature-name]/ux-review.md. I've updated [list of design docs] to match the chosen variant. The rejected variants are preserved at.pdlc/brainstorm/variants/[feature-name]/as considered alternatives. The triggering Step 10.6 finding(s) [IDs] are marked resolved. Back to you for Step 11."Neo (Architect): "Got it. Taking the updated design package into Step 11 — I'll link
ux-review.mdfrom the PRD's Design Docs section and walk all five design artifacts to the Step 12 approval gate together. The Variant Convergence section will be visible to the human at approval time as a record of the design-time choice."
When fired and the team rejected all variants ("none of these" path):
Muse (UX Designer): "Neo — variant convergence didn't converge to a chosen variant. The team rejected all [N] options I drafted; we resolved via path [a/b/c]: [one-line description of resolution]. The full record is in the Variant Convergence section of
ux-review.md. [If path (b): "The original Step 10.6 textual fix is back in play."] [If path (c): "An ADR has been drafted inDECISIONS.mdcapturing the deliberate accept-as-is decision."] Back to you for Step 11."Neo (Architect): "Got it. Continuing to Step 11."
When skipped (trigger conditions didn't fire):
Muse (UX Designer): "Neo — Step 10.7 trigger conditions didn't fire — Step 10.6 surfaced findings but none required visual exploration to resolve (the textual fixes from 10.6 are sufficient). I've left a one-line skip record in
ux-review.mdso the audit trail is complete. Back to you for Step 11."Neo (Architect): "Got it. Continuing to Step 11."
Muse reads docs/pdlc/design/[feature-name]/ux-review.md — specifically the As-Built Audit section that Party Review wrote — and answers two questions:
If question 1 is no OR all three signals are no OR the affected surface is admin-only → write the skip record and hand back to Neo. If question 1 is yes AND at least one signal hits AND the surface is user-facing → proceed to Phase A′.
Record the trigger outcome in the build phase log — append a ## Variant Convergence Triage (Step 12.5) block:
## Variant Convergence Triage (Step 12.5)
- Step 10.6 triage tier: Skip / Lite / Full (must be Lite or Full to fire)
- Trigger signals (deltas read from ux-review.md As-Built Audit section):
- C1. Nielsen 8 drops ≥3: yes / no — [design-time score → as-built score]
- C2. Nielsen 4 drops ≥3: yes / no — [design-time score → as-built score]
- C3. Total Nielsen drops ≥5: yes / no — [design-time total → as-built total]
- Affected surface: [component] — major user-facing? yes / no
- Outcome: Fire / Skip
When the trigger conditions don't fire, append a ## Variant Convergence (Step 12.5) block to ux-review.md, just below the Inception 10.7 block:
## Variant Convergence (Step 12.5)
**Outcome:** Skipped — trigger conditions not met.
**Rationale:** [one line — e.g., "As-built scorecard came in at parity with design-time (Nielsen 36/40 → 36/40); no regression to converge against." or "Step 10.6 was Skipped, so there's no design-time scorecard to delta against."]
Hand back to Neo via the skip handoff (Phase E′ skip variant).
Output an Agent Handoff block before any variant work begins:
Neo (Architect): "Muse — Party Review just landed and your as-built scorecard shows [signal — e.g., 'Nielsen 8 dropped from 4 to 1 on the dashboard hero' or 'Total Nielsen 36→29 on the primary checkout flow']. The implementation has drifted from the design in a way that won't yield to a single targeted fix; we need to explore source-level alternatives before the Step 13 approval gate. You're up — define the variant criteria, work with Friday to write 2–3 alternative branches, render them side-by-side, walk the team through them, and bring back the chosen variant for me to merge. The feature branch
feature/[feature-name]is the baseline; variant branches should be authored from it."Muse (UX Designer): "On it. I'll define the variant criteria against the regression signal, hand off to Friday to write 2–3 variant branches addressing the criteria, then render the branches side-by-side in the visual companion. Each variant gets a per-branch as-built scorecard so the team can see which alternative actually closes the gap. Once the team picks one, Friday merges back to the feature branch and I re-run the scorecard against the merged state. If the scorecard now passes, we continue to Step 13. If it still regressed, we iterate (capped at 2 iterations before escalating). Back to you with the convergence."
This phase has nested handoffs: Muse → Friday → Muse. Output Agent Handoff blocks at each transition.
Muse identifies the regression locus from the As-Built Audit (which heuristic dropped, which component is affected, what change in the implementation caused the drop), then drafts variant criteria:
Muse writes the criteria to .pdlc/build/variants/[feature-name]/criteria.md so Friday can reference them while authoring. Then hands off to Friday.
Muse (UX Designer): "Friday — variant criteria are at
.pdlc/build/variants/[feature-name]/criteria.md. [N] variants requested: A focuses on [trade-off A], B on [trade-off B], C on [trade-off C]. Each variant must address [specific regression]. Author each as a branch offfeature/[feature-name]namedfeature/[feature-name]-variant-[a|b|c]. Per-variant rationale doc at.pdlc/build/variants/[feature-name]/variant-[a|b|c].mdcapturing approach + key files modified + any new tests added. Don't write production code that ships an anti-pattern — the catalog refuse list applies to variants too. Back to me when all branches are pushed."Friday (Frontend Developer): "Got it. I'll branch from the current feature tip, write variant A first, then B, then C. Each variant will be its own commit on its own branch — no cross-contamination between variants. I'll include a per-variant test if the change is testable in isolation. Rationale docs land at the path you said. Push and back to you."
Friday creates each variant branch off the current feature branch tip:
# From feature/[feature-name] tip
git checkout feature/[feature-name]
git checkout -b feature/[feature-name]-variant-a
# Implement variant A's changes...
git add -A
git commit -m "variant: [feature-name] variant A — [one-line approach]"
git push -u origin feature/[feature-name]-variant-a
git checkout feature/[feature-name]
# Repeat for B (and C)
Each variant commit uses the variant: commit-type prefix to signal that it is a non-shipping exploration commit (not a feat: / fix: — the merge into the feature branch later carries the canonical commit). Friday does not delete the rejected branches at this stage; they're preserved through Phase D′ and cleaned up at /ship Wrap-up.
Per-variant rationale doc (.pdlc/build/variants/[feature-name]/variant-[a|b|c].md) captures:
# Variant [A/B/C] — [feature-name]
**Branch:** `feature/[feature-name]-variant-[a|b|c]`
**Author:** Friday
**Approach:** [1–2 sentences — what this variant does differently]
**UX trade-off:** [what it favors, what it sacrifices]
## Files modified
- `path/to/file.ext` — [what changed in this file, 1 line]
- `path/to/other.ext` — [...]
## Diff stats
[output of `git diff --stat feature/[feature-name]..feature/[feature-name]-variant-[a|b|c]`]
## Key code excerpt
[5–15 lines from the most-changed file showing the variant's approach. Use ` ```language ` fence for syntax highlighting in the visual companion.]
## Tests added
- [test file] — [what it covers, or "no new tests — covered by existing test suite"]
## Anti-pattern self-check
[clean / flagged-and-fixed — Friday confirms no catalog refuse-list anti-patterns introduced]
Friday (Frontend Developer): "Muse — [N] variant branches pushed:
feature/[feature-name]-variant-a,-variant-b[,-variant-c]. Rationale docs at.pdlc/build/variants/[feature-name]/. Diff stats: A is [+X / -Y] over [N files], B is [+X / -Y] over [N files][, C is …]. All variants pass the existing test suite (or include new tests for changes that broke existing assertions). No anti-pattern self-check failures. Back to you for the chooser."Muse (UX Designer): "Got it. Re-running the as-built scorecard against each variant branch — this gives the team per-variant scorecard deltas in the chooser. Then I render the compare-mode page and we get the team's pick."
For each variant branch, Muse:
git checkout feature/[feature-name]-variant-[a|b|c]).Per-variant scorecard captured in the rationale doc as a Per-variant scorecard sub-section. Switch back to feature/[feature-name] before Phase C′ — don't leave the working copy on a variant branch.
The visual companion may not be running at Construction time (it's normally Inception-only). Step 12.5 starts it temporarily for the chooser session.
bash scripts/start-server.sh --project-dir $(pwd) --feature [feature-name]
start-server.sh is idempotent — no-op if already running healthy. Confirm via the /health endpoint or the $STATE_DIR/server-info file. The portal at http://localhost:7352/ (or pdlc livemode) auto-follows the new backend; users with a bookmarked portal URL don't need to copy a new port number.
The server auto-shuts on its 30-minute idle timeout — Step 12.5 doesn't explicitly stop it. Subsequent Construction work continues unaffected (the portal is just a renderer; it doesn't gate any phase).
For Construction variants, the panel content is code-excerpt + diff-stats + per-variant scorecard, not a rendered HTML mockup. (Rendering each variant as a built-and-screenshotted artifact is the live-class direction deferred to a future wave.) Each panel shows:
<pre><code class="language-X">[data-choice="variant:X"] mechanism as Inception[data-choice="variant:reject-all"])Write the page to $CONTENT_DIR/compare-mode.html. The structure mirrors the Inception version (link /variant-chooser.css, use .vc-container / .vc-panel / .vc-choose / .vc-reject-all classes); the chooser CSS works identically for code-excerpt panels.
Same mechanism as Inception (Phase C). Muse polls $STATE_DIR/events for the most recent line whose choice value starts with variant:. Variant ID = suffix.
When Muse reads choice: "variant:reject-all", she switches to the inline Decision Review pattern:
Muse (UX Designer): "You rejected all variants. Three resolution paths:
(a) Generate fresh variants with new criteria. Tell me what's missing across all [N] options. Friday writes a new round of branches with revised criteria. (Cost: another iteration; counts toward the 2-iteration cap.)
(b) Accept the current as-built scorecard regression. Decide that the regression isn't worth chasing — the as-built implementation ships as-is. ADR required in
DECISIONS.mdcapturing the accepted regression with severity rationale. (Cost: ADR write; non-P0 only — P0 findings cannot be accepted at Construction per the Step 12 approval gate rules.)(c) Drop into manual fix mode. Friday and I work directly on the feature branch to address the regression without variants — a more surgical fix than full alternatives. (Cost: tight feedback loop with you, no automated convergence. Step 13 waits until our manual fixes land and the scorecard re-runs.)
Which? (a / b / c)"
Path (a) restarts at Phase B′ with revised criteria (counts as iteration 2 if we were on iteration 1). Path (b) writes the ADR and continues to Step 13. Path (c) hands lead back to Neo with a note that Muse + Friday are continuing manual fixes.
When the user selects a variant, Muse and Friday execute the merge-back + re-validation:
Muse (UX Designer): "Friday — variant [a/b/c] is chosen. Merge it back into
feature/[feature-name]."Friday (Frontend Developer): "On it."
git checkout feature/[feature-name]
git merge --no-ff feature/[feature-name]-variant-[chosen]
# Resolve any conflicts (rare — variants are usually clean alternatives to the same locus)
git push origin feature/[feature-name]
The rejected variant branches are preserved (not deleted). They remain as feature/[feature-name]-variant-* until /ship Wrap-up cleans them up. This is the safe default — destructive deletion requires explicit user confirmation, which we don't ask for at convergence time. Users can manually git branch -D feature/[feature-name]-variant-X later if they want immediate cleanup.
Muse re-runs the scorecard against the merged feature branch:
Compute deltas against design-time and against the pre-merge as-built (the original Party Review scorecard). The expected outcome: the chosen variant closes the regression. If it does:
ux-review.md (template structure below). Place it just after the Inception Variant Convergence (Step 10.7) section, before As-Built Audit. The As-Built Audit section's tables are NOT rewritten — they remain the historical record of the pre-merge scorecard. The post-merge scorecard lives in the new 12.5 section.METRICS.md Variant Convergence calibration log (Step column = 12.5).If the post-merge scorecard still trips the trigger gate (regression not closed), increment the iteration counter and run Phase B′ again with revised criteria. Maximum 2 iterations per Party Review. If iteration 2 also fails to close the regression:
"Variant convergence couldn't close the regression in 2 iterations. Two resolution paths: (b) accept the regression with ADR (non-P0 only), (c) drop into manual fix mode."
METRICS.md calibration log with useful? = N and a 1-line note explaining why convergence failed (signals the trigger thresholds may need re-tuning).ux-review.md (Step 12.5)Append (don't replace) the following block to ux-review.md, just after the Inception Variant Convergence (Step 10.7) section and before As-Built Audit:
## Variant Convergence (Step 12.5)
**Triggered by:** [signal — e.g., "C1: Nielsen 8 dropped 4→1 on dashboard hero (delta -3 vs design-time)"]
**Component:** [component-slug]
**Variants generated:** [2 or 3]
**Iterations:** [1 or 2]
**Outcome:** Chosen variant [a/b/c] | Rejected all → path (a) regen / (b) accept regression / (c) manual fix | Iteration cap exhausted → path (b)/(c)
### Variants considered
| ID | Branch | Approach | UX trade-off | Per-variant Nielsen total | Anti-pattern self-check | Outcome |
|---|---|---|---|---|---|---|
| a | `feature/[feature-name]-variant-a` | [...] | [...] | [n/40] | clean / flagged-and-fixed | Chosen ✓ / Considered |
| b | `feature/[feature-name]-variant-b` | [...] | [...] | [n/40] | clean / flagged-and-fixed | Chosen ✓ / Considered |
| c | `feature/[feature-name]-variant-c` | [...] | [...] | [n/40] | clean / flagged-and-fixed | Chosen ✓ / Considered |
### Per-variant rationale docs
- `.pdlc/build/variants/[feature-name]/variant-a.md`
- `.pdlc/build/variants/[feature-name]/variant-b.md`
- `.pdlc/build/variants/[feature-name]/variant-c.md`
### Rationale for selection
[1–2 paragraphs from user's annotation comments + Muse's reasoning about why this variant closes the regression best]
### Per-variant annotations (if any)
| Variant | Annotation excerpts (verbatim) |
|---|---|
| a | [...] |
| b | [...] |
| c | [...] |
### Post-merge scorecard
| Metric | Design-time | As-built (pre-merge) | As-built (post-merge) | Delta vs design-time |
|---|---|---|---|---|
| Nielsen total | [n/40] | [n/40] | [n/40] | [+/- N] |
| Nielsen 4 | [score] | [score] | [score] | [+/- N] |
| Nielsen 8 | [score] | [score] | [score] | [+/- N] |
| 8-state failures | [count] | [count] | [count] | [+/- N] |
| Cognitive-load failures | [count/8] | [count/8] | [count/8] | [+/- N] |
Trigger-gate re-check: **Closed / Still regressed / Within tolerance.**
### Branches
- **Merged into feature branch:** `feature/[feature-name]-variant-[chosen]`
- **Preserved (cleanup at /ship Wrap-up):** `feature/[feature-name]-variant-[other]`, `feature/[feature-name]-variant-[other]`
After convergence (or skip / escalation), Muse hands lead back to Neo. Five handoff variants:
When fired and a variant was chosen and the regression closed:
Muse (UX Designer): "Neo — variant convergence complete. We considered [N] variants and chose variant-[a/b/c]; Friday merged its branch back into the feature branch. Post-merge scorecard closed the regression — Nielsen total now [n/40] (was [m/40] pre-merge, design-time was [k/40]). The full record is in the Variant Convergence (Step 12.5) section of
ux-review.md. The triggering As-Built Audit finding(s) [IDs] are marked resolved. Rejected variant branches (feature/[feature-name]-variant-[other], etc.) are preserved for cleanup at/shipWrap-up. Back to you for Step 13 (Review approval gate)."Neo (Architect): "Got it. Taking the merged feature branch into Step 13 — the human will see the Variant Convergence (12.5) section in
ux-review.mdalongside the unified review file at the approval gate. The variant trail is durable: we can show the human exactly which alternative we picked and why, with the per-variant scorecards as evidence."
When fired and a variant was chosen but the regression is still partially open (within iteration cap):
Muse (UX Designer): "Neo — variant [a/b/c] merged but the post-merge scorecard still shows partial regression — Nielsen total [n/40] vs design-time [k/40] (delta still ≥3). I'm running iteration 2 with revised criteria — Friday will write a new round of variant branches addressing the residual gap. Back to you when iteration 2 converges or escalates."
Neo (Architect): "OK, holding Step 13 until the regression closes or escalates."
When fired and the team rejected all variants ("None of these" path):
Muse (UX Designer): "Neo — variant convergence didn't converge. The team rejected all [N] options; we resolved via path [a/b/c]: [path description — regen / accept regression with ADR / drop into manual fix mode]. [If path (b): "ADR drafted in DECISIONS.md capturing the accepted as-built regression."] [If path (c): "Friday and I are working manually on the feature branch; Step 13 waits until our fixes land and I re-run the scorecard."] Back to you with the resolution."
Neo (Architect): "Got it."
When iteration cap exhausted:
Muse (UX Designer): "Neo — variant convergence exhausted the 2-iteration cap without closing the regression. Calibration data logged to METRICS — the trigger thresholds may need re-tuning. Resolution path [b/c] chosen by the human: [description]. Back to you."
Neo (Architect): "Got it."
When skipped (trigger conditions didn't fire):
Muse (UX Designer): "Neo — Step 12.5 trigger conditions didn't fire — as-built scorecard came in [at parity / within tolerance] vs design-time. I've left a one-line skip record in
ux-review.mdso the audit trail is complete. Back to you for Step 13."Neo (Architect): "Got it. Continuing to Step 13."
ux-review.md currentThe Variant Convergence sections (10.7 and 12.5) are one-shot per phase — they're filled when the step runs and not updated thereafter (unlike the As-Built Audit and Ship Verify sections, which fill at Construction Review and Ship Verify respectively).
Inception (10.7): if the chosen variant turns out to be wrong during Construction (e.g., Friday discovers the variant has implementation issues that weren't visible in the mockup), that surfaces as a new finding at Construction Review (Party Review) — captured in the As-Built Audit section, which can in turn trigger Step 12.5. The 10.7 record remains the historical truth of the design-time choice.
Construction (12.5): the post-merge scorecard captured here is the convergence record. If /ship Verify (Step 11.5) discovers ship-time UX regressions on top of the converged feature, those land in the Ship Verify section, not as a re-do of 12.5. Step 12.5 doesn't re-run; ship-time regressions are handled by Step 11.5's existing pattern.
Reflect (Phase 3): Jarvis reads both 10.7 and 12.5 sections at retrospective to fill the useful? column in METRICS.md Variant Convergence calibration log — the ground-truth signal for whether each fire actually paid off. After 3 fires accumulate in METRICS, Jarvis flags the calibration trigger at Reflect.
Branch cleanup (Construction-only): rejected variant branches accumulate as feature/[feature-name]-variant-*. They are deleted at /ship Wrap-up (Step 18-equivalent on the ship side) — but only after explicit user confirmation, since branch deletion is destructive. If the user defers cleanup, the branches persist; they become harmless once the feature ships and the main feature branch is merged.
agents/extensions/muse-ux-design.md — Nielsen rubric, anti-pattern refuse list, 8-state matrix, persona scanskills/brainstorm/steps/design-laws-audit.md (Phase A–E shape, triage gate pattern), skills/brainstorm/steps/threat-model.md (handoff banner pattern)skills/brainstorm/steps/03-design.md Step 10.7 invokes the Inception pathskills/build/steps/03-review.md Step 12.5 invokes the Construction pathtemplates/ux-review.md v1.5.0+ — Variant Convergence (Step 10.7) + Variant Convergence (Step 12.5) sectionsdocs/pdlc/memory/METRICS.md — Variant Convergence calibration log (Step column distinguishes 10.7 vs 12.5 entries)scripts/server.cjs — GET /variant-chooser.css (serves the chooser stylesheet); existing $STATE_DIR/events log captures variant-pick clicks via the auto-injected scripts/helper.jscompare-mode.html written to $CONTENT_DIR/, using <link href="/variant-chooser.css"> and [data-choice="variant:X"] buttons — no changes to scripts/frame-template.html needed for either pathscripts/variant-chooser.css — flexbox side-by-side layout, panel styling, chooser-button styling, mobile-stack at <900px (works for both HTML-mockup panels at 10.7 and code-excerpt panels at 12.5)scripts/start-server.sh is idempotent; Step 12.5 invokes it to start the server temporarily for the chooser; auto-shuts on 30-min idle timeout.pdlc/build/variants/[feature-name]/criteria.md (Muse's per-step variant criteria) + .pdlc/build/variants/[feature-name]/variant-[a|b|c].md (Friday's per-variant rationale + scorecard).pdlc/brainstorm/variants/[feature-name]/[component-slug]-variant-[a|b|c].htmldocs/.research/.craft-trigger-design-2026-04-30.md — variant-rendering against running app via source-rewriting, deferred to a future wave when branch-based hits a real ceilingdata-ai
Run a feature autonomously from approved-PRD to shipped, evaluated by a per-turn Sentinel hook. Requires bypass-permissions mode and Agent Teams mode.
data-ai
Force-release a stuck roadmap-level feature claim (admin command)
devops
Bypass the deploy-before-Operation guardrails block with a single confirmation
testing
Record an architectural or product decision in the PDLC Decision Registry