mcpField
S
sb-health

sb-health

github.com/strongeronデザイン・UI3978 回インストール4 週間前に更新
リポジトリ

sb-health について

sb-healthは、デザインシステムのトークンやスタイルを検査し、Storybook表示用の指摘を出力するスキルです。エラーと情報レベルの兆候を区別し、任意でプロパティとトークンファミリーのルールも検証できます。

主な機能

  1. 01生のカラー値と未定義トークンの検出
  2. 02トークン使用状況とスケール間隔の確認
  3. 03CSSトークンとDESIGN.mdの記述の照合
  4. 04任意のプロパティ・トークン分類ルール検査
  5. 05Storybook表示用の指摘を出力

活用シーン

  1. 01トークンに置き換えるハードコード色の特定
  2. 02未宣言トークンを参照するコンポーネントの確認
  3. 03設計ブリーフとコードのずれの確認
  4. 04デザイナー定義のプロパティ・トークン規則の検証

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/strongeron/storybook-workbench --skill sb-health

インストール後、Claude Code で/sb-healthを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

CONTEXT.md
agents/
openai.yaml
decorators/
withLayoutFrame.tsx
references/
colors.example.json
colors.schema.json
scripts/
check-property-tokens.py
scaffold-wrapper.sh
validate-design-system.sh
wrappers/
DesignSystemHealth.tsx
icons.tsx
ReportIntro.tsx
resolve-paint.ts
usage-index.tsx
usage-stamp.tsx

詳細

sb-health — デザインシステムのヘルスゲート

ブラウザーからシェルコマンドを実行できないため、スクリプトがチェックを実行して JSON を書き出し、ラッパーがそれをレンダリングします。 design-system-health.json はレンダリング済みの出力(Health Docs + DesignSystemHealth/TokenMatrix)です。そのため、 refresh-usage.sh はほかのレンダリング済み抽出ツールとともに、このチェックを再実行します。詳しくは CONTEXT.md §STORAGE MAP を参照してください。

実行方法

SKILL=${CLAUDE_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}
CORE=${CLAUDE_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}
"$SKILL/scripts/validate-design-system.sh"       # → .storybook/design-system-health.json
# --emit-prompt  also outputs an LLM sub-agent prompt for semantic checks
#                (naming drift, semantic-vs-presentational, scale clarity)
"$CORE/scripts/scaffold-wrapper.sh" DesignSystemHealth   # → .storybook/wrappers/ (+ icons.tsx)

# Opt-in property→token-family check (off until a designer authors the rules file):
"$SKILL/scripts/check-property-tokens.py" --init   # scaffold design-system/lint/colors.json (+ schema)

チェック項目

  • raw-color — コンポーネント内の hex/rgba/hsl リテラル(トークンを使うべき箇所)。リテラルの値が既存トークンの解決後の値と一致する場合(例:兄弟要素で bg-secondary を使っているタイルの #005596 → --secondary は #005596 に解決される)、修正方法は新しいトークンを作ることではなく、その一致するトークンを採用することです。該当するトークンを解決できる場合、検出結果にその名前が表示されるため、修正は「トークンを追加する」ではなく「--x に置き換える」です。
  • undefined-token — コンポーネントが、宣言されていない --foo を参照している
  • scale-gap — スペーシング/タイポグラフィのスケールに予期しない間隔がある
  • unused-token — 宣言されているものの、一度も参照されていない(var、Tailwind ユーティリティ、またはカスタムの @utility)。ここでは再スキャンせず、sb-inventory の単一のソース(.storybook/project-inventory.json → tokens.map)から読み取ります。これにより、ヘルスチェック、インベントリ、トークンビューの内容が食い違うことはありません。まず sb-inventory を実行してください。ファイルがない場合、このチェックはスキップされます。
  • design-md — DESIGN.md(Google Labs の YAML トークン+Markdown 形式。エージェントにビジュアルアイデンティティを伝える方法として、ますます一般的になっています)は事実ではなく主張です。AGENTS.md と同様、コードの変更に伴って内容が古くなったり、最初から誤っていたりすることがあります。スクリプトはこれを検出し、そこに記載された色とコードの CSS トークンで実際に宣言されている色を照合し、コードで定義されていない各色について design-md-drift を出力します。存在する DESIGN.md は、整合性を確認するまで信頼できないものとして扱ってください。
  • property-token-family (オプトイン) — 有効で、宣言済みのトークンが、誤ったプロパティファミリーで使われている場合(例:color: var(--color-container) — テキスト色としてコンテナ用トークンを使っている)。raw-color は「トークンがない」ケースを検出し、undefined-token は「トークンが存在しない」ケースを検出します。このチェックは「実在するトークンだが、スロットが間違っている」ケースを検出します。デザイナーが design-system/lint/colors.json を作成するまで無効です(下記参照)。そのため、初期設定のままでも設定不要で使えます。検出結果は warning/info のみです。オプトインしても、成功している CI ビルドが失敗に変わることはありません。
  • stylelint が設定されている場合は実行します

summary(エラー/警告/情報の件数)と主な検出結果を報告します。DesignSystemHealth ラッパーは共通のアイコンセットを使って重大度を表示します(絵文字は使いません)。

書き出される JSON の形式(このフィールドを読み取り、再計算しないでください)。各検出結果は {kind, severity, message, file?, line?, fix?} で、件数の集計は summary に含まれます。

{
  "findings": [
    { "kind": "raw-color",       "severity": "error",   "file": "Button.tsx", "line": 42, "message": "#3b82f6 literal", "fix": "use --color-primary" },
    { "kind": "undefined-token", "severity": "error",   "file": "Card.tsx",   "line": 11, "message": "--surface-2 not declared" },
    { "kind": "design-md-drift", "severity": "warning", "message": "DESIGN.md claims #1e90ff; no token declares it" },
    { "kind": "unused-token",    "severity": "info",    "message": "--legacy-accent declared, never referenced" },
    { "kind": "scale-gap",       "severity": "info",    "message": "spacing jumps 16px → 48px" },
    { "kind": "property-token-family", "severity": "warning", "file": "Card.css", "line": 3, "message": "background uses --color-content — not allowed for 'background*' (expects --color-container / --color-canvas)", "fix": "Use one of --color-container, --color-canvas, or remap with /* color-lint-alias: … */" }
  ],
  "summary": { "total": 6, "errors": 2, "warnings": 2, "info": 2, "checksRun": ["raw-color", "undefined-token", "..."] }
}
プロパティ→トークンファミリーのルール(任意設定、デザイナーが管理)

どのプロパティにどのトークンファミリーを割り当てるかはデザイン上の意図なので、スクリプトではなく、デザイナーが編集できるルールファイルに記述します。ルールはデザイナーが管理し、リンターは開発者が管理します。最初に一度だけひな形を作成します(ファイルと、どのエディターでも内容がわかるよう自己文書化された JSON Schema の両方が書き出されます)。

"$SKILL/scripts/check-property-tokens.py" --init    # → design-system/lint/colors.json (+ colors.schema.json)
// design-system/lint/colors.json — owned by the designer
{
  "$schema": "./colors.schema.json",
  "propertyTokens": {
    "color":       ["--color-content"],                                   // exact property
    "background*": ["--color-container", "--color-canvas", "--color-backdrop"], // family (trailing *)
    "box-shadow":  ["--color-border", "--color-shadow"],
    "border*":     ["--color-border"]                                     // values are token PREFIXES
  }
}

対象となるのは、ルールに記載されたプロパティだけです(プロパティを1つずつ有効にします)。回避策は優先順に以下のとおりです。どちらもソースファイルから読み取られます。

/* color-lint-alias: --color-theme --color-container */  /* file-level prefix remap: a token is
                                                            semantically right but lives in the "wrong"
                                                            family — treat this prefix as that one */
color: var(--color-theme-fg); /* color-lint-ignore */    /* per-line suppression — counted, and the
                                                            report nudges a refactor past 10. The number
                                                            growing is the signal: mute fast, fix slowly. */

ルールファイル自体も、DESIGN.mdと同様に事実ではなく主張です。ルールで許可されたトークンプレフィックスに一致する宣言済みトークンがない場合、スクリプトはproperty-rules-driftを出力します。これにより、古い設定が問題なく通過したり、誤ったフラグが出たりするのを防げます。

トリアージの順序 — 判定を左右するのは件数ではなく重大度です: まずerrorを修正します(raw-color → 既存のトークンにマッピングする、undefined-token → トークンを宣言するか、タイプミスを修正する)。次にwarningを整合させます(design-md-drift → design-mdに引き継ぐ、property-token-family → 許可されたトークンに置き換える。トークンが本当に適切な場合はcolor-lint-aliasを追加する、property-rules-drift → ルールファイルを修正する)。そして、infoはそのまま報告します(unused-token/scale-gap/property-lint-suppressionsは確認が必要なシグナルであり、自動修正の対象ではありません。「禁止事項」を参照)。エラーが0件でinfoが20件のリポジトリは健全です。

禁止事項(および、見落としがちな理由)

  • unused-tokenを見つけても、絶対にすぐ削除しないでください — これはerrorではなくinfoです。静的スキャンでは、Tailwindユーティリティ(bg-[--brand])で使われているトークン、文字列結合で実行時に組み立てられるvar()、モノレポ内の別のアプリで使われているトークンを検出できません。「未使用」とは「参照が見つからなかった」という意味であり、「安全に削除できる」という意味ではありません。
  • scale-gapを修正対象の不具合として扱わないでください — これはinfoです。実際のスケールには意図的な間隔があります(本文サイズから大きく離れたディスプレイサイズなど)。「滑らかに」しようとすると、誰も求めていないトークンが作られ、デザイナーが選んだリズムが崩れます。
  • DESIGN.mdを事実として信頼しないでください — AGENTS.md/CLAUDE.mdと同様に、これは主張であり、実態とずれることがあります。まずdesign-md-driftとの整合を取ってください。未整合のDESIGN.mdは、コードで定義されていない色について、確信を持って誤った説明をすることがあります。
  • raw-colorを、新しいトークンを作って「修正」しないでください — 既存のトークンにマッピングします。リテラル値ごとに新しいトークンを作ると、混乱をトークンレイヤーに移すだけです(次回の実行でundefined-tokenのノイズがさらに増えます)。
  • 再度grepして、このJSONを手作業で計算し直さないでください — ブラウザーからシェルを実行できないため、情報源はスクリプトだけです。各フィールドを参照してください。目視で再計算すると、ラッパーが表示する件数とずれてしまいます。

後回しにする場合

抽出(混乱したコードベースをトークンとコンポーネントに変換する作業)では、このスキルは測定のみを行います。実際に抽出するには、/ds-runbook → /ds-audit → /ds-token-extract → /ds-component-extractを実行してから、ここに戻って健全性を確認し、sb-storiesでキャプチャしてください。

ずれが生じた**DESIGN.mdを扱う場合(または、コードで実際に使われているトークンをもとに新規作成/再生成する場合)は、design-md**スキルに引き継いでください。このスキルはGoogle LabsのDESIGN.md形式を構成、抽出し、詳細に監査します。sb-healthはずれを検出するだけですが、design-mdは概要を整合させるか、書き直します。

次の手順

健全性に問題があり、プロジェクトが移行中であれば、ストーリーを作成する前にトークンを修正するか、ds-*スキルに引き継いでください。それ以外の場合は、検出結果を追記してsb-storiesに進みます。

コメント