| name | update-issue |
| description | Update an existing GitHub Issue's description based on the issue number. Reads all issue comments and reflects any items not yet captured in the description. After refreshing the description, reviews it for remaining ambiguities or unclear requirements and posts any open questions as a follow-up 確認事項 comment. |
| argument-hint | [Issue番号] |
| hooks | {"Stop":[{"matcher":"","hooks":[{"type":"command","command":"node \"${CLAUDE_PLUGIN_ROOT}/scripts/stop-servers.mjs\""}]}]} |
Update Issue
引数で受け取ったIssue番号をもとに、Issueのコメントを全件読み取って文脈を把握し、まだdescriptionに反映されていない事項を反映するスキル。Instructionsに従い、Issueの内容とコメントの確認、コードの分析、descriptionの更新を行う。
責務の分担: 本スキルは「既存Issueとコメント取得・未反映事項の抽出・コード分析・コメント/分析で判明した依存関係の既存Issueへの relationships 反映・既存『依頼内容』ブロックが保持されたことの事後確認」までを担い、「本文整形・投稿前チェック・既存変更ログの verbatim 再掲・既存依頼内容ブロックの verbatim 再掲・gh issue edit 実行」は post-issue-body スキルへ委譲する。本文テンプレート・変更ログ追記ルール・投稿前チェックリスト・heredoc 投稿コマンドはすべて post-issue-body 側に集約されているため、本スキル内では再記述しない。
「依頼内容」の扱い: 本スキルの役割は「コメントから拾った未反映事項の反映」であり、依頼内容ブロック(<details><summary>依頼内容</summary>)を新規作成しない。既存bodyを丸ごと依頼内容として複写すると、更新後 description で元本文と反映後本文が二重に残るため。「人が最初に書いた原文」を残す用途は create-issue-from-issue-number の責務であり、本スキルはそこに触れない。ただし、すでに依頼内容ブロックが存在する Issue(旧フォーマットの裸の ## 依頼内容 見出しも含む)に対しては、その中身を verbatim で再掲して失わないよう引き継ぐ(旧フォーマットは post-issue-body 側が折りたたみブロックへ詰め替える)。コメントで依頼内容そのものの書き換え要望が来ても依頼内容ブロックは書き換えず、コメント由来の変更は 概要 要件 実装プラン 側で反映する。
Instructions
実行モードの制約
本スキル固有のリスク: 本スキルは claude-task-worker の cc-update-issue ラベルをトリガーに自動起動され、ワーカーはスキルプロセスの同期完了を根拠に cc-update-issue を外す。処理が未完のままターンを終えると、後続の answer-issue-questions / triage-created-issue / exec-issue などが古い description を前提に起動されてしまう。
実行ステップ
1. 作業ディレクトリの確認とベースブランチ(分析のターゲットブランチ)の確定
pwd で現在地を確認する。.claude/worktrees/ 配下にいればそのworktree内で、それ以外(リポジトリのルート等)ではその場で作業する。worktreeを新たに作成しないこと。
リモート同期は以下を試行し、失敗しても中断せずスキップして続行する(本スキルはコードを変更しないため)。git rebase や git pull は実行しない(未コミット変更や conflict による中断を避けるため)。
続いて分析の基準となるベースブランチ(BASE_BRANCH)を確定する。サブIssue(parent を持つIssue)の作業ブランチは cc-epic-<parent番号> から派生し、実装PRもそこへ向くため、デフォルトブランチではなく epic ブランチが分析のターゲットになる。デフォルトブランチをターゲットと見なすと、epic ブランチへマージ済みの兄弟サブIssueの変更が「未反映」に見え、「Epic PR が未マージだがどう扱うか」といった本来不要な検討事項・確認事項が混入する(exec-issue / create-pr のベースブランチ決定と同じ確定的導出を用いる)。
git fetch --prune || true
BASE_BRANCH=""
PARENT=$(gh issue view "<Issue番号>" --json parent --jq '.parent.number // empty') || PARENT="__unresolved__"
if [ "${PARENT}" != "__unresolved__" ] && [ -n "${PARENT}" ] \
&& git rev-parse --verify --quiet "refs/remotes/origin/cc-epic-${PARENT}" >/dev/null; then
BASE_BRANCH="cc-epic-${PARENT}"
fi
if [ -z "${BASE_BRANCH}" ]; then
CURRENT=$(git rev-parse --abbrev-ref HEAD)
UPSTREAM=$(git rev-parse --abbrev-ref --symbolic-full-name '@{upstream}' 2>/dev/null || true)
UPSTREAM=${UPSTREAM#origin/}
if [ -n "${UPSTREAM}" ] && [ "${UPSTREAM}" != "${CURRENT}" ] \
&& git rev-parse --verify --quiet "refs/remotes/origin/${UPSTREAM}" >/dev/null; then
BASE_BRANCH="${UPSTREAM}"
fi
fi
if [ -z "${BASE_BRANCH}" ]; then
BASE_BRANCH=$(git symbolic-ref --short refs/remotes/origin/HEAD | sed 's@^origin/@@')
fi
echo "BASE_BRANCH=${BASE_BRANCH} PARENT=${PARENT}"
以降のすべてのステップ(ステップ3の未反映事項の抽出・ステップ4のコード分析・ステップ4.5の確認事項の洗い出し)は BASE_BRANCH を分析のターゲットブランチとして扱う。
- 現在の作業ディレクトリのコード状態(=
BASE_BRANCH 由来)が分析対象。「この変更はデフォルトブランチにまだ入っていない」ことを問題として扱わない
BASE_BRANCH が cc-epic-<N> の場合、Epic PR(cc-epic-<N> → デフォルトブランチ)が未マージであることは Epic フローの正常状態。これを根拠とした確認事項・リスク・検討事項(「先に Epic PR をマージすべきか」「マージされていないがどうするか」等)を一切生成しない
- epic ブランチへマージ済みの兄弟サブIssueの変更は「既に存在するコード」として扱い、実装プランで再実装しない
gh issue view --json parent に失敗した場合(PARENT=__unresolved__)は parent 不明として続行するが、未マージPRを根拠とした確認事項は生成しない(epic フローの正常状態を誤って確認事項化しないための安全側の倒し方)。その旨は最終報告に1行残す
2. 既存Issueの取得
引数から先頭のIssue番号を取り出し、そのIssueを取得して現在の内容を確認する。
gh issue view <Issue番号> --json number,title,state,labels,body,url
なお、変更ログの verbatim 再掲用の既存本文取得は post-issue-body が mode=edit で再度行うため、本ステップの body は分析用途(差分検出)で使い、post-issue-body へは Issue 番号だけを伝えればよい。
コメントの取得(必須)
コメント全件が更新の唯一の入力になるため、必ず併せて取得する。
gh issue view <Issue番号> --comments
本文・コメントに画像URLがある場合、gh-asset でダウンロードして内容を読む。テキストだけでは伝わらない仕様(UIの見た目・エラー画面・図など)がdescription更新の判断に必要なことがあるため、URLを見て終わりにせず、ダウンロードした画像を実際に Read で確認する。
gh-asset download <asset_id> ~/Downloads/
参考: https://github.com/YuitoSato/gh-asset
2.5. 既存「依頼内容」ブロックの検出(新規作成はしない)
ステップ2で取得した body に、既に依頼内容ブロックがあるかどうかだけを確認する。ある場合はその存在と中身を記録し、無い場合は「無し」として扱う。本スキルは依頼内容ブロックを新規作成しない。
- 既存bodyに
<details><summary>依頼内容</summary> ブロックが存在する場合(create-issue-from-issue-number が書き込んだもの)
- verbatim 再掲は
post-issue-body 側が担当する(args.sections.依頼内容 を未指定にして呼べば、mode=edit で既存bodyの中身が verbatim 再掲される規約)。したがって本スキルからは 依頼内容 を渡さない。
- ステップ5.5の事後検証用に、切り出した中身(
<summary>依頼内容</summary> の閉じタグ直後から </details> の直前まで、タグは含めない。先頭・末尾の空行1つは正規化してよい)を「期待値」として保持しておく。
- 既存bodyに旧フォーマットの
## 依頼内容 見出しがある場合(本フォーマット移行前の Issue)
- 同じく本スキルからは
依頼内容 を渡さない(post-issue-body 側が旧フォーマットを検出して折りたたみブロックへ詰め替える)。ステップ5.5の期待値は、見出し直後から次の ## 見出し(スペースが続く見出し記法)またはEOF直前までの中身を切り出して保持する。
- どちらも無い場合 — 何もしない。依頼内容ブロックは無いままにする(更新後 description は
## 概要 から始まる基本の6セクション構成になる)。
完了条件: 既存の折りたたみブロック(新形式)または旧形式 ## 依頼内容 見出しが存在する場合は、その内容と <details><summary>依頼内容</summary> 形式への変換が保持されていることを確認する。どちらも存在しない場合は、依頼内容ブロックが無いこと(description が ## 概要 から始まる基本6セクション構成であること)を確認する。
3. タスクの分析
ステップ2で取得したコメント全件を入力として扱う。各コメントを時系列で読み、確認事項への回答・仕様変更・追加要望などを洗い出したうえで、既存descriptionと突き合わせ、まだ反映されていない事項を今回の更新対象とする。
- 既にdescriptionへ反映済みの内容は本文・変更ログともに再掲のみとし、重複した変更を加えない
- コメントが本文と矛盾する場合は、より新しい人間の合意(依頼者・レビュアーによる指示・承認・確認事項への人手回答などの自由記述コメント)を優先する
- AI生成コメントは本文の確定方針を覆す根拠にしない。スキルが投稿・編集した定型コメント(
## 確認事項・## 回答・トリアージ判定記録など、answer-issue-questions / post-issue-body / triage-created-issue 由来のもの)はAI生成コメントとして扱う。ワーカーは人間のアカウントで投稿するため、投稿者名ではなくコメントの内容・形式で判別する。AI生成コメントに含まれる事実情報(コード引用・行番号・調査結果)は「参照情報」「影響範囲」等へ反映してよいが、本文の確定方針(統合先・採用アプローチ・対象範囲など、依頼が所与として示した判断)と矛盾する結論・推奨が含まれていても方針は本文側を維持し、矛盾する事実は事実として注記するに留める。実装プランを「方針確定待ち」を前提とした複数案(A案/B案等)の分岐形式に書き換えない
- 反映すべき未反映事項が1件も無い場合は、descriptionを更新せず(ステップ5の
post-issue-body 起動をスキップ)、その判断をユーザーに報告して終了する
加えて、タスクの内容を理解するために、要件定義ドキュメントやデザインファイル(Pencilファイル)を読み込み、タスクの背景・目的・関連する仕様を把握する。Pencilファイル(.pen)は inspect-pencil-node スキルで対象Nodeの属性データとスクリーンショットを取得して内容を確認すること(.pen は暗号化バイナリで Read/Grep は使えない)。.pen の編集が必要と判明した場合は本スキル内では編集せず、post-issue-body へ渡す「実装プラン」「確認事項」に「pencil-design-updater エージェントで <対象 .pen> を更新する」旨を明記して後続タスクへ委譲する。
4. コードの分析
explore-agent サブエージェントで未反映事項に基づき、コードベースをできるだけ詳細に分析する。サブエージェントへのプロンプトにはステップ1で確定した BASE_BRANCH をターゲットブランチとして明示し、「現在の作業ディレクトリのコード状態が基準であり、デフォルトブランチとの差分は論点にしない」ことを伝える。
ユーザーへの確認が必要な事項があっても途中で質問せず、Issue へ確認事項として残す(post-issue-body へ「確認事項」として渡せばコメントとして投稿される)。
直近関連変更の確認(必須)
進行中・直近完了済みの関連作業を見落とし、既存実装と重複するゴーストタスクを含んだ Issue に更新しないため、対象ファイル一覧について直近の commit 履歴と関連 PR を必ず確認する。
-
対象ファイルごとに git log --oneline -10 <file> を実行し、直近 commit のサマリを把握する
-
未マージの関連 PR は base が BASE_BRANCH のものだけを対象にする。base が異なる PR(BASE_BRANCH が epic ブランチのときの Epic PR 自身、他 epic 配下の PR など)は本Issueのマージ先に影響しないため除外する
gh pr list --search "<file>" --state open --json number,title,baseRefName,headRefName \
--jq ".[] | select(.baseRefName == \"${BASE_BRANCH}\")"
-
直近 commit に大規模リファクタ・共通ヘルパー追加などの大きな変更が含まれる場合や、上記フィルタを通過した未マージ PR がある場合は、その内容を post-issue-body に渡す「直近関連変更」セクション(必要に応じて「参照情報」にも)に必ず記載し、実装プランが既存実装と重複していないか検証する
-
除外した PR(Epic PR 等)は「直近関連変更」にも「確認事項」にも書かない。Epic PR の未マージは Epic フローの正常状態であり、記載すると後続の answer-issue-questions / exec-issue が不要な検討事項として扱ってしまう
-
git 履歴のない新規機能要求など確認が困難なケースでは「該当なし」と記載してスキップしてよい
4.5. 反映後 description の曖昧点レビュー(確認事項の補強)
ステップ3〜4で反映内容(更新後の 概要 要件 実装プラン など)が固まったら、その内容を「実装者がそのまま着手できる解像度になっているか」という観点で読み直す。コメントを反映してもなお、要件が曖昧・前提が未確定・複数の解釈が残る箇所があれば、それを確認事項として洗い出す。
descriptionは実装者や後続スキル(exec-issue など)が着手時の唯一の入力になるため、曖昧なまま更新すると気づかれずそのまま手戻りになる。反映で埋めきれなかった不明点をその場で質問に変換してコメントに残しておけば、着手前に人が答えられる状態を作れる。これがこのステップの狙いで、descriptionを「更新して終わり」にせず「更新した内容の穴を突く」ことに価値がある。
洗い出す観点の例:
- 要件の受け入れ条件(どうなれば完了と言えるか)が本文から判断できない
- 人間のコメント同士、または人間のコメントと既存本文で結論が食い違い、どちらを採るか確定できない(AI生成コメントと本文の食い違いは対象外 — ステップ3のとおり本文の確定方針を維持し、確認事項化して人間の意思決定へ差し戻さない)
- 実装プランの分岐(対象範囲・非対応ケース・既存挙動との整合)が仕様として未確定
- ステップ4のコード分析で前提と既存実装が食い違い、意図を確認しないと進められない
洗い出しの対象外(確認事項にしない):
BASE_BRANCH(=マージ先)ではなくデフォルトブランチとの差分に由来する論点。特に Epic PR(cc-epic-<N> → デフォルトブランチ)の未マージは Epic フローの正常状態なので、「Epic PR がマージされていないがどうするか」「先にマージが必要か」は確認事項にしない
ここで洗い出した確認事項は、ステップ4で既に把握していた未確認事項とマージして重複を除いたうえで、ステップ5で post-issue-body の confirmation_items としてまとめて渡す(post-issue-body がそれらを1つの ## 確認事項 コメントとして投稿する)。コメントを二重に投稿しないよう、確認事項の投稿口はこの confirmation_items に一本化する。
曖昧点が本当に無ければ confirmation_items は省略してよい(穴埋めのために無理に質問を作らない — 中身の薄い確認事項はノイズになり、かえって着手を遅らせる)。なお、途中でユーザーへ直接質問せず必ずコメントに残す方針は本スキル全体で共通(ステップ4の注記と同じ)。
5. post-issue-body スキルで Issue を更新
ステップ2〜4.5の分析結果を 以下の YAML ブロックの形でそのまま args として Skill tool で post-issue-body を起動する(post-issue-body は args を YAML として機械的にパースする規約)。
mode: edit
issue_number: <ステップ2で確定した番号>
title: <更新後タイトル — 変えない場合はステップ2で取得した既存タイトルを再掲>
sections:
概要: |
(1-3行、コメント由来の更新を反映)
要件: |
- ...
(無ければ "なし")
参照情報: |
- ドキュメント: `<path>` — <説明>
(無ければ "なし")
直近関連変更: |
- `<commit hash>` <subject> — <影響>
(ステップ4で確認した結果、無ければ "該当なし")
実装プラン: |
1. (コメント反映後の最新版)
影響範囲: |
- `<path>` — <概略>
new_changelog_entry: コメントの〇〇を要件に反映
confirmation_items:
- <ステップ4で新たに発生した未確認事項、またはステップ4.5で洗い出した反映後の残曖昧点>
sections.依頼内容 は本スキルからは絶対に渡さない。ステップ2.5のとおり、既存の依頼内容ブロック(新旧フォーマットとも)の verbatim 再掲は post-issue-body 側の責務(args.sections.依頼内容 未指定なら既存bodyの中身を verbatim 再掲する規約)。既存bodyに依頼内容が無ければ追加もしない。コメントで発生した仕様変更は 概要 要件 実装プラン 側で反映する。
Skill tool 呼び出しは Skill(skill='post-issue-body', args=<上記YAML文字列>)(必要なら plugin namespace 付きで claude-task-worker:post-issue-body)。args は改行を含む複数行文字列としてそのまま渡す。post-issue-body の責務範囲は以下のとおりで、本スキルから重複して実行しない。
gh issue view --json body で既存本文を再取得して変更ログを verbatim で再掲
- 本文テンプレート・投稿前チェックリストに従って本文を組み立て・検証
gh issue edit で更新(--remove-label は不使用)
- 確認事項が渡されていればコメント投稿
完了後、Issue URL と確認事項コメントの有無が返ってくる。未反映事項が0件と判断した場合は post-issue-body を起動せず、その旨をユーザーに報告して終了する。
5.5. 既存「依頼内容」ブロックが失われていないかの事後検証
post-issue-body は本文全体を heredoc で上書きするため、verbatim 再掲ロジックのバグや漏れで元の依頼原文が消える可能性がある。本スキルは依頼内容ブロックを新規作成しないが、既に存在した依頼内容を失わせない責任は本スキルにあるので、投稿完了直後に検証する。
以下を機械的に実行する(ユーザーへの確認は不要):
- ステップ2.5で「既存bodyに依頼内容が無い」と判定した場合 — 本ステップはスキップする(保護対象が無い)。
- 未反映事項が0件で
post-issue-body の起動をスキップした場合 — 本ステップもスキップする(description を更新していないため)。
- ステップ2.5で「既存bodyに依頼内容あり」と判定した場合 — 以下の手順で検証する:
gh issue view <issue_number> --json body -q .body で更新後の body を取得する。
- 取得した body から
<details><summary>依頼内容</summary> ブロックの中身を抽出する(<summary> の閉じタグ直後から </details> の直前まで、タグは含めない。先頭・末尾の空行1つは正規化してよい)。本文中に <details> は依頼内容と変更ログの2つ存在し得るので、必ず <summary>依頼内容</summary> で識別してから切り出す。
- ステップ2.5で保持した「期待値」と抽出した中身を比較する。改行・空白まで含めて完全一致すること。前後の空行1つ程度の差は許容してよいが、内容の欠落・改変は不可。
- 書き出しが折りたたみブロックになっていること — 実行前が旧フォーマット(
## 依頼内容 見出し)だった場合も、更新後は必ず <details><summary>依頼内容</summary> に詰め替わっていること。裸の見出しのままなら逸脱として扱う。
- 一致しない、または折りたたみになっていない場合は次の順で復旧を試みる:
- もう一度
post-issue-body を同じ args で呼び直す(一過性の投稿エラーの可能性)。
- 再実行後も一致しない場合は、
gh issue view --json body で取得した現在の body に対して「## 概要 の直前に <details>\n<summary>依頼内容</summary>\n\n<期待値>\n\n</details>\n\n を差し込んだ本文」を組み立て、gh issue edit <issue_number> --body-file - <<'EOF' ... EOF で直接上書きする。既存に旧フォーマットの ## 依頼内容 見出しや別の依頼内容ブロックが残っていれば、その部分は取り除いてから差し込む。
- どちらでも解消しなければ、Issue URL と失敗理由を最終報告に含めて終了する(サイレント失敗させない)。
- 検証が通れば、Issue URL・確認事項コメントの有無・依頼内容保護検証結果(
一致 / 復旧して一致 / 未一致(要手動確認))をまとめて報告して終了する。
完了条件: 実行前bodyに依頼内容があった場合は更新後bodyでもその中身が <details><summary>依頼内容</summary> ブロックとして保持されていること(または未反映事項0件・依頼内容無しで本ステップをスキップした状態)。
5.6. 依存関係の反映(blockedBy / blocking)
コメント履歴やコード分析で、この Issue が他の Open な Issue と依存関係を持つことが判明した場合、それを GitHub ネイティブ relationships(blocked-by / blocking)として既存Issueに反映する。本スキルは新規Issueを作らないため、gh issue edit --add-blocked-by / --add-blocking で追加する(本文の ## 依存関係 セクションには書かない)。
以下を機械的に実行する(ユーザーへの確認は不要)。依存関係の言及・示唆が無ければ本ステップはスキップする。未反映事項0件で post-issue-body の起動をスキップした場合でも、コメントで依存関係が判明していれば本ステップは実行してよい(relationship の付与は description 更新とは独立のため)。
-
依存関係の抽出: ステップ2〜4で読んだコメント・本文・コード分析から、この Issue の依存関係への言及(#123・Issue URL・「〇〇 が終わってから」「〇〇 が前提」「〇〇 をブロックする」等)を洗い出す。推測で無関係な Issue を紐付けないよう、根拠が明確なものだけを対象にする。
-
方向の確定:
- blockedBy(この Issue をブロックする=先に片付けるべき Issue): この Issue に着手する前に完了している必要がある Open Issue の番号。
- blocking(この Issue がブロックする=後続で待たせる Issue): この Issue が完了しないと進められない Open Issue の番号。
-
現在状態の検証: 対象 Issue 番号は gh issue view <番号> --json number,state,title で Open であることを確認する。CLOSED の Issue は含めない。
-
既存relationshipとの差分: 現在の relationship を取得し、まだ貼られていない依存だけを追加する(既存relationshipは剥がさない。--remove-blocked-by / --remove-blocking は使わない)。
gh issue view <このIssue番号> --json blockedBy,blocking
-
付与(best-effort): 差分の番号だけを渡す。--add-blocked-by / --add-blocking はカンマ区切りで複数番号を1フラグにまとめてよい。追加が無い側のフラグは省略する。
gh issue edit <このIssue番号> --add-blocked-by <番号,番号,...>
gh issue edit <このIssue番号> --add-blocking <番号,番号,...>
gh issue edit --add-blocked-by / --add-blocking が失敗しても(権限不足・gh バージョン未達・存在しない番号等)、description 更新はすでに完了しているため、エラーを最終報告に残したうえで処理を続行する(ロールバックしない)。付与・スキップの結果は最終報告に1行で記録する。
中断条件
- 引数が空、または Issue 番号として解釈できない
gh issue view で対象 Issue が見つからない、または CLOSED
post-issue-body が失敗し、再試行しても解消しない
- ステップ5.5の既存「依頼内容」保護検証で、
post-issue-body 再実行と直接 gh issue edit によるフォールバックの両方に失敗した場合 → Issue URL・失敗理由・保持されるべき「依頼内容」期待値を出力して終了(サイレントに終わらせない)
注意事項
- このスキルはコードを一切変更しない。Issue の更新・コメントは原則
post-issue-body 経由で行う(本スキル内で直接 gh issue edit を呼ぶのはステップ5.5のフォールバック用途に限る)
- 途中でユーザーに質問しない。確認したいことは
post-issue-body へ「確認事項」として渡し、コメントとして残す
- 本文の確定方針を覆せるのは人間のコメントだけ。AI生成コメント(
## 回答 等の定型コメント)は事実の反映元に留め、方針変更・実装プランの複数案分岐化・「方針確定を依頼する」確認事項化の根拠にしない(判別基準はステップ3を参照)
- description を反映しただけで終わらせず、ステップ4.5で「反映後もなお残る不明点・曖昧な要件」を見直し、あればステップ4の未確認事項とマージして
confirmation_items として渡す(## 確認事項 コメントに一本化する。曖昧点が無ければ無理に作らない)
- コメント/分析で依存関係が判明したら、ステップ5.6で
gh issue edit --add-blocked-by / --add-blocking により既存Issueへ GitHub ネイティブ relationships として反映する(本文に ## 依存関係 は書かない)。既存relationshipは剥がさず、まだ貼られていない依存だけを best-effort で追加する。根拠が明確な依存のみを対象にし、無ければスキップする
- 依頼内容ブロック(
<details><summary>依頼内容</summary>)を新規追加しない(理由は冒頭「『依頼内容』の扱い」を参照)
- 既存bodyに依頼内容ブロックがあった場合、その保持は
post-issue-body の verbatim 再掲規約に委ねる。args の sections.依頼内容 は本スキルからは渡さない(渡すと原文とのズレを生む可能性がある)。ステップ5.5で実際に保持されかつ折りたたみで書き出されたかを検証する
- Pencil ファイル(
.pen)の読み込みは inspect-pencil-node スキル経由でのみ行う(暗号化バイナリのため Read/Grep は使えない)
.pen の編集は本スキルでは絶対に行わない。必要と判明した場合は pencil-design-updater エージェントで対応する旨を post-issue-body 経由で「実装プラン」または「確認事項」に明記して後続タスクへ委譲する(.pen 編集は pencil-design-updater 専任・edit-pencil-design スキル経由の運用 — 同パス上書き・差分Node特定・snapshots/ 出力 — に集約されており、手で pencil コマンドを直接組み立てたり frontend-implementer/general-purpose-assistant 等で代用したりしない)