agentsclimarketplace

Dux design md lint

Skill Yash-1511/bmad-dux-visual-architect/skills/dux-design-md-lint

Validates DESIGN.md against the getdesign.md alpha spec and WCAG contrast. Use when the user says 'lint DESIGN.md', 'validate DESIGN.md', or selects DL from Mayasura's menu.From its SKILL.md

Install
npx -y skills add Yash-1511/bmad-dux-visual-architect --skill dux-design-md-lint

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

7.5 KB, as published. Nobody here has run it

dux-design-md-lint

Overview

Validates the project's DESIGN.md against the getdesign.md alpha spec and WCAG 2.1 AA contrast, producing a self-contained HTML report under {design_output_folder}/lint/{timestamp}.html. The report groups findings by severity, renders failing color pairs as inline swatches, and ships concrete fix snippets.

The deterministic work (parse, schema check, coverage, token-ref resolution, contrast math) lives in Python scripts. The prompt interprets findings, decides edge-case severity, walks the user through the report, and offers handoff to dux-design-md for fixes.

The workflow runs under Mayasura, the Visual Architect — that persona is established by dux-agent-mayasura and carries through unchanged. Do not re-greet, do not break character.

Args: --headless for CI gating (exits non-zero on any AA-level contrast failure or spec error). Optional path arg to a non-default DESIGN.md location.

Conventions

  • Bare paths (e.g. references/contrast-rules.md) resolve from the skill root.
  • {skill-root} resolves to this skill's installed directory.
  • {project-root}-prefixed paths resolve from the project working directory.
  • {skill-name} resolves to the skill directory's basename.

On Activation

Load module config from {project-root}/_bmad/config.yaml and {project-root}/_bmad/config.user.yaml — root level plus the dux section. Bind:

  • {design_md_path} from dux.design_md_path (default {project-root}/docs/DESIGN.md)
  • {design_output_folder} from dux.design_output_folder (default {project-root}/_bmad-output/design)

If {design_md_path} does not exist, exit early with a clear pointer to dux-design-md (DM) — there is nothing to lint. Do not create a placeholder file.

Read {design_workspace}/.dux-design-md.decision-log.md if it exists. The DESIGN.md decision log is owned by dux-design-md; this workflow reads it to surface rules the user has explicitly chosen to relax (with reasons) and adjust severity accordingly. Never write to it. Lint's own per-run state lives entirely inside the HTML report.

Stage 1 — Run the Linter

Run the deterministic checker:

python3 scripts/lint.py {design_md_path} -o {design_output_folder}/lint/{timestamp}.findings.json

The script parses DESIGN.md (YAML front matter + prose sections), runs all six checks, and emits a single findings JSON document. It does no interpretation — every finding includes a category, a severity, a location (section, line, or token), a detail, and a fix snippet where one is unambiguous. See scripts/lint.py --help for the full check list.

Exit codes from the script:

  • 0 — no findings at error severity
  • 1 — at least one error-severity finding (spec violation, broken token ref, AA body-text contrast fail)
  • 2 — script error (malformed file, unparseable YAML)

In interactive mode, run regardless of exit code and continue. In headless mode, propagate the exit code on completion.

Stage 2 — Interpret and Adjust

Read the findings JSON. The script assigns a default severity to every finding; this stage is where prompt judgment refines edge cases the deterministic logic can't decide:

  • Contrast on disabled / placeholder roles — AA still applies but a 3:1 minimum is conventional rather than 4.5:1. Downgrade body-text fails on these to warning if context makes it clear they're disabled-state pairs.
  • Hairline-as-decoration — hairline colors used purely as 1px non-functional borders are not text contrast; suppress contrast findings against hairline when no text role pairs with it.
  • Relaxations from the DESIGN.md decision log — if the log records "AA relaxed for <role> because <reason>", downgrade matching findings to info and annotate with the recorded reason.
  • Pseudo-pairs — color pairings the script inferred from the YAML cartesian (e.g. success text on surface-card when the brand never uses success text on cards) get downgraded to info if no component actually composes them.

Do not invent findings the script did not surface. The script is the source of truth for what exists in DESIGN.md; the prompt's job is to interpret severity, not to add new defects.

Severity tiers (final, after adjustment):

TierExamples
errorRequired YAML block missing, prose section out of order or missing, YAML↔prose 1:1 broken, token ref points at non-existent token, AA body-text contrast fail (< 4.5:1) on a real component pair
warningAA large-text contrast fail (< 3:1), Known Gaps section empty or platitudinous, semantic-color pair the brand actually uses falls short of AAA
infoAAA aspiration (any pair < 7:1 body / 4.5:1 large), spec quirks worth noting but not breaking, suppressed-by-relaxation findings

Stage 3 — Render the Report

Render the HTML report:

python3 scripts/render-report.py {findings-json-path} --design-md {design_md_path} -o {design_output_folder}/lint/{timestamp}.html

The renderer produces a single self-contained HTML file — no external CSS, no CDN, no images. Every failing color pair renders as an inline swatch (background-color + on-color rendered as actual CSS) so the user sees the failure, not just the math. Findings group by severity (errors → warnings → info), and each entry includes its detail, exact contrast ratio (for contrast findings), and fix snippet ready to paste.

If interactive, also write a small companion summary line to stderr and offer to open the report.

Stage 4 — Walk the User Through

In interactive mode, present findings to the user in order: errors first, walking each one with the exact location and the concrete fix. After errors, offer to skim warnings and info. Soft-gate at the end: "anything you want to dig into, or shall we hand off to DM to apply fixes?"

In headless mode, skip the walkthrough.

Stage 5 — Handoff

If errors exist and the user accepts, dispatch dux-design-md in Update mode with the findings JSON as the change brief. DM is the authoritative writer; lint never edits DESIGN.md directly.

If no errors exist, mention the report path and exit. Mayasura's menu stays available.

Headless Mode

--headless runs Stages 1, 2 (script-level severity only; no prompt adjustment in headless), and 3 — then exits.

Emit JSON on stdout:

{
  "status": "pass" | "fail",
  "errors": <count>,
  "warnings": <count>,
  "info": <count>,
  "report": "{design_output_folder}/lint/{timestamp}.html",
  "findings_json": "{design_output_folder}/lint/{timestamp}.findings.json",
  "design_md": "{design_md_path}"
}

Process exit code:

  • 0 if errors == 0
  • 1 if any error-severity finding exists

This is the contract CI consumers depend on; do not break it.

Non-Negotiables

  • Findings are evidence-based. The script is the source of truth for what's in DESIGN.md. The prompt may interpret severity; it must not invent defects.
  • HTML report is self-contained. No external CSS, no CDN, no fonts pulled from the web. The report opens cleanly offline.
  • Never write to DESIGN.md or its decision log. Lint reads; DM writes.
  • Contrast math is deterministic. All ratios come from the script. Do not hand-calculate or estimate.
  • Mayasura persona. Carries through from dux-agent-mayasura. Do not re-greet, do not break character.

Keep looking

Skills are one crate of 627,801. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.