記事の要約
- pbakaus/impeccable(Apache 2.0)は、AI生成UIの「AIっぽさ」を 59個の決定的(deterministic)ルールで検出するスキル+検出器
- Impeccable は IBM Bob 向けディレクトリを同梱していないが、
.cursor/版をそのまま配置して完全に動いた(23コマンド認識、検出器も実行可能) - 同じAI生成HTMLを起点に、Impeccable を参照しただけの場合と Bob で検出器をループに入れた場合を比較した
- 結果:参照しただけの版は 4件 → 11件に悪化。検出器を回した版は 0件
- 効いたのは「1回で直す」ことではなく、検出 → 修正 → 再検出のループ(Bobも1回目は0件にできなかった)
検証環境
| 項目 | 値 |
|---|---|
| ホスト | IBM Bob IDE 2.0.3 |
| Impeccable | SKILL.md version: 4.0.4(package.json は 3.5.0) |
| Node.js | v26.3.1 |
| 検証日 | 2026年8月14日 |
Impeccable とは
AIコーディングエージェント向けのデザインスキルです。中身は大きく2つ。
-
23コマンド:
polishauditcritiquedistillanimatebolderquietertypesetcolorizelayoutなど。SKILL.md の Commands 表で Build / Evaluate / Refine / Enhance / Fix / Iterate の6カテゴリに分類されています(うちcraftは非推奨エイリアスで、実質22個) -
59検出ルール:
scripts/detector/registry/antipatterns.mjs(617行)に定義。detect.mjsから機械的に実行できます
ルールの例(実際のID):
ai-color-palette 紫/violetグラデ、暗背景+シアン
nested-cards カードの中のカード
low-contrast コントラスト比不足(WCAG)
gray-on-color 色背景の上のグレー文字
cramped-padding ボーダー内側の余白不足
skipped-heading 見出しレベル飛ばし
side-tab border-left 4px + border-radius
overused-font 多用されすぎたフォント
gradient-text グラデーション文字
em-dash-overuse —(em dash)の多用
「AIっぽさ」だけでなく、アクセシビリティ(コントラスト比、見出し構造)まで含まれているのがポイントです。ここが後で効いてきます。
なぜ必要か
AIモデルは似たSaaSテンプレートで訓練されているため、デザイン指示を与えないと同じ「AIテンプレート風」UIに収束します。今回の題材でもそれが露骨に出ました。
「動物病院のサイトを作って」 と指示したのに、返ってきたのがこれです。

紫→青グラデーション、AIでUIを生成させたことがある人なら誰もが見たことがあると思います。犬猫小動物の絵文字が面白すぎる。
結果
Bob に /impeccable polish を投げた結果がこちらです。
なんかそれっぽくなった?
使える画像がなかったので、どうしてもシンプルなデザインになってしまっていますが、動物病院の写真とか動物の写真とか載せたら良い感じになるのではないでしょうか。
紫→青グラデーションが消え、ヒーローとCTAが一貫したオレンジになりました。検出器で測ると アンチAIパターンは4件 → 0件です。
以下、改善の経緯を書いていきます。
Bob への導入
どのディレクトリを使うか
Impeccable はエージェントごとにディレクトリを持っています。
$ ls -a impeccable/
.agents .claude .claude-plugin .codex .cursor .gemini
.grok .hermes .kiro .opencode .pi .qoder .rovodev .trae
IBM Bob 専用のディレクトリはありません。 ではどれを使うか。実体を比較しました。(Bobが)
| ディレクトリ | ファイル数 | reference | scripts | サイズ | 接頭辞 | ベンダー固有 frontmatter |
|---|---|---|---|---|---|---|
.agents/ |
153 | 36 | 40 | 3.4M | $impeccable |
なし |
.claude/ |
148 | 36 | 40 | 3.4M | /impeccable |
user-invocable argument-hint allowed-tools
|
.cursor/ |
148 | 36 | 40 | 3.4M | /impeccable |
なし |
.gemini/ |
148 | 36 | 40 | 3.4M | /impeccable |
なし |
.opencode/ |
148 | 36 | 40 | 3.4M | /impeccable |
なし |
reference 36件・scripts 40件・3.4MB は全ディレクトリで同一でした。差分は3点だけです。
- SKILL.md 内の自己参照パス
- コマンド接頭辞(
/impeccableか$impeccableか) -
.claude/のみ Claude Code 固有の frontmatter を持つ(allowed-toolsが.claude/パス前提)
つまり検出器を含む実体はどれを選んでも同じで、違うのは「エージェントにどう呼ばせるか」だけ。
Bob はスラッシュコマンドを /impeccable で受けるので、.cursor/ が最も素直です。frontmatter は name / description / version / license のみで Cursor 固有キーを持たず、実質「/ 接頭辞の中立版」として使えます。
git clone https://github.com/pbakaus/impeccable.git
cp -r impeccable/.cursor/skills/impeccable ~/.bob/skills/impeccable
SKILL.md 内の自己参照パスが .cursor/... のまま残りますが、SKILL.md 自身が「ランタイムが報告するベースディレクトリを優先し、.cursor/skills/impeccable/scripts はフォールバック」と明記しているため実害はありません。
認識確認
Bob に読み込ませたところ、そのまま通りました。
✅ name: impeccable
✅ version: 4.0.4
✅ コマンド: 23個(Build 5 / Evaluate 2 / Refine 6 / Enhance 6 / Fix 3 / Iterate 1)
✅ 検出ルール: 59個(antipatterns.mjs, 617行)
✅ context.mjs: 正常動作、6つのディレクティブを出力
Bob 向けの対応が一切ないスキルが、コピーしただけで完全に認識されました。
実験設計
同じ原本から2つの経路に分岐させ、それぞれを同じ検出器で測ります。
before/vetclinic.html (AI生成の原本)
│
├─────────────→ after/vetclinic.html スキルを参照して全面リデザイン(検出器なし)
│
└─────────────→ after/vetclinic-bob.html Bob で /impeccable polish
cp before/vetclinic.html after/vetclinic-bob.html
出発点を揃えているので、フェアな対照になります。
ステップ1:ベースライン測定
$ node ~/.bob/skills/impeccable/scripts/detect.mjs \
"file:///.../after/vetclinic-bob.html"
[ai-color-palette] Purple/violet gradient (Tailwind)
[ai-color-palette] Purple/violet gradient background
[ai-color-palette] Purple/violet gradient background
[skipped-heading] <h2> "ペットの診療をお考えですか?" followed by <h4> "診療案内" (missing h3)
4 anti-patterns found.
4件。内訳は ai-color-palette ×3 と skipped-heading ×1。
前者は例の紫グラデーション(ヒーロー、CTA、bg-purple-50 の猫カード)。後者はフッターで h2 の次が h4 になっている構造欠陥です。Impeccable が狙う「AIの兆候」と、アクセシビリティ問題が同時に出ました。
ステップ2:Impeccable を「読んだだけ」の版
比較対象として、もう1つの版があります。AIエージェントに Impeccable を参照させて全面リデザインさせたものです。スキルの原則(グラデーションをやめる、ダークフッターをやめる、Shadowをボーダーにする)に従って、レイアウトごと作り直しています。
こんな動物病院のサイトは嫌ですね。
この版は一度も detect.mjs を実行していません。 スキルの知識は使ったが、測定はしなかった版です。
$ node ~/.bob/skills/impeccable/scripts/detect.mjs \
"file:///.../after/vetclinic.html"
[cramped-padding] <div> "border": children flush against border on top/right/bottom
[low-contrast] 2.5:1 (need 4.5:1) — text #9ca3af on #ffffff
[low-contrast] 2.5:1 (need 4.5:1) — text #9ca3af on #ffffff
[low-contrast] 2.5:1 (need 4.5:1) — text #9ca3af on #ffffff
[low-contrast] 2.5:1 (need 4.5:1) — text #9ca3af on #ffffff
[nested-cards] Card inside card
[nested-cards] Card inside card
[nested-cards] Card inside card
[nested-cards] Card inside card
[nested-cards] Card inside card
[skipped-heading] <h2> "ご予約・お問い合わせ" followed by <h4> "診療案内"
11 anti-patterns found.
4件 → 11件。悪化しました。
内訳を追うと、何が起きたかが分かります。
| ルール | 変化 | 何が起きたか |
|---|---|---|
ai-color-palette ×3 |
消滅 ✅ | 紫グラデ除去は成功 |
skipped-heading ×1 |
残存 | フッターの h4 修正が漏れた |
nested-cards ×5 |
新規 ❌ |
bg-gray-50 セクション内に border 付き白カードを置いた |
low-contrast ×4 |
新規 ❌ |
text-gray-400(#9ca3af)が白背景で 2.5:1 |
cramped-padding ×1 |
新規 ❌ | ボーダー化した際に内側余白が不足 |
「一番目立つ兆候(紫グラデ)は消せたが、直した先で3種類のアンチパターンを新たに踏んだ」という結果です。
ステップ3: 本気で作らせる
/impeccable polish after/vetclinic-bob.html
動物病院のサイトとして、デザインを本気で作り込んでください。
レイアウト・構成・タイポグラフィ・余白・配色、すべて変更して構いません。
条件:
- 掲載情報(診療科目、診療時間、アクセス、初診フロー、予約導線)は維持すること
- 作業後、必ず detect.mjs を実行して検出0件を確認すること
- 0件にならない場合は修正を繰り返すこと
ここで Bob の挙動が変わりました。reference/polish.md と reference/craft-floor.md を読みに行ったのです。craft-floor.md は「検出器では捕まえられない品質の下限」を定義したドキュメントで、SKILL.md から「UI編集の直前に読め」と指示されています。
そこから Bob が拾ってきた禁止事項:
- Unicode glyphs or emoji standing in for an icon system → 絵文字の廃止
- kicker above heading → 英字ラベルの廃止
- colored border-left/right above 1px on cards
どれも59ルールの検出対象ではありません。 検出器には引っかからないが、スキルが「やるな」と定めている項目です。
3ラウンドで0件へ
| ラウンド | 検出 | 内容 |
|---|---|---|
| 初稿 | 6 | low-contrast ×4、kicker-above-heading ×2 |
| 2回目 | 2 | low-contrast ×2(opacity: 0.85 の重ね、CTAの #fed7aa) |
| 3回目 | 0 | — |
変わったもの
構造そのものが変わりました。
- ナビゲーションバーを追加(スティッキー、アンカーリンク付き)
-
診療科目:カード → オレンジの罫線+テキスト(
nested-cardsの原因を構造ごと排除) -
診療時間:
<thead>付きの「曜日 / 午前 / 午後」テーブルに再設計 -
アクセス:カード →
<dl>のグリッド - 初診フロー:カード積み重ね → 番号丸+コネクタのステップリスト
- 本文コピー:「予防接種から手術まで幅広く対応」→「子犬の予防接種・健康診断から、内科・外科・歯科治療まで幅広く対応します」
$ node ~/.bob/skills/impeccable/scripts/detect.mjs \
"file:///.../after/vetclinic-bob.html"
$ echo $?
0
0件を維持したまま、デザインが別物になりました。
学び
1. 効いたのは「AIの賢さ」ではなくループ
**Bob も一発では0件にできませんでした。ステップ3でも初稿で検出ルールに6件引っかかりました。
つまりこれは「AIがデザインを分かっている」話ではなく、客観的な合否判定がループに入っているかの話です。テストがあるからリファクタできる、というのと同じ構図です。
2. 「AIっぽさの排除」は副作用を持つ
ステップ2の版の nested-cards ×5 は、「グラデーション背景をやめて白背景+ボーダーにする」という正しい判断の副作用でした。色で区切っていた領域を枠線で区切り直した結果、枠の入れ子ができています。
「AIっぽさを消す」改修は、それ自体が新しいアンチパターンを生みます。1回直して終わりにできない理由がこれです。
3. 「0件」は「良いデザイン」ではない
検出のルールに引っかからないデザインでも人間が見ると微妙でした。
4. 検出器の外側は craft-floor.md が担う
Impeccable は「検出できる59ルール」と「検出できないが守るべき下限」を別ファイルに分けて持っています。前者は detect.mjs、後者は craft-floor.md。SKILL.md はUI編集の直前に後者を読むよう指示しています。
detect.mjs 機械的に検出できる59項目 → 合否判定
craft-floor.md 検出できない品質の下限 → エージェントが読む
この二層構造を理解しないと、「0件だから完璧」という誤読をします。検出器を通すのは最低条件であって、目標ではありません。
実用上のポイント
Bobへのスキル導入は問題なく行えました。
修正には人間が具体的な指示をする必要があるものの、アンチパターンルールは機械的判定なので出力にブレはな以下と思います。
再現手順
# 導入
git clone https://github.com/pbakaus/impeccable.git
cp -r impeccable/.cursor/skills/impeccable ~/.bob/skills/impeccable
# 依存(これを忘れると DEGRADED で過少カウント)
cd ~/.bob/skills/impeccable
npm init -y && npm i htmlparser2 css-select css-tree domutils puppeteer
# 静的解析
node ~/.bob/skills/impeccable/scripts/detect.mjs path/to/ui.html
# ブラウザ実測(コントラスト比まで評価)
node ~/.bob/skills/impeccable/scripts/detect.mjs "file://$PWD/path/to/ui.html"
# CI向け
node ~/.bob/skills/impeccable/scripts/detect.mjs --json src/
主なオプション:
--json JSON出力
--quiet 件数のみ
--scope <name> ドメイン限定(type, layout)
--viewport <WxH> URLスキャン時のビューポート(既定 1280x800)
--no-advisory advisory(em-dash多用など)を抑制
個別に無効化する場合:
<!-- impeccable-disable overused-font -- exported brand doc -->
<div class="brand">...</div>
参考リソース
- Impeccable 公式
- GitHub: pbakaus/impeccable(Apache License 2.0)
本記事に引用したルールID・説明文・ヘルプ出力は Impeccable(Apache License 2.0, © Paul Bakaus)に由来します。



