directions-lab について
directions-labは、リポジトリ内にデザイン検討ページを構築するスキルです。Todayと複数の案を共通コントロールで比較でき、設定をレジストリで管理し、Storybookのエントリーも生成します。
主な機能
- 01Viteの方向性ページを構築
- 02Todayと2〜3案を比較
- 03レジストリで案と画面を設定
- 04Storybookの提案ストーリーを生成
- 05スキャフォールドの検査とテスト
活用シーン
- 01製品機能のデザイン検討を作成
- 02出荷済みコンポーネントと案を比較
- 03Storybookのデザインディレクトリに提案を追加
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ paperclipai/ paperclip --skill directions-labインストール後、Claude Code で/directions-labを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
agents/openai.yamlassets/PRECEDENTassets/motion/v1-mvp-motion.cssassets/templates/api-routes.ts.mjsapi-stub.ts.mjsbuild-info.ts.mjsdefine-lab.ts.mjsentry.html.mjsfixtures.ts.mjskit.ts.mjslab-state.ts.mjslab.css.mjslaunch-entries.json.mjsmain.tsx.mjsproviders.tsx.mjsregistry.ts.mjsshot.cjs.mjsassets/templates/direction/index.tsx.mjsMotionSpecimen.tsx.mjsSlotBody.tsx.mjstokens.css.mjsassets/templates/frames/AppShell.tsx.mjsBoard.tsx.mjsLabToolbar.tsx.mjsSlot.tsx.mjsSurfaceFrame.tsx.mjsSurfaceView.tsx.mjsassets/templates/stories/compare.stories.tsx.mjsassets/templates/tests/api-stub.test.ts.mjslab-state.test.ts.mjs詳細
Directions lab
Directions lab は、このリポジトリでデザインの検討を行うためのものです。1ページ、1つの機能、Today と 2〜3 個のデザイン案、機能が表示されるすべての画面、そして毎回同じコントロールを備えるため、共有リンクを誰が開いても同じように表示されます。artifact directions lab(ui/src/artifact-directions)が先例として固定のリファレンスになっており、このスキルでは配線を手作業で描き直すことなく、同じ形式の新しい lab を生成します。
作成するもの
- ページ。
ui/<slug>-directions.htmlとui/src/<slug>-directions/。バックエンドを使わない、2つ目の Vite エントリーです。すべての状態は URL に保持されます(?d=&s=&theme=&chrome=&anim=、提案パレットの場合はproposal=1も追加)。レジストリモジュールがデザイン案 ID、数字キー、ラベル、画面、ランディングビュー、ストーリー ID の唯一の情報源です。ツールバー、キーボード、概要ボード、キャプチャスクリプトは実行時にこのレジストリを読み込み、add-directionはストーリーのデザイン案ごとのエクスポートとの整合性を保ちます。つまり、デザイン案はレジストリのエントリー1つとディレクトリ1つで構成されます。 - ツールバー。 1行目はデザイン案の行です。番号付きのデザイン案の後に
0.Todayを置き、セグメントコントロールとして表示します。Theme と Animation は右寄せにします。2行目は画面の行です。Overview と、画面ごとのタブを1つずつ配置します。2行目が作成されるのは、画面が複数ある状態で lab をスキャフォールドした場合のみです(画面が1つの lab に後から画面を追加する場合は、2行目を手作業で追加する必要があります。references/lab-anatomy.mdのセクション8を参照)。画面が1つの場合は、キーボード操作の凡例を1行目に配置します。ヘッダーにはほかに何も置きません。 - Today。 必ず存在し、常に
0.Todayとします。アダプターと fetch スタブを使い、lab のフィクスチャ上にリリース済みコンポーネントをマウントします。各デザイン案を評価する際の基準となるため、描き直すことはありません。 - デザイン案。 2つまたは3つを番号付きで用意します。それぞれが独自のスコープ付き
tokens.cssを持つ、自己完結したキットのディレクトリです。すべてのデザイン案に V1 MVP のモーションブロックをそのまま含め、それを検証するテストも用意します。これにより、どの lab でもホバー時の動作が同じになります。モーションに触れる前に、references/motion-spec.mdを読んでください。 - ディレクトリエントリー。
ui/storybook/stories/design-proposals/に、固定 ID を持つストーリーファイルを1つ作成し、提案としてカタログに登録します。design-proposals Storybook はデザインシステムの公式ディレクトリになりつつあります。lab は最初のコミットからそこに存在します。
リポジトリのチェックで強制され、レビュアーも期待する厳格なルールがあります。コミットするものにコードコメントを含めないこと、lab 内に600行以上のファイルを作らないこと(check は600行で拒否します)、package.json スクリプトを追加しないこと、ロックファイルを変更しないこと、スクリーンショットや生成されたカタログファイルをリポジトリに追加しないことです。
始める前に
リポジトリのルートで、自分のブランチ(origin/master から作成する claude/<slug>-directions)を使って作業します。ui/node_modules/.bin/vite が存在することを確認してください。存在しない場合は pnpm install --frozen-lockfile を実行します。次に、ジェネレーター独自のテストを実行します。
node --test .agents/skills/directions-lab/scripts/scaffold.test.mjs
ここで失敗する場合は、通常、テンプレートかモーションアセットが先例(ui/src/artifact-directions/directions/d5-v1-mvp/tokens.css)から乖離しています。また、2つのケースでは実際の機能マップとカタログスクリプトも読み込むため、機能マップの行やカタログメッセージが変更されている場合も、ここで検出されます。スキャフォールドを作成する前にジェネレーターを修正してください。古いテンプレートを使って作成した lab は、後になって描画の問題に見える形で失敗します。
要件を読み、対象の根拠を確認する
Tonio が書いた内容から4つの項目を抽出します。対象(slug とタイトル)、表示される場所(場所ごとに1つの画面)、指定されたデザイン案の数または名前、フラグ名やコンポーネント名です。質問する前に、まずコードを確認してください。
rg -l "<Subject>" ui/src/components ui/src/pages
rg -n "<subject word>" maps/feature-map/*.md
最初の grep では、コンポーネントファイル、フラグのフック(use<Feature>Enabled)、および useQuery/queryFn から ui/src/api/* へたどることで、Today が応答する必要のある /api/ ルートがわかります。2つ目では、ストーリーが参照する機能 ID がわかります。この根拠の確認により、画面に関する質問を一般論ではなく、具体的な内容にできます。抽出と導出の表全体については、references/questions-and-defaults.md を参照してください。
1 回の呼び出しで質問する
AskUserQuestion の呼び出しは最大 2 問とし、ブリーフですでに回答されている質問は省略します。
- 方向性はいくつですか? 選択肢は
2と3です。質問では、名前のない方向性を 3 つ選ぶと、後で名前を変更できるよう、1.Refine(トークンと間隔を調整し、構造は維持)、2.Rework(新しいコンポーネントを使い、レイアウトは維持)、3.Rethink(新しいレイアウト)として準備し、2 つ選ぶと1.Refineと2.Rethinkとして準備することを伝えます。ブリーフに数が記載されている場合や、方向性の名前が挙げられている場合は省略します。 - どのサーフェスを対象にしますか? grep で見つかった使用箇所と「1 か所のみ」から複数選択します。2 つ以上選択すると、サーフェスの行が生成されます。ブリーフに場所が記載されている場合は省略します。
テーマ、アニメーション、Today、ポート、スラッグ、ランディングビューについては質問しないでください。これらはスキルで固定されています。質問できない場合(ヘッドレス実行)は、ほかのことを始める前に次のように記載してから続行します。「質問できないため、方向性を 3 つ、サーフェスを 1 つ()に設定します。後から scaffold.mjs add-direction で変更できます。」
導出した内容を伝えてから、スキャフォールドを生成する
ジェネレーターを実行する前に、導出した値をすべて返信で明示します。スラッグとタイトル、各サーフェスを id:Label:width@nav の形式で記載し、width の根拠となる行も示します。方向性の数と名前、グループ、機能とその feature-map の行(または [] と例外を示す文)、フラグのフック、Today が必要とする /api/ パスも含めます。スラッグや機能の誤りはここなら簡単に見つけられますが、ファイルを作成した後では修正に手間がかかります。その後:
node .agents/skills/directions-lab/scripts/scaffold.mjs new \
--slug composer --title "Composer" \
--surfaces thread:Task-thread:960@tasks,panel:Right-panel:434@tasks \
--directions 3 --dry-run
プラン(パス、ポート、セル、ストーリー)を確認し、--dry-run を外して実行します。new はすべてをメモリ上でレンダリングし、既存のパスがあれば処理を拒否します。lab、html エントリ、Vite 設定、ストーリーファイル、2 つの .claude/launch.json エントリ、1 行の .gitignore を書き込み、その後、Storybook カタログチェック、lab 自身の Vitest ファイル、Vite ビルドを検証します。失敗した場合は、書き込んだものを削除して共有ファイル 2 つを復元するため、途中まで書き込まれた lab によってリポジトリ全体の pnpm test や tsc -b が失敗することはありません(ui/vitest.config.ts には include フィルターがなく、ui/tsconfig.json は src 全体を含みます)。返信には --json の出力を引用してください。
--surfaces は場所ごとに id:Label:width@nav を指定します。nav はシェルでハイライトするサイドバー項目(tasks、artifacts、other)で、width はその場所におけるプロダクト独自の定数です(references/questions-and-defaults.md を参照)。使用するフラグは次のとおりです。明示された名前には --names a,b,c、--group Components|Pages|Layouts|Patterns(grep のヒットが ui/src/components の場合は Components)、maps/feature-map に照らして検証される --capabilities area/key,...(省略する場合は [] と例外を示す文を使用)、--company name:PREFIX(既定値は acmehats:ACM)、--landing auto|all|today|<id>、--ports dev,preview(ジェネレーターが空いているポートを選択)、失敗したスキャフォールドを調査するための --keep-on-failure です。
表示して確認する
ジェネレーターが追加した dev エントリを起動し、preview_start {name: "<slug>-directions-dev"} を実行して、3 つの URL を開きます。/(ランディング)、/?d=today&s=<first surface>、/?d=<first direction id>&s=<first surface>(方向性が未命名の場合は d1-refine)です。document.documentElement.dataset.labAnim === "1" であることを確認し、モーションの標本にカーソルを合わせて、前面がせり上がり、2 ページがめくれるのを見ます。a を押して再びカーソルを合わせ、塗りつぶしだけが変わることを確認します。コンソールで [<slug>-directions] unhandled の行を確認してください。各行が Today に必要となるルートです。概要ボードとキャプチャスクリプトでは、この動きは表示されません(iframe はポインター入力を受けず、静止画ではモーションの低減が指定され、--hover が記録するのはホバー中の 1 フレームであって遷移ではありません)。そのため、遷移はこの方法でのみ検証できます。
骨組みをコミットしてから描画する
まず、変更を加えていない骨組みを feat(ui): scaffold the <title> directions lab としてコミットします。レビュー担当者は、配線に埋もれたものではなく、描画部分だけの差分を確認できます。次の順番で作業します。各フェーズの完了条件は references/drawing-phases.md に記載されています。
- フレーム。 各
data-lab-stub="frame-<surface>"領域を、その場所を囲む製品のクロームに置き換えます。製品のクラス文字列をコピーし、レジストリの幅を固定し、プレゼンテーション用プリミティブを再利用して、内部でスクロールしないようにします。先例となるフレーム(ThreadFrame、PanelFrame、GalleryFrame、AppShell)を参考にしてください。 - フィクスチャとToday。
kit.tsのサーフェスごとのデータを、それぞれの場所が受け取る props の型に合わせて再定義し、fixtures.tsを埋めます。adapters.ts経由で、提供済みのコンポーネントをdirections/today/<Pascal>Body.tsx(サーフェス ID の PascalCase。たとえばthreadならThreadBody.tsx)にマウントし、api-routes.tsのregisterFeatureRoutes()内に、コンポーネントが取得するルートだけを登録します。同じデータで製品と一致し、実際のコンポーネントを使ったテストが通れば、Today は完了です。 - 方向性。 1 つずつ作業します。モーションの見本を描画に置き換え、フック名(すべての処理分岐で
data-front、インラインの基準角度とともにdata-rotateおよびdata-spread)を維持し、その方向性のtokens.css(ライトテーマのベースと.darkのオーバーライド)にすべての生の値を記述します。モーションブロックには手を加えないでください。各フェーズの後にscaffold.mjs check --slug <slug>を実行します。
フェーズ 2 ではスロット props の形が変わり、すべての kit がその型に従うため、フェーズ 2 はフェーズ 3 より先に行います。
キャプチャ
node ui/src/<slug>-directions/shot.cjs --port <dev> --d all --out <scratch dir>
キャプチャは 1440×900、DPR 2、両方のテーマでの静止状態です。PNG は PR に添付し、リポジトリには追加しないでください。--hover を指定すると、モーションを許可した別のブラウザーコンテキストから、方向性ごとに静止状態とホバー状態のペアを追加します。モーションそのものを評価できるのは、Animation トグルをオンにしたブラウザーペインだけです。
引き継ぎ
node .agents/skills/directions-lab/scripts/scaffold.mjs check --slug <slug> --strict --run
--strict は data-lab-stub マーカーが残っていると処理を拒否します。--run はラボのテスト、カタログチェック、トークンゲート、ラボの Vite ビルド、cd ui && pnpm typecheck を実行し、最初に失敗した時点で停止します。また、手動で行う項目(pnpm build-storybook とリポジトリ全体の型チェック)を Not run: 行に記載した ## Verification ブロックを出力します。--json は同じ結果をデータとして返し、該当項目は notRun に含まれます。.github/PULL_REQUEST_TEMPLATE.md のすべてのセクションを埋め、リンクするイシューのパス B に 3 つの機能リクエスト用ラベルを入力し、ストーリー ID、起動エントリー、デプロイした場合は Vercel エイリアスも記載して PR を作成します。DESIGN.md のディレクトリー行は、PR の本文にテキストとして記載してください。ラボの PR から適用してはいけません。
スキル自体が差分に含まれる場合は、強制追加してください。/.agents/ は Git の無視対象であり、リポジトリで追跡されているスキルは git add -f で追加されています。
Storybook とデザインディレクトリ
new は ui/storybook/stories/design-proposals/<slug>-directions.stories.tsx
を作成します。メタ ID は design-<slug>-directions、タイトルは Design proposals/<Group>/<Title> directions/Compare で、リテラルの parameters.paperclip ブロック(status: "proposed"、home: "design-proposals"、implementation: "prototype"、
boundary: "fixtures"、capabilities、exception、notes)と、Compare、
Today、各方向につき 1 つのストーリー、TodayProductionPalette が含まれます
(デコレーターは iframe 全体に提案パレットのテーマを適用しますが、このストーリーはそれを無効にし、出荷済みとして Today を表示できるようにします)。ページ自体はデフォルトで本番パレットを表示します。
?proposal=1 を指定すると、エントリーと並べて比較できるよう、ページを提案テーマでラップします。
カタログスクリプトは Storybook の起動時、cd ui && pnpm typecheck の実行時、および CI でこれらすべてを検証します。
各方向が進むライフサイクルと、各段階で手動編集が必要な箇所については
references/lifecycle.md に記載されています。proposed(new が書き込む状態)、adopted(実験的な設定の背後にあるプロダクトコードと、機能ホームのストーリー)、current(フラグを削除した状態)、historical(replacement を指定して廃止し、ID を維持したまま提案フォルダーから移動した状態)です。現在、カタログは提案フォルダー内のすべてのエントリーを proposed に保つよう強制しています。ディレクトリに current のエントリーを含められるようにするガバナンス変更は、すぐに適用できる差分として references/canonical-directory.md にまとめられています。Tonio が承諾した場合に限り、単独の PR として一度だけ提案してください。
後から依頼された場合
- 方向を追加する:
scaffold.mjs add-direction --slug <slug> --name <Name>(次の数字、レジストリエントリー、モーションブロックと見本を含むキットディレクトリ、ストーリーのD<N>エクスポートを追加し、その後checkを実行します。失敗した場合はロールバックします)。 ツールバーの凡例は実行時にレジストリに従います。ジェネレーターは--force-countを指定しない限り 4 つ目の方向の追加を拒否します。このオプションを指定すると、レジストリにallowMoreも記録されます。ストーリーの説明にある「1–N」の文だけは手動で更新する必要があります。フェーズ 2 でkit.tsのスロットプロパティを再型付けした後は、生成したキットが新しいプロパティに適合しないため、add-directionは追加を拒否し、手動で行う手順を表示します。 - ラボを一覧表示する:
scaffold.mjs list。 - 方向の名前変更、サーフェスの追加、またはライフサイクルに沿った方向の移動:
references/lab-anatomy.mdのセクション 5 と 8、およびreferences/lifecycle.mdに従って手動で行います。 - 公開する:
<SLUG>_DIRECTIONS_OUT_DIR=<dir>/paperclip-<slug>-directionsを指定してビルドし、出力からsw.jsを削除します。親ディレクトリからvercel deploy <that dir> --prod --yesを実行します。ベース名がプロジェクト名になり、エイリアスが公開 URL になります。 詳細はreferences/today-fixtures-and-build.mdのセクション 11 を参照してください。
してはいけないこと
uiの Vitest スイートを 2 つ同時に実行しないでください。ラボのファイルだけを実行してください。- 8 セルを超える開発サーバーから
d=all&s=boardにアクセスしないでください。ボード全体を表示するには、静的起動エントリー(<slug>-directions)を使用してください。 - アーティファクトラボの
html:not(.dark)トークンの慣用表現をコピーしないでください。新しいラボでは、ライトモードの値をベースブロックに、ダークモードの値を.dark [data-direction=…]の下に記述します。 - ラボのモーションブロックを編集しないでください。上昇量や扇形の変更は Tonio が決定します。
- PR に含めるものに、コメント、
package.jsonのスクリプト、ロックファイルの変更、PAP ID、localhost の URL を追加しないでください。
スキルのメンテナンス
ジェネレーターのテンプレートは、assets/PRECEDENT に記録されたコミット時点の先例をもとに作成されました。scripts/scaffold.test.mjs は生成される構造を固定し、置換後のモーションアセットが先例のブロックと引き続き一致することを検証します。先例が変更された場合は、テンプレートを作り直し、固定バージョンを更新してください。テンプレートの規約とコンテキストオブジェクトについては、references/generator.md で説明しています。
参考資料
| ファイル | 読むタイミング |
|---|---|
references/questions-and-defaults.md | 質問する前。導出テーブル、フラグ行としての評価プロンプト |
references/lab-anatomy.md | フレームを描画するとき、またはツールバー、状態、ボードを変更するとき |
references/today-fixtures-and-build.md | Today のマウント、フェッチスタブ、ビルド、キャプチャ、デプロイ時 |
references/motion-spec.md | ホバーアニメーションに関する作業。方向ごとのチェックリスト |
references/drawing-phases.md | 足場の作成後、フェーズごとに |
references/design-proposals-storybook.md | ストーリーファイル、カタログゲート、テーマ |
references/lifecycle.md | 方針の採用、リリース、または廃止時 |
references/canonical-directory.md | Tonio がガバナンス PR を承認した場合のみ |
references/repo-gates.md | PR の前 |
references/generator.md | ジェネレーターを変更するとき |