アプリ内フィードバック→責任者DM→Issue→自動修正PR→1タップ承認
社内アプリの不具合報告を、責任者の個別DMに届け、Issueにして夜間に修正PRまで自動で作り、承認は既存のPR画面のMergeボタン1タップで済ませる設計。通知先を中継1箇所に集約してトークン拡散を防ぎ、既読は通知のリアクションで持ち、絵文字で自分の通知を拾う無限ループを断つ。
約5.3万トークンの節約 (API料金換算で約80円分)。 要件定義・技術調査・試行錯誤ぶんのトークンがまるごと不要になります。※ 出品者申告とレビューに基づく推定値。モデル・タスク内容により変動します。
この巻物について
「アプリ内フィードバック→責任者DM→Issue→自動修正PR→1タップ承認」は、開発プロセスカテゴリのAI指示書(MDファイル)です。社内アプリの不具合報告を、責任者の個別DMに届け、Issueにして夜間に修正PRまで自動で作り、承認は既存のPR画面のMergeボタン1タップで済ませる設計。通知先を中継1箇所に集約してトークン拡散を防ぎ、既読は通知のリアクションで持ち、絵文字で自分の通知を拾う無限ループを断つ。この巻物をAIに読み込ませると、ゼロから設計・調査する場合に比べて 約5.3万トークン(API料金換算で約80円)・85%のトークンを節約できます。
- カテゴリ
- 開発プロセス
- 対応AI
- claude-code、cursor、codex-cli
- ライセンス
- 商用利用可 (再販不可)
- 価格
- 無料
- ゼロから開発時
- 約6.2万トークン
- この巻物使用時
- 約9,000トークン
- 節約量
- 約5.3万トークン (約80円)
- 更新日
- 2026-08-28
使い方 (AIに渡す3つの方法)
いちばん簡単なのはワンライナー。Claude Code のターミナルに貼るだけです。
claude "https://makimono-md.vercel.app/api/v1/files/dm-issue-pr-1/raw を読み込んで、この指示書どおりに実装して"
中身
アプリ内フィードバック → 責任者の個別DM → Issue → 自動修正PR → 1タップ承認
社内 Web アプリの「不具合・要望フォーム」を、報告が入ってから修正が本番に出るまで繋ぐ設計。 責任者の手作業は最後の「PR をマージする1タップ」だけになる。
対象: Next.js App Router のアプリ(複数可)/通知先 Discord / CI は GitHub Actions / ホスティングは Vercel。 他スタックでも「中継を1箇所に置く」「既読マークを通知先に持たせる」考え方はそのまま使える。
全体像
[アプリのフォーム] POST /api/feedback
↓
[中継サーバー1台] POST /api/feedback-intake → 責任者の個別DMへ通知
↓(夜間バッチが取りに行く)
GET /api/feedback-intake?pending=1 … 未処理の報告を JSON で返す
↓
[夜間ジョブ] gh issue create --label feedback
→ 成功したものだけ POST /api/feedback-intake/ack (通知に ✅ を付ける=既読)
↓
[無人セッション] feedback ラベルの Issue を拾って修正 → テスト → PR 作成(マージはしない)
↓
[中継] POST /api/notify → 「PRできました」+PRリンク+承認手順 をDMへ
↓
[人] PR を開いて Merge を押す → Git 連携でそのまま本番デプロイ
設計判断(ここを外すと破綻する)
1. 通知先を各アプリに持たせず、中継1箇所に集約する
各アプリに Bot トークンを配ると、権限(多くの場合 Administrator)がアプリの数だけ拡散する。 中継サーバー1台だけがトークンを持ち、各アプリには中継の URL と共有シークレットの2つだけを渡す。
得られるもの:
- 通知先を変えたい時(DM → チャンネル、担当者の変更)に中継の1箇所だけ直せばよい。各アプリは無改修。
- 新しいアプリを追加する時、通知先を毎回考えなくていい(標準の既定が決まる)。
FEEDBACK_RELAY_URL=https://<中継のホスト>/api/feedback-intake
FEEDBACK_RELAY_SECRET=<32バイトのランダム16進>
認証は Authorization: Bearer <secret> の定数時間比較。
シークレット未設定のときは「認証なしで通す」ではなく 503 で止める(設定漏れが公開中継になるのを防ぐ)。
2. 個別DMを読む処理をローカルに置かない
「夜間ジョブが DM を読んで Issue 化する」と考えると、ジョブ側に Bot トークンが必要になる。 しかし 別の Bot のトークンでは他人との DM チャンネルを読めない(403)。 通知に使った Bot 自身のトークンが要る=結局トークンを配ることになる。
そこで中継に「未処理キューの取得」と「既読化」も持たせる。ジョブ側は共有シークレットだけで動く。
GET /api/feedback-intake?pending=1&limit=50
→ {"ok":true,"items":[{message_id, created_at, parse_ok, app_name, kind,
title, body, submitter, page_path, source_url, permalink}]}
POST /api/feedback-intake/ack {"message_id":"..."}
- 古い順で返す(先に来た報告から処理したいので)。
- パースできなかったものは
parse_ok:falseで返す。捨てない。呼び出し側が判断する。
3. 既読マークは「通知先のリアクション」で持つ
処理済みかどうかを状態ファイルや DB で持つと、実行するマシンが変わった時に二重起票する。 通知メッセージに ✅ のリアクションを付けるのを唯一のマーカーにすると、状態が通知先に一元化されて壊れない。
- Issue 作成に成功した時だけ ack する。失敗したら ack しない=次回そのまま再試行される。
- ack は冪等にする(既に付いていても成功扱い)。
4. 自分の通知を自分で拾う無限ループを、絵文字で断つ
同じ DM に「報告の通知」と「PRができた通知」の両方を流すと、 未処理キューが自分の送った通知を報告として拾い、そこから Issue を作り、また通知が飛ぶ。
先頭の絵文字で種別を固定し、キューは報告だけを拾う:
| 種別 | 先頭 | キューが拾うか |
|---|---|---|
| 不具合の報告 | 🐛 | 拾う |
| 要望の報告 | 💡 | 拾う |
| こちらからの連絡(PR完成など) | 🔧 | 拾わない |
この判定は純関数に切り出してテストを書く。ここが壊れると通知が無限に増える。
export function isFeedbackNotification(content) {
return content.startsWith("🐛 **[") || content.startsWith("💡 **[");
}
5. 自由記述から作った修正は「PR で止める」
不具合報告は利用者の自由記述であり、それが人の目を通らずに本番コードを書き換えるのは危ない。 無人セッションには次を禁止事項として明文で渡す:
- PR をマージしない
- 本番へデプロイしない
- 既定ブランチへ直接 push しない
- 報告が曖昧で修正内容を特定できない場合は、推測で実装せず Issue にコメントして終わる
承認は専用のボタンサーバーを作らない。GitHub の PR 画面の Merge ボタンがそのまま承認ボタンになる(スマホでも1タップ)。 ホスティングを Git 連携にしておけば、マージ=本番反映まで自動で繋がる。
6. 通知に「次に何をすればいいか」を書く
承認者は手順を覚えていない。PR の URL が付いている時だけ、通知の末尾に固定文を足す。
承認するには: 上のリンクを開く → 緑の「Merge pull request」→「Confirm merge」。
これで本番に反映されます。直さない時は何もしなくて大丈夫です。
PR 以外のリンク(Issue など)には付けない。判定は正規表現でよいが、テストを書く。
実装の要点
中継エンドポイント(Next.js App Router)
app/api/feedback-intake/route.ts に POST(通知)と GET(未処理キュー)、
app/api/feedback-intake/ack/route.ts に既読化、app/api/notify/route.ts に連絡用を置く。
export const runtime = "nodejs"(cryptoとFormDataを使う)- 通知本文は先頭の絵文字・アプリ名・種別・タイトル・本文300字・提出者・画面パス・提出元URL の順で固定
- ペイロードに
allowed_mentions: { parse: [] }とflags: 4(SUPPRESS_EMBEDS)。 本文に URL を入れるとリンクプレビューが展開されて通知欄が流れるため - スクリーンショットは multipart で素通しする。添付付きが弾かれたら本文だけで再送する (画像のせいで通知全体が消えるのが最悪)
- 送信元アプリ単位のレート制限(例: 1時間60件)。サーバーレスではインスタンス単位の概算になることをコメントに書く
夜間ジョブ
1. GET ?pending=1 で未処理を取得
2. parse_ok:false → Issue を作らず ack もせず、理由をログに出す
3. アプリ名 → リポジトリのマッピングで宛先を決める(未マッピングも同様に残す)
4. gh issue create --label feedback(ラベルが無ければ作る)
5. 成功したものだけ ack。ack に失敗したら「重複の可能性」を警告に出す
6. 上限を超えた分は「残りN件」を明示して次回へ回す
黙って何もしない経路を作らない。 設定が無い・CLI が無い場合もスキップした事実を1行必ず出す。 (沈黙は「正常」と誤読され、動いていないことに何ヶ月も気付かない)
無人セッションへの渡し方
Issue を拾ったら in-progress ラベルを付けて二重着手を防ぐ(起動に失敗したら外す)。
子プロセスへ長いプロンプトを渡す時は argv ではなく stdin かファイル経由にする
(日本語長文は argv でサイズ上限と文字化けに当たる)。
踏んだ罠(全部実際に起きた)
-
ローカルの作業ディレクトリをリポジトリ名から組み立てない。
owner/my-app→~/work/my-appと決め打ちすると、フォルダ名が違う(日本語名など)作業ツリーを見つけられず、 「無ければクローンする」フォールバックが動いて、環境変数も依存パッケージも無い新品のクローンでテストを回そうとして落ちる。git remote get-url originを突き合わせて既存の作業ツリーを探すのが正しい。URL はhttps://host/owner/repo(.git)とgit@host:owner/repo(.git)の両形式を正規化して比較する。 -
人間の DM を試し撃ちの的にしない。 「今後こう届きます」という見本を送った結果、貼ったリンクが 404 だったり、既にマージ済みの PR だったりして 「押すボタンが無い」と混乱させた。受け手は文面ではなくリンク先の画面を信じる。 経路の確認は API のレスポンスや読み取りで完結させ、人に届く形で試すなら状態が文面と一致する実物だけを貼る。
-
フォームの設置先レイアウトを間違えると誰も使えない。 自動導入スクリプトが「最も深いレイアウト」を選ぶ実装だったため管理者用レイアウトに入り、 報告者である一般利用者の画面に出なかった。ルートレイアウトを最優先にする。
-
レイアウトへの自動挿入で壊れた JSX を書かない。 閉じタグの位置を推測して挿入すると、兄弟要素が2つ並ぶ構文エラーになる。 安全に挿入できない形なら書き換えず「手で入れてください」と残作業に積む。
-
strict な TypeScript 設定(
noUncheckedIndexedAccess)のリポジトリでは配列添字がT | undefined。 配布用テンプレートは添字アクセスに undefined ガードを入れておく。 -
提出者の特定は認証方式に依存する。 テンプレートが特定の認証前提だと、別方式のアプリでは常に「不明」になる。 導入時にそのアプリのセッションから取り直す。
検証(ここまでやって初めて「動いた」と言える)
- 中継: 認証なし→401 / 必須項目なし→400 / シークレット未設定→503 / 正常→200 を実際に叩いて確認
- 通知が実際に届いた本文を読み返して確認する(送信APIが200を返したことは着弾の証明にならない)
- フォームから本番の実投稿を1件行い、レスポンスがどの経路を通ったか(例:
sinks.via === "relay")で確認 - 夜間ジョブを
--dryで流し、何件・どのリポジトリへ・どんなタイトルで作る予定かを表示させる - 実際に1件だけ起票し、キューが1件減ることを確認(=ack が効いている)
- 「こちらからの連絡」を送った直後にキューを見て、0件のままであることを確認(=無限ループしない)
そのまま使える環境変数
| 名前 | 置き場所 | 用途 |
|---|---|---|
FEEDBACK_RELAY_URL | 各アプリ / 夜間ジョブ | 中継のエンドポイント |
FEEDBACK_RELAY_SECRET | 各アプリ / 夜間ジョブ / 中継 | Bearer 認証の共有シークレット |
FEEDBACK_DM_USER_ID | 中継のみ | 通知先の個人ID |
<BOT_TOKEN> | 中継のみ | 通知先APIの認証。アプリや各PCへ配らない |
FEEDBACK_REPO_MAP | 夜間ジョブ | アプリ名=owner/repo のカンマ区切り |
よくある質問
+「アプリ内フィードバック→責任者DM→Issue→自動修正PR→1タップ承認」とは何ですか?
社内アプリの不具合報告を、責任者の個別DMに届け、Issueにして夜間に修正PRまで自動で作り、承認は既存のPR画面のMergeボタン1タップで済ませる設計。通知先を中継1箇所に集約してトークン拡散を防ぎ、既読は通知のリアクションで持ち、絵文字で自分の通知を拾う無限ループを断つ。
+どれくらいトークン(費用)を節約できますか?
ゼロから開発すると約6.2万トークンかかりますが、この巻物を使えば約9,000トークンで済みます。差し引き約5.3万トークン(API料金換算で約80円)・85%の節約です。
+どうやって使いますか?
無料です。MDファイルを Claude Code などのAIに読み込ませるだけ。ワンライナーをターミナルに貼れば実装が始まります。要件定義や技術調査を省いて実装だけにトークンを使えます。
+どのAIツールに対応していますか?
claude-code、cursor、codex-cli に対応しています。
+商用利用できますか?
ライセンスは「商用利用可 (再販不可)」です。
🤝 自分でAIを動かすのは、まだ不安…という方へ
この巻物の内容を、AIを使うプロに丸ごと任せることもできます。姉妹サービスAI代行堂なら「LINEで頼むだけで、仕事が完成」。
関連する巻物
ドキュメント駆動開発プロセス CLAUDE.md — 作るものを固めてから書かせる
「AIが暴走して意図と違うものを作る」を根絶する開発プロセス指示書。UI仕様→機能設計→実装の順をAIに強制し、1ファイルごとに承認ゲートを挟む。受託開発・チーム開発向け。
AIに指示書マーケットを自動参照させ、終了時に自動出品させるMD
開発依頼を受けた瞬間にマーケットの完成済み指示書を検索してAIに読ませ、セッション終了時には汎用ノウハウを自動出品させる仕組みの作り方。全台配布・秘密情報スキャン・実際に踏んだ配布バグ3つの回避込み。
「そのPCにしか直せない障害」をAIに自分で気付かせて着手させる
特定の1台にしかリポジトリが無い機能は、修正手順を書いても誰にも実行されず放置される。SessionStart hook で当該PCのAIだけに指示を出し、完了後は指示書へ状態を書き戻して再実装事故を防ぐ型。走査の時間予算とセッション跨ぎの再開、メール一致だけの自動承認がなりすまされる理由と署名キー方式、状態問い合わせAPI、鍵の自動配布、no-op通知の抑止まで、実際に94件の滞留を解消した実例に基づく手順。
この巻物、誰かのトークンも救えます
𝕏 で節約レシートをシェア