Harness Design Pipeline
Orchestrator composing all 6 design-pipeline sub-projects into a single sequential pipeline with convergence-based remediation: FRESHEN → DETECT → FIX → AUDIT → FILL → REPORT. Produces a unified
pass/warn/failverdict and a per-phase report. Mirrors harness-docs-pipeline in shape; consumes the formal verifier interface generically so a 5th rule-based verifier composes for free.
When to Use
- When you want a single-command design health check across drift, anatomy, brand, and craft
- After major UI refactoring that may have caused widespread drift
- As a periodic hygiene check (per-PR or per-sprint)
- When onboarding a new project that has no DESIGN.md (bootstrap mode via FILL phase)
- When
on_prtriggers fire on a UI-touching change - NOT for fixing a single known drift issue (use align-design-system directly)
- NOT for single-pass verification (use
harness check-designdirectly) - NOT for authoring DESIGN.md or tokens.json (use
harness-designskill — orchestrator only stubs absent inputs)
Capability Roles
- Defines (Service Definition): the composed-verifier seam — the
Verifier<F, Cat, Meta>interface (packages/cli/src/shared/verifier.ts) driven generically byVerifierRegistry(packages/cli/src/design-pipeline/registry.ts). This orchestrator consumes the interface generically and never reimplements a verifier. - Provides (Provider):
detect-design-drift,audit-component-anatomy, andaudit-brand-compliance(each satisfiesVerifier<F>, so a 5th composes with a singleregistry.register(...)call).harness-design-craftis dispatched in the FILL phase with a different output shape and is deliberately not registered as a verifier. - Consumes (Consumer): this skill —
harness-design-pipeline(andharness check-design) iterate the registry uniformly, so adding a verifier costs zero orchestrator change.
Relationship to Sub-Skills
| Skill | Pipeline Phase | Role |
|---|---|---|
| detect-design-drift | DETECT | Find token bypass + primitive-adoption drift |
| align-design-system | FIX | Apply codemods + emit suggestions for drift findings |
| audit-component-anatomy | AUDIT | Find missing required anatomy parts in components |
| audit-brand-compliance | AUDIT | Find token misuse + forbidden phrases (brand semantics) |
| harness-design-craft | FILL | Critique copy/hierarchy/polish (LLM-judgment ceiling skill) |
This orchestrator delegates to sub-skills — it never reimplements their logic. Each sub-skill retains full standalone functionality.
Iron Law
The pipeline delegates, never reimplements. If you find yourself writing drift detection logic, fix application logic, or audit logic inside the orchestrator, STOP. Delegate to the dedicated sub-skill.
Safe fixes are silent, unsafe fixes surface. v1 follows align-design-system's pre-flight classifier verdict: applied outcomes are silent successes; suggestion / skipped-unsafe / failed outcomes surface in the report. Never override the classifier from inside the orchestrator.
Flags
| Flag | Effect |
|---|---|
--fix |
Enable convergence-based auto-fix (default: detect + report only) |
--no-freshen |
Skip the FRESHEN phase |
--no-fill |
Skip the FILL phase (input bootstrap + craft polish) |
--ci |
Non-interactive: safe fixes only, no prompts |
--mode <m> |
Verifier mode (fast or full); default fast |
--files <...> |
Optional file/glob scope passed to each verifier |
--design-strictness <s> |
Override design.strictness |
--json |
Machine-readable output |
Shared Context Object
All phases read from and write to a shared DesignPipelineContext:
interface DesignPipelineContext {
graphAvailable: boolean;
inputs: {
designMdExists: boolean;
tokensJsonExists: boolean;
componentRegistryExists: boolean;
brandRulesExist: boolean;
};
bootstrapped: { designMd; tokensJson; componentRegistry; brandRules: boolean };
driftFindings: DriftFinding[];
fixesApplied: FixOutcome[];
auditFindings: { anatomy: AnatomyFinding[]; brand: BrandFinding[] };
craftFindings: CraftFinding[];
craftSuggestions: number;
exclusions: Set<string>;
verifiersRun: string[];
verifiersFailed: Array<{ name: string; error: string }>;
verdict: 'pass' | 'warn' | 'fail';
summary: { totalFindings; bySeverity; byCode; fixesApplied; iterationsRun; durationMs };
}
The context is passed to sub-skills via .harness/handoff.json with a pipeline field. align-design-system v1 already supports reading pipeline.driftFindings and writing pipeline.fixesApplied; other sub-skills run in standalone mode when invoked from the orchestrator.
Process
Phase 1: FRESHEN — Input Freshness Check
Skip this phase if --no-freshen flag is set.
- Check graph existence. Look for
.harness/graph/directory; setcontext.graphAvailable. - Check input file presence:
design-system/DESIGN.mdexists?design-system/tokens.jsonexists?## Component Registrysection present in DESIGN.md?## Brand Rulessection present in DESIGN.md?
- Set
context.inputs.*flags. Bootstrap action is DEFERRED to FILL phase (clean phase responsibilities).
Phase 2: DETECT — Find Design Drift
- Invoke
runDetectDrift({ path, mode, files? }). - Populate
context.driftFindingswith allDRIFT-T*andDRIFT-P*findings. - Record
'detect-drift'incontext.verifiersRun. - On failure: push to
context.verifiersFailedand continue (graceful degradation). - If
design.audit.driftDetection.enabled === falsein config: SKIP this phase entirely.
Phase 3: FIX — Convergence-Based Drift Remediation
This phase runs only when --fix flag is set.
Convergence Loop
previousCount = context.driftFindings.length
maxIterations = 5
while iteration < maxIterations:
1. Write pipeline.driftFindings to handoff.json
2. Invoke align-design-system in pipeline mode
3. Append outcomes to context.fixesApplied
4. If applied === 0: STOP (converged)
5. Re-run detect-design-drift
6. newCount = remaining findings
7. if newCount >= previousCount: STOP (no progress)
8. previousCount = newCount
9. iteration++
Each align run mutates source files via its safe codemods (T001/T002/T003 only). Probably-safe / unsafe / failed outcomes are recorded but never auto-applied (align's pre-flight classifier is the gate).
Phase 4: AUDIT — Rule-Based Verifier Loop
- Iterate the orchestrator's
VerifierRegistrygenerically:audit-anatomyrunner → populatecontext.auditFindings.anatomyaudit-brandrunner → populatecontext.auditFindings.brand
- Each verifier's failure is captured in
context.verifiersFailedwithout aborting the loop. - Iron Law: the orchestrator does NOT branch on verifier name inside the audit logic. Adding a 5th verifier means registering it; the loop body stays unchanged.
Phase 5: FILL — Bootstrap + Ceiling Polish
Skip this phase if --no-fill flag is set.
5a. Bootstrap missing inputs. For each absent input declared in Phase 1:
- DESIGN.md missing → write a minimal stub with
## Aesthetic Direction,## Component Registry,## Anti-Patterns,## Brand Rulessections, each containing<!-- TODO: ... -->placeholders. - tokens.json missing → write a minimal
{ "$description": "TODO: declare design tokens" }stub. ## Component Registrymissing (DESIGN.md exists but section absent) → append a stub table.## Brand Rulesmissing → append a stub voice subsection.
Set context.bootstrapped.{designMd,tokensJson,componentRegistry,brandRules} per-input.
5b. Invoke design-craft-elevator POLISH (critique phase).
- Call
runDesignCraft({ phases: ['critique'] }). - Populate
context.craftFindingsandcontext.craftSuggestions. - Record
'design-craft-critique'incontext.verifiersRun.
design-craft suggestions are surfaced in REPORT but do NOT contribute to the error/warn severity counts — they're ceiling-layer suggestions, not violations.
Phase 6: REPORT — Verdict + Summary
Compute verdict:
| Condition | Verdict |
|---|---|
| Any error-severity finding remains after FIX | fail |
| Any warn-severity finding OR craft suggestion OR bootstrapped any input | warn |
| Zero findings, zero suggestions, zero bootstrapped | pass |
Aggregate summary.bySeverity and summary.byCode across drift + anatomy + brand findings. (Craft findings use tier, not severity — they're tracked separately.)
Render human-readable or JSON output.
Harness Integration
harness design-pipeline— CLI entry point. Recommended for CI usage with--ci --fix.mcp__harness__run_design_pipeline— MCP tool. Same input/output. Consumed by agents needing the full design health check.harness check-design— Single-pass verifier. The orchestrator INVOKES check-design's underlying verifiers (anatomy, drift, brand) but expands them into a convergence-loop pipeline. Choose check-design for one-shot verification; choose this orchestrator for the full pipeline with fixes.harness validate— Stays single-pass (and fast). The orchestrator is opt-in and heavier — different contract..harness/handoff.json— Carries thepipelinefield between orchestrator and align-design-system. Other sub-skills run standalone-mode from the orchestrator's perspective.
Success Criteria
See docs/changes/design-pipeline/orchestrator/proposal.md for the full 34 success criteria. Highlights:
- Generic Verifier registry: adding a 5th verifier requires only a
register()call - Iron Law compliance: orchestrator imports NO drift/fix/audit logic, only sub-skill entry points
- Convergence loop bounded at 5 iterations + plateau detection
- Verdict:
pass/warn/failper documented rules - 4-platform skill markdown shipped
- MCP tool
run_design_pipelineregistered (count 73 → 74)
Rationalizations to Reject
These are common rationalizations that sound reasonable but lead to incorrect results. When you catch yourself thinking any of these, stop and follow the documented process instead.
| Rationalization | Why It Is Wrong |
|---|---|
| "Looping detect → fix → detect is slow — I'll apply every fix in one pass and skip the re-detect." | Each align pass fixes only safe codemods, and re-running detect is how the loop measures progress, detects plateau (newCount >= previousCount), and catches fix oscillation. Collapsing the loop hides non-convergence and leaves drift unmeasured. |
| "Detecting this drift inline is just a regex — I'll compute it in the orchestrator instead of invoking detect-design-drift." | Iron Law: the pipeline delegates, never reimplements. Inline detect/fix/audit logic diverges from the sub-skill's rules and defeats the whole composition contract. Invoke runDetectDrift. |
| "align classified this as a suggestion, but it looks safe to me — I'll auto-apply it from the orchestrator." | Safe fixes are silent, unsafe fixes surface. Overriding align's pre-flight classifier from the orchestrator is explicitly forbidden; suggestion / skipped-unsafe / failed outcomes surface in the report, never as writes. |
"Only one warn-severity finding remains — I'll report pass so CI stays green." |
The verdict table is fixed: any warn-severity finding OR craft suggestion OR bootstrap yields warn, never pass. Downgrading the verdict hides declared violations from the humans relying on it. |
| "I'm adding a 5th verifier — I'll branch on its name inside the audit loop to wire it in." | The Iron Law requires the audit loop stay verifier-agnostic; adding a verifier is a register() call. Branching on verifier name inside the loop breaks the generic registry and the "5th verifier composes for free" guarantee. |
Examples
Example: Clean project, default flags
$ harness design-pipeline
Verdict: ✓ pass
Phases:
FRESHEN inputs: DESIGN.md=yes tokens.json=yes registry=yes brand=yes
DETECT drift findings: 0
FIX iterations: 0, fixes applied: 0
AUDIT anatomy: 0, brand: 0
FILL bootstrapped: none, craft suggestions: 0
Summary: 0 total findings (0 error, 0 warn, 0 info) in 142ms
Verifiers run: detect-drift, audit-anatomy, audit-brand, design-craft-critique
Example: Project with drift, --fix enabled
$ harness design-pipeline --fix
Verdict: ⚠ warn
Phases:
FRESHEN inputs: DESIGN.md=yes tokens.json=yes registry=yes brand=yes
DETECT drift findings: 14
FIX iterations: 3, fixes applied: 9
AUDIT anatomy: 1, brand: 0
FILL bootstrapped: none, craft suggestions: 4
Summary: 5 total findings (0 error, 5 warn, 0 info) in 1842ms
Verifiers run: detect-drift, align-design-system, audit-anatomy, audit-brand, design-craft-critique
(9 drift fixes auto-applied in convergence loop; 5 remaining warnings + 4 craft suggestions for human review)
Example: Empty project, FILL bootstraps inputs
$ harness design-pipeline
Verdict: ⚠ warn
Phases:
FRESHEN inputs: DESIGN.md=no tokens.json=no registry=no brand=no
DETECT drift findings: 0
FIX iterations: 0, fixes applied: 0
AUDIT anatomy: 0, brand: 0
FILL bootstrapped: designMd, tokensJson, componentRegistry, brandRules, craft suggestions: 0
Summary: 0 total findings (0 error, 0 warn, 0 info) in 89ms
(All inputs absent; FILL wrote minimal stubs; verdict warn because bootstrap occurred — author the TODO sections to clear it.)
Gates
- No new verifier logic. Iron Law. Delegate to sub-skills exclusively.
- No graph schema changes. Findings persist through the existing
DesignConstraintAdapter.recordFindings()path. - No interactive prompts in v1.
--fixapplies safe codemods silently; probably-safe / unsafe surface as suggestions only.--ciis the default behavior in v1; v1.x adds--interactivefor terminal sessions. - No standalone
harness validateinvocation. validate stays single-pass; the orchestrator is opt-in. - No DESIGN.md content generation. Bootstrap writes stubs with TODO comments — sample content rots faster than skeletons.
Escalation
- When the convergence loop hits maxIterations without converging: check
context.summary.iterationsRun === 5. Real fix oscillation almost always indicates a conflict between drift findings (e.g., two tokens with the same value). InspectfixesAppliedoutcomes; the failing pattern is usually visible. - When a verifier consistently fails:
context.verifiersFailed[].errorcarries the message. Run the verifier standalone (e.g.harness skill run audit-brand-compliance) to reproduce — orchestrator just propagates the failure. - When FILL bootstraps a file you didn't want bootstrapped: delete the stub; the orchestrator only writes when the file is absent. Or run with
--no-fillto suppress the entire phase. - When verdict is
failbut you want to merge anyway: the orchestrator exits with code 1; bypass via CI config (treating design-pipeline as advisory not blocking). Not recommended — error-severity findings represent declared violations. - When
--cimode is too conservative: v1's--cionly applies align'ssafe-codemod-classified fixes. Use v1.x's--interactive(or the standaloneharness align-design-system --dry-run) to review and apply probably-safe fixes manually.
Status
v1 — in implementation. See:
- Spec:
docs/changes/design-pipeline/orchestrator/proposal.md - Roadmap entry: part of the
design-pipelineinitiative (the orchestrator) - Sibling:
harness-docs-pipeline(the pattern this mirrors) - Floor + ceiling sub-skills:
detect-design-drift,align-design-system,audit-component-anatomy,audit-brand-compliance,check-design,harness-design-craft