Learning Activity
広告とLPの溝を埋める分析で、分析単位の粒度ズレが最も再発しやすい落とし穴。
問題の構造
依頼フローでは「対象の広告グループ(AG)を決める」が最初に来るが、ヒートマップツール側の絞込粒度は「LP × チャネル × デバイス」までしか絞れないことが多い。この2つを最初に握らないと:
- AG単位で本命を選定 → ヒートマップは全AG合算値しか取れない
- ヒートマップ粒度にAG定義を寄せる → 対象AGに存在しない検索語句を議論に載せてしまう
実際に起きた誤り: 対象AGを拡張したら「大学入学式スーツ」等の語句が流入38%を占める最大カテゴリに浮上。しかし元の対象AGには0件で、分析全体が誤診断。
対策: Step 0を依頼フローに組み込む
Step 0a: 対象AGを triage (費用絶対額1位) で特定
Step 0b: ヒートマップ取得粒度とAG粒度のズレを明示
→ 例:「本AGはヒートマップ母集団の約35%」と限界事項に明記
Step 1以降: ①対象AG決定 → ②語句カテゴライズ → ... ⑦改善案
学び
- 「技術的に粒度を揃える」配慮で依頼要件を逸脱しないこと
- 分析の限界(粒度ズレ)は正直に開示する方がレビュワーの信頼を得る
- 母集団定義を勝手に変えない。変えるなら必ずレビュー前に握る
関数が200個ある Cloud Functions プロジェクトで「変更ファイルから影響を受ける関数だけデプロイ」を機械化した話。grep ベースだと共通ヘルパー経由の多段依存を追えず、結局は全デプロイに流れがち。dependency-cruiser の依存グラフ JSON を使えば transitive 依存を一発で解ける。
構成
- 関数エントリ辞書の抽出:
index.tsを ts-morph で AST パースして{ 関数名 → ファイルパス }を生成。環境分岐(if (ENV === 'production')など)も追う - 依存グラフ生成:
depcruise --output-type json srcで全モジュールの依存JSONを出力(数百ファイルでも1〜2秒) - 影響範囲計算:
git diffの変更ファイル集合から逆依存グラフを BFS で辿り、エントリ集合との積集合を取る
ハマりどころ
- 全デプロイに倒すべきファイルを別途定義する:
package.json,tsconfig.json,firebase.json, エントリ辞書の構造変更(関数追加・削除)。これらは transitive 解析では検出できない - base ref の辞書は
git show <ref>:pathで一時ディレクトリに再構築して比較。worktree を切るより軽い - depcruise 結果はキャッシュ推奨(src の mtime で自動失効)
限界
静的解析なので process.env.FUNCTION_NAME 的な文字列参照や動的 import は追えない。その場合は --all で全デプロイにフォールバックできる逃げ道を残しておく。
# 実行例
ts-node scripts/affected-functions.ts --env production --base origin/main --json
# → { fullDeploy: false, affectedFunctions: [...], deployCommand: "firebase deploy --only functions:a,b,c" } 参考: Claude CodeでCLIツールを活用した開発効率化
「探索と分析はCLIに任せ、LLMは結果の解釈に専念する」という分業を実践した記録。
使ったツールと役割
| ツール | 計測軸 |
|---|---|
knip | 未使用 export / file / dependency |
madge --circular / --summary | 循環参照・hub依存数 |
type-coverage --strict --detail | any の数(ファイル別) |
semgrep --config=p/security-audit | セキュリティ監査 |
git log | 変更頻度(hot)・バグ修正集中(fix grep)・Temporal Coupling |
肝はクロスリファレンス
単一シグナルでは判断できない。
ホットスポット単独は問題ではない。「変更が多い」=「ビジネス重要で活発」というポジティブシグナルでもある。 問題は 型穴・循環参照・バグ多発と重なるとき だけ。
実測例: 1ファイルが hot×循環×hub×型穴 の4冠 → 最優先リファクタ対象として一発で炙り出せた。
設計の判断
| 単位 | 配置 |
|---|---|
| 単一ツール(knipなど) | CLAUDE.md に「あるよ」と一行 |
| 複数ツール連携の段階分析 | スキル化(/refactor-priority 等) |
ツールごとに dotfiles/docs/tools/{tool}.md を書き、CLAUDE.md は索引として参照する設計。スキル数を増やしすぎない。
環境構築メモ
mise use -g npm:knip npm:madge npm:type-coverage npm:dependency-cruiser
brew install semgrep
mise の npm: バックエンドで ~/.config/mise/config.toml に追記される(Brewfile相当の再現性)。
LP分析でヒートマップCSVの「クリックイベントラベル列」だけで中身を推定するのは不十分。LP HTMLを curl で実取得しないと、CTA文言やマイクロコピーが分からず、改善案が抽象論に終わる。
必要な実装
# 1. LP HTMLを取得
curl -sL -A "Mozilla/5.0 (iPhone;...)" "$LP_URL" -o lp.html
# 2. エンコーディング自動判定(SHIFT_JIS / UTF-8 / EUC-JP)
file lp.html
iconv -f SHIFT_JIS -t UTF-8 lp.html > lp_utf8.html
# 3. h1-h4 / a / button / 本文を抽出
抽出するべき要素
| 要素 | 用途 |
|---|---|
<title> / <meta description> | ページ全体の訴求 |
h1-h4 | セクション構造(上から順) |
a / button のテキスト | CTAコピー・マイクロコピー |
| 本文(重複除去・順次) | セクション文言 |
「LPに存在しない要素」が逆に示唆を持つ
ポジティブチェック(何があるか)だけでなく**ネガティブチェック(何がないか)**も重要。
例: 「評判口コミ」系検索が流入22%なのにLPにお客様の声セクションが無い=最大流入への応答ゼロが判明。これはCSVヒートマップだけでは絶対に見えない。
依頼要件との関係
ビジネス依頼の「CTAのコピーを書き換える」レベルの具体提案は、CTA実文言を取得しないと書けない。抽出→対比→書き換え案の3ステップで「現状: ○○ → 改善案: △△」の形で提示する。
分析レポートで「課題発見→施策提案」を網羅的に書くと情報過多で読まれない。ビジネスサイドから来た依頼書の項目①〜⑦に1対1対応させ、各回答に**参照元(どの資料のどの部分を見たか)**を添える構造が最も読みやすい。
構造
## 参照データ一覧
| 略称 | 実体 | 粒度 |
|---|---|---|
| 資料A | 検索語句レポート | ... |
| 資料B | LPレポート | ... |
| 資料C | ヒートマップCSV | ... |
## ① 対象を決める
### 回答
...
### 参照元
- 資料B → L4粒度で集計 → 費用1位のスライスを選定
## ② カテゴライズ
### 回答
...
### 参照元
- 資料A → ①で絞込 → XXX語句 → カテゴリ辞書で分類
効果
| Before(網羅型) | After(1対1対応) |
|---|---|
| 課題1〜6が並列で優先度不明 | ①〜⑦順に読めば結論が導ける |
| 数値の出典が追えない | 資料A〜Eで追跡可能 |
| レビュワーが「この数値の根拠は?」と往復 | 各主張の横に参照元がある |
| 代理店がサボれる | 事業主が「資料Xの何ページ」で検証できる |
重要ポイント
- 依頼書の文言に忠実に答える(「対象の広告グループを決める」と書いてあるなら広告グループ粒度で答える。LP粒度に勝手に格上げしない)
- 分析の限界を正直に開示する(粒度ズレ・セグメント切れない問題など)
- 参考PDFなど既存アウトプット形式があれば踏襲する(2列「現状vs改善案」レイアウト等)
「AI出力の品質をビジネス側が評価できる状態」を設計することで、標準化プロセスの再現性が上がる。
claude.ai の Remote Trigger(/schedule で作る定期実行エージェント)は、実行環境から外部 HTTPS 通信がプロキシで 403 ブロックされる。RSS 取得・Slack Webhook 投稿を伴う「定期ニュース収集 → 通知」タスクを Remote Trigger で組もうとしてハマった。
確認した挙動
curl→ CONNECT tunnel 403 (exit 56)WebFetch→ HTTP 403- Slack Incoming Webhook への POST も同様にブロック
- 使えるのは
WebSearchくらい
落とし穴
エージェントが外部フェッチ失敗時に WebSearch で代替しようとすると、フィード本文を読めないためハルシネーション(実在しない CVE 番号など)を混入させて「それっぽい」結果を返してくる。Slack に流す直前まで気づけない可能性があるので要注意。
さらに Remote Trigger の MCP 接続は claude.ai アカウントのコネクタが自動継承されない。mcp_connections に connector_uuid / name / url を明示指定しないとリモート側の Claude セッションでは MCP ツールが使えない。そして UUID を取得する公開 API がない。
代替案
外部通信を伴う定期タスクは Cloudflare Workers Cron Trigger で実装するのが堅牢。
wrangler.tomlの[triggers] crons = ["0 23 * * *"]で cron 指定fetch()/ KV / Secrets すべて使える- 無料枠内で完結
wrangler dev --test-scheduledでローカル発火テスト可能wrangler tailで本番ログも追える
使い分け
| ケース | 向いてる仕組み |
|---|---|
| 外部 API 呼び出し・Webhook 投稿が必須 | Cloudflare Workers Cron |
| コードベースの自動レビュー・git 操作 | claude.ai Remote Trigger |
| claude.ai 側完結の会話的タスク | claude.ai Remote Trigger |
| 高頻度・低レイテンシ | Cloudflare Workers Cron |
コードベース自動ドキュメント生成ツール(wikigen等)を試して辿り着いた気づき。AIはコードの”構造”は完璧に読めるが、“意味”は読めない。そしてその限界は本質的であって、モデルの賢さで埋まらない。
ドキュメントの4層構造
| 層 | 内容 | 生成元 | 機械で可能か |
|---|---|---|---|
| Layer 1: 構文 | コード自身 | コード | — |
| Layer 2: 構造 | ファイル関係・関数呼出・API定義 | コード | ✅ 完璧 |
| Layer 3: 機能 | ユーザーから見てこの機能が何をするか | 人間の頭 | ❌ |
| Layer 4: 意図 | なぜこう実装されているか、ビジネス要件 | 人間の頭 + 過去の会話ログ | ❌ |
なぜLayer 3がコードから出ないか
ファイル名が PublicTaskList.svelte でも、それが「顧客向け実績ページ」なのか「社内タスク管理」なのかは読めない。コレクション名 divisions が「業界別」か「社内部門」かも曖昧。多段ワークフローは複数リポをまたぐので、順に読んでもユーザー体験として再構築できない。「なぜこのif文があるか」はコミットメッセージにすら無く、Slack過去ログや誰かの記憶にしか残っていないことも多い。
つまり暗黙知(tacit knowledge)がコードの外にあり、存在しない情報はAIも生成できない。
重要な誤解の訂正
「AI向けドキュメント」は”理解済みの知識の圧縮”であって”理解の代替”ではない。llms.txt や AGENTS.md の議論はほぼ前者で、「すでに誰かが理解しているものを機械可読形式で固定化する」話。理解そのものを生み出す話ではない。
“骨子×世界観”モデル
この限界を逆手に取った役割分担:
| 役割 | 担当 | 作業量 |
|---|---|---|
| 構造(Layer 2) | 機械(wikigen等) | 秒〜分 |
| 機能要約(Layer 3) | 人間 + AI対話 | 各ページ数分 |
| 意図(Layer 4) | 人間 + 関係者インタビュー | プロジェクト単位 |
| AI向け圧縮 | 機械(AGENTS.md変換) | 秒 |
機械が骨子を作り、人間が”自分が見ている世界”を書き込む。その合作こそが真のドキュメント。
心理的にも理にかなっている
ゼロから書けと言うと永遠に書かないドキュメントも、骨子を渡されると埋まる。「このページ名、これ何する機能?」と聞けば人間は1行で答えてくれる。アウトラインを埋める形式にすることで書き出しの心理障壁を下げるのが肝。
ツール評価基準の転換
ドキュメント自動生成ツールの真価は「どこまで自動で書けるか」ではなく「人間の暗黙知を引き出しやすい下書きをどこまで作れるか」にある。完璧な自動化を目指すより、人間の追記を誘発する良質な下書きを作る方が、最終的なドキュメントの質は高くなる。
wikigenはGo製CLIで、Claude Codeを呼び出してコードベースから仕様wikiを自動生成する。embeddings/Docker/Ollama不要。Astro+Svelte+Firebaseの中規模プロダクトで検証した結果、想像を超えるクオリティだった。
本質は「Claude Codeをワーカーとして外部から叩くパターン」
これが一番の学び。wikigenはClaude Codeスキルのようなものではなく、外部プログラムがclaude CLIを子プロセスとして並列に起動する設計。スキルとは別物。
| 観点 | スキル | wikigen方式 |
|---|---|---|
| 実行場所 | 現在の会話内(同一context) | 外部プロセスが独立context起動 |
| 並列 | 不可 | -pp Nで並列worker |
| Context消費 | 現在のcontextを食う | 各subprocess独立 |
| 運用 | 人が対話 | GH Actionsで無人実行可能 |
いわゆる Claude Code headless mode / Claude Code as SDK のパターン。claude -p <prompt> で対話UIを起動せずプロンプト投入だけできるので、それを外部オーケストレーターから叩くと「バッチ処理」「CI統合」「Slack Bot裏側」等に応用できる。会話UIとしてのClaude Codeと、プログラムから叩くワーカーとしてのClaude Codeは別の顔、という発想転換が大事。
実行のコツ
-localフラグは不要: 位置引数に直接ローカルパスを渡せばclone不要 →./wikigen /path/to/repo- privateリポでもローカルクローンさえあれば動く
- 認証は
claudeCLIの対話ログイン状態を子プロセス継承で引き継ぐ。CLAUDE_CODE_OAUTH_TOKENを明示設定しなくても動作した(READMEに記載なし) - 単一ページだけ生成したい場合は
-retryを悪用: 1ページだけ空ファイル(<200B)を置いてretry実行 → そのページだけ生成される
クオリティ検証結果
24ページ構成のwikiを2分24秒で設計。1ページ本生成は約3分で16,301文字。スポットチェックで確認した範囲では:
- ソース引用が行番号まで全て正確(ハルシネーションなし)
- sequenceDiagramとflowchartのmermaid図を自動生成
- コメントと実装の乖離のような人間のレビュアーでも見落としがちな細部まで指摘
- 「設計上の特徴」セクションを自力で作成する抽象化力
記事が触れていない注意点
- 「追加課金なし」はClaude Pro/Max契約者のOAuthトークン方式のみ。
ANTHROPIC_API_KEY利用時は従量課金 --bareモードではOAuthトークン無効- OAuthトークンは1年有効
- 便利な未記載フラグ:
-dry-run,-model(haiku/sonnet/opus),-json
向き/不向き
向き: コード主体のリポの叩き台仕様wiki、新人オンボーディング初稿、設計ドキュメントの老朽化対策(GH Actionsで定期再生成)
不向き: Markdownコンテンツ主体のドキュメントリポ、ビジネス要件・設計意図の「Why」の記述(wikigenはコード根拠に限定される)
environment inputの罠
workflow_dispatch に environment の choice input を用意すると、「Use workflow from」(ブランチ選択UI、削除不可)との組み合わせで 任意ブランチのコードを本番にデプロイできてしまう。デプロイ先はブランチで自動決定し、inputに環境選択を持たせない設計が安全。
# NG: inputで環境を選ばせる
environment: ${{ inputs.environment }}
# OK: ブランチで自動決定
environment: ${{ github.ref == 'refs/heads/master' && 'production' || 'develop' }}
ブランチガードパターン
develop/master 以外からの手動実行をスキップする:
jobs:
deploy:
if: github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master'
concurrency group も同じ式で統一すると一貫性が保てる。
develop push の自動デプロイは慎重に
開発ブランチへの push で自動デプロイすると、他メンバーが個別に Functions 等を反映している場合に競合する。開発環境は手動デプロイの方が安全なケースがある。
Environments の Required Reviewers の制約
承認設定は環境単位で適用される。push 自動デプロイは即時、手動デプロイは承認必須、を分けたい場合は環境名を分ける必要がある(例: production / production-manual)。ただしコードの安全性は PR レビュー、デプロイの安全性はブランチ制約で役割分担すれば、デプロイ時の承認は不要な場合が多い。
新規ワークフロー作成チェックリスト
- デプロイ先はブランチで自動決定しているか(environment input 不使用)
- develop/master 以外の実行をスキップするガードがあるか
- concurrency 設定があるか
- timeout-minutes が設定されているか
- push トリガーのブランチは適切か(develop の自動デプロイが本当に必要か)
- README に手順・パラメータが記載されているか
Files(API機能)
- APIからファイルを一度アップロードし、
file_idで複数リクエストから再利用する仕組み - ローカルのClaude Codeでは
Readツールでファイルを直接読めるので不要 - ユースケース: Claudeを組み込んだアプリで、ユーザーがアップロードしたPDF等を複数回参照するとき
Skills(Console版 vs ローカル版)
| Console Skills | ローカル Skills | |
|---|---|---|
| 実行場所 | Anthropicクラウドのサンドボックス | 自分のPC |
| 内容 | コード実行でファイル生成(.pptx/.xlsx等) | プロンプトテンプレート(/commit 等) |
| 用途 | APIレスポンスとしてファイルを返す | 開発者自身のワークフロー効率化 |
整理
- ローカルClaude Code = 自分自身の開発ツール
- Console Files/Skills = 自分が作るプロダクトに組み込むAPI機能
自分でClaude Codeを使って開発する分にはConsole側は直接関係ない。「Claudeを組み込んだアプリを他人に提供する」段階で意味を持つ。