GitHub Issueの確認事項(最後のコメント・descriptionの両方)を、コードベース・ドキュメント・そこから参照されている外部リンク(仕様書・ライブラリ公式ドキュメント等)まで調査し、根拠に基づいた回答をコメントに追記するスキル。調査しても事実で決まらず人間の意思決定が必要な項目は、固定セクションで明示して後続のトリアージへ引き渡す。
resolve-pencil-conflict
gitコンフリクト状態になった.penファイル(Pencilで作成されたデザインファイル)を、Pencil CLI(`pencil`コマンド)とgitだけで解消するスキル。
.penは暗号化バイナリでテキストマージが不可能なため、コンフリクトマーカーの手編集や`git mergetool`は絶対に使わず、「片側採用 → もう一方の変更をPencilで再適用」のフローで解消する。
ユーザーが.penファイルのコンフリクト解消、rebase/merge中に`UU`/`AA`状態になった.penの解消、テキストマージで破損した.penの復旧などを依頼した場合に必ずこのスキルを使用する。
通常の.penの編集・新規作成は`edit-pencil-design`スキル、PR全体のコンフリクト解消フロー(rebase起点・force-push)は`resolve-pr-conflict`スキルの担当。
含まれるファイル(1)
- SKILL.md12.6 KB
SKILL.md(原文)
インストールする前に、エージェントに与えられる指示の中身を確認できます。
Resolve Pencil Conflict
gitコンフリクト状態になった .pen デザインファイルを「片側採用 → もう一方の変更をPencilで再適用」のフローで解消するスキル。
位置づけ(関連スキルとの分担)
| スキル | 担当 |
|---|---|
| 本スキル | .pen ファイル単体のgitコンフリクト解消・破損復旧 |
edit-pencil-design | .pen の通常の編集・新規作成(本スキルの再適用ステップで利用する) |
resolve-pr-conflict | PR全体のコンフリクト解消フロー(rebase・force-push)。その過程で .pen のコンフリクトに遭遇した場合に本スキルへ委譲される |
重要な前提
- テキストマージは絶対禁止:
.penは暗号化バイナリのため、コンフリクトマーカー(<<<<<<<等)の手編集やgit mergetoolによるテキストマージはファイルを破損させ、開けなくする - 両側の変更を1ファイルに機械的にマージする手段は存在しない: 解消は必ず「どちらか一方のバージョンをそのまま採用し、採用しなかった側の変更内容をPencilの編集として再適用する」方針で行う
.penはRead/Grepでは読めない。中身の確認はすべてpencil interactive経由(executeのGetによるツリーダンプ、executeのTakeScreenshot/Exportによる画像)で行う。CLI 0.3.5 のシェル内ツールはbrowser/execute/get_app_state/get_style/read_skillの5つだけで、Nodeの読み書きも画像出力もexecuteに一本化されている(旧get_screenshot/export_nodes/get_editor_state/batch_get/batch_designは廃止)
前提条件の確認
pencil version— pen.dev CLIが使えない場合は本スキルのフローを実行できないため、無理に解消せずgit rebase --abort/git merge --abortで中断し、セットアップ手順(npm install -g @pen.dev/cli、Node.js 18以上必要。0.3.5 未満では以降の手順が動かないためバージョンも確認する)を報告に含めて終了するpencil status— 未認証の場合も同様に中断し、認証手順(pencil login、またはPEN_CLI_KEY環境変数の設定)を報告に含めて終了するgit status --short— 対象の.penが実際にコンフリクト状態(UU/AA/UD/DU)であることを確認する
解消手順
ステップ1: コンフリクト状態の確認
git status --short # UU = 両側変更、AA = 両側追加、UD/DU = 片側削除
UD/DU(片側がファイルを削除している)の場合は、ファイルを残すべきか自体が仕様判断になるため、無理に解消せずgit rebase --abort/git merge --abortで中断し、どちら側が削除しているか・双方のブランチと該当コミットを含めて中断理由を報告して終了する(呼び出し元・人間がその報告を基に判断する)
ステップ2: 作業ディレクトリの確保と3バージョンの取り出し
中間ファイルの保存先は固定パスにせず、実行ごとに一意なディレクトリを確保する(同時実行での上書き衝突を防ぎ、trap で途中失敗時も自動後始末される)。
WORK_DIR="$(mktemp -d -t pencil-conflict-XXXXXX)"
trap 'rm -rf "$WORK_DIR"' EXIT
index の stage から共通祖先・両側のバージョンを書き出す。
git show :1:path/to/design.pen > "${WORK_DIR}/base.pen" 2>/dev/null \
|| rm -f "${WORK_DIR}/base.pen" # 共通祖先(AA コンフリクトでは stage :1 が無いため base.pen を作らない)
git show :2:path/to/design.pen > "${WORK_DIR}/ours.pen" # ours 側
git show :3:path/to/design.pen > "${WORK_DIR}/theirs.pen" # theirs 側
ours/theirs の意味の反転に注意: git merge 中は ours = 現在のブランチ / theirs = マージ対象ブランチだが、git rebase 中は逆転し、ours(:2: / --ours)= rebase先のターゲットブランチ側、theirs(:3: / --theirs)= 自分のブランチのコミット側になる。どちらが「自分のデザイン変更」かを取り違えると、採用と再適用が逆になり変更を取りこぼす。
ステップ3: 各バージョンのNodeツリーを取得し、両側の変更内容を把握する
for v in base ours theirs; do
[ "$v" = "base" ] && [ ! -s "${WORK_DIR}/base.pen" ] && continue # AA: 共通祖先なしはスキップ
pencil interactive -i "${WORK_DIR}/${v}.pen" -o "${WORK_DIR}/${v}.pen" 2>/dev/null <<'EOF' | sed -n 's/^TREE //p' > "${WORK_DIR}/${v}.json"
execute({ input: 'Print("TREE", JSON.stringify(Get((n,c)=>({d:c.depth,id:n.id,name:n.name,type:n.type,x:n.x,y:n.y,w:c.bounds.width,h:c.bounds.height,fill:n.fill,content:n.content}))))' })
exit()
EOF
done
数値フォーマットの揺れ(例: 13.995000000000001 と 13.995)を差分と誤認しないよう、jq で正規化してから diff する。
for v in base ours theirs; do
[ -f "${WORK_DIR}/${v}.json" ] || continue # AA: base.json は生成されないためスキップ
jq -S 'walk(if type == "number" then tonumber|tostring|tonumber else . end)' \
"${WORK_DIR}/${v}.json" > "${WORK_DIR}/${v}.norm.json"
done
if [ -f "${WORK_DIR}/base.norm.json" ]; then
diff "${WORK_DIR}/base.norm.json" "${WORK_DIR}/ours.norm.json" # ours 側が変えたNode
diff "${WORK_DIR}/base.norm.json" "${WORK_DIR}/theirs.norm.json" # theirs 側が変えたNode
else
diff "${WORK_DIR}/ours.norm.json" "${WORK_DIR}/theirs.norm.json" # AA: 共通祖先が無いため両側を直接比較する
fi
ツリーダンプは [{"d":0,"id":"...",...}, ...] の1行JSONとして返る。行頭マーカー TREE を付けて sed で抜くのは、[INFO] Starting pen.dev (headless)... のような起動ログも [ で始まるため。属性を増やしたいときは visitor の返すオブジェクトに足す。
必要に応じて両側の見た目も確認する。execute の TakeScreenshot(["document"]) は base64 を返すだけなのでデコードして保存し(${WORK_DIR} 配下でよい)、複数Nodeをファイルとして残すなら Export(nodeIds, "png", outputDir) を使う("document" は Export では使えない)。
pencil interactive -i "${WORK_DIR}/ours.pen" -o "${WORK_DIR}/ours.pen" <<'EOF' > "${WORK_DIR}/ours-shot.txt"
execute({ input: 'TakeScreenshot(["document"])' })
exit()
EOF
grep -o '"image": "[^"]*"' "${WORK_DIR}/ours-shot.txt" | sed 's/.*: "//; s/"$//' | base64 -d > "${WORK_DIR}/ours.png"
ステップ4: ベースの選択と採用
Node差分が大きい・プロンプトでの再現が難しい側をベースとして採用する(目安: 変更Node数が多い側。同程度なら自分のデザイン変更側をベースにし、相手側の変更を再適用する方が意図の取りこぼしが少ない)。
git checkout --ours -- path/to/design.pen # または --theirs(ステップ2の反転注意を再確認)
git add path/to/design.pen
ステップ5: 採用しなかった側の変更を再適用する
ステップ3で特定した「採用しなかった側のNode差分」を具体的な編集指示に落とし込み、edit-pencil-design スキルの手順(エージェントモード --prompt、または heredoc 安全規則に従った execute の Insert / Update / Delete + save())で再適用する。編集前スナップショットは採用したベースのツリーになる。
ステップ6: 両側の変更が揃ったことの検証とスクリーンショット
再適用後のツリーダンプ(ステップ3と同じ execute の Print("TREE", ...))に「ours側の変更Node」「theirs側の変更Node」の両方が反映されていることをNodeツリー差分で確認し、edit-pencil-design の手順どおり影響Nodeのスクリーンショットを .pen と同階層の snapshots/ に残す。検証の基準は、base があるケースはステップ3の base.norm.json との差分、base が無い(AA)ケースは ours.norm.json と theirs.norm.json の直接比較で洗い出した差分が、両方反映されているか。
ステップ7: git操作の続行
git add path/to/design.pen 済みであることを確認して git rebase --continue / git merge --continue で続行する。
両側の変更意図が両立できない(同じNodeを異なる方針で変更している等)と判明した場合は、無理に解消せず git rebase --abort / git merge --abort で中断し、両側のスクリーンショットのパスと両立できない理由(対象Node・双方の変更内容)を報告して終了する(呼び出し元・人間がその報告を基に判断する)。
予防策
.gitattributes に .pen をバイナリとして明示しておくと、gitがテキストマージを試みてコンフリクトマーカーを埋め込みファイルを破損させる事故を防げる(コンフリクト自体は発生するが、常に本スキルのフローで安全に解消できる):
*.pen binary
リポジトリに .gitattributes の指定が無い場合は、コンフリクト解消のついでに追加を提案する。
トラブルシューティング
- コンフリクトマーカーの混入等で
.penが破損して開けない: テキストマージを実行してしまった典型的な事故。破損ファイルの修復は不可能なので、git checkout --ours -- <path>/--theirsで正常な側のバージョンに戻す(コンフリクト状態からやり直したい場合はgit checkout -m -- <path>で3-way状態を復元できる)。その後、本スキルの手順で解消し直し、.gitattributesへの*.pen binary追加を提案する AA(両側追加)コンフリクトでgit show :1:が失敗する: 共通祖先が存在しないため想定内。ステップ2〜3のガードにより自動的に base 無し(ours/theirs 直接比較)として扱われるため、そのままステップ4以降を進めてよい- どちらの変更か判別できない:
git log --oneline -- <path>で両ブランチの該当コミットとメッセージを確認し、変更の出所を特定する。それでも判断できなければ無理に解消せずgit rebase --abort/git merge --abortで中断し、確認した事実(両側のコミット・スクリーンショット)を添えて報告して終了する pencilコマンドが使えない環境: 本スキルのフローは実行不可。「前提条件の確認」どおりgit rebase --abort/git merge --abortで中断し、セットアップと認証を案内するUnknown tool: get_screenshot/export_nodes/get_editor_state/batch_design: 廃止済み。ツリー取得はexecuteのGet、画像はexecuteのTakeScreenshot/Export、再適用はexecuteの変更系関数に読み替える(pencil versionが 0.3.5 未満なら入れ直す)
実行結果の報告
- コンフリクトの種別(
UU/AA/UD・DU)と対象.penの絶対パス - 採用した側(ours / theirs とそれがどのブランチの変更か)と選択理由
- 再適用した変更内容(Node IDと概要)
- 検証結果(両側の変更が揃っていることの確認方法)と出力したスクリーンショットの絶対パス
- 実行したgit操作(
--continueまで完了したか、中断したならその理由)
レビュー
まだレビューはありません。使ってみた感想をお寄せください。
同じリポジトリのスキル
概要と使いどころ
Write the merged Pencil design reference back into a UI implementation Issue's description. Takes the Issue number as argument, resolves the merged design PR on the `cc-ui-design-<Issue number>` branch, collects the `.pen` and snapshot paths it added, and appends (or replaces) the `## UIデザイン` section at the end of the Issue body using a lost-update-safe edit.
依頼された内容(自然言語の説明、または既存のIssue番号)を要件とTODOに分解し、タスクごとにGitHub Issueを作成するスキル。タスクの整理・分解、複数Issueの一括作成、依存関係の明示が必要な場合に使用する。「この機能をIssueに分けて」「タスクを洗い出してIssueにして」「PRDのIssue #123 を分解して」といったリクエストで発動する。
claude-task-worker のカスタムワーカー(`workerFiles` に登録する TS 定義)を、`AskUserQuestion` で要件を全項目確定させてから生成し、`claude-task-worker list-workers` でロード検証までするスキル。「カスタムワーカーを作って」「独自のワーカーを追加したい」「新しいラベルで動くワーカーを定義したい」といったリクエストで使用する。
claude-task-workerプラグインのバージョンをインクリメントし、commit-pushでコミット・プッシュしたうえでPRを作成する。引数で `major` / `minor` / `patch` を受け取り、対応する部分をインクリメントする(省略時は `patch`)。「バージョンを上げて」「バージョンアップ」「bump version」「メジャーバージョンを上げて」などのリクエストで使用する。
指定されたPR番号のDependabot PRを確認し、依存ライブラリのバージョンアップ内容をCHANGELOGとcontext7から取得して、コード修正が必要かを判定します。修正が必要な場合は修正を行い、pushまで実施します。