たぬ姉

起動画面は公式の標準どおりに作り、
アプリは自分で「けんこう診断」する

調子が悪いときは原因を見つけ、公開前には問題がないか確認し、これまでの判断を次回へ引き継ぎます。
専門知識がなくても全体像が分かるように、実例から順に説明します。

🤒なんか
おかしい
→
📋アプリが
自己申告
→
🤖AIが数字で
原因特定
→
🔧直る
「見てきて」「押してみて」の往復ナシで直ります

このキットで作るアプリには「体調メモ」の仕組みが入ります。
アプリが自分の調子(何件処理した・何秒かかった・どこで失敗した)を 数字でメモしてくれるので、不具合のときあなたが状況を説明しなくても、 AIがそのメモを読んで原因を特定し、修正まで進められます。

💡 実例:ある配信ツールで「診断画面が固まる」不具合を、この体調メモの数字だけで原因特定。 読み込みが817秒(約14分)もかかっていた原因を突き止め、0.005秒まで直した実績があります。 人間がやったのは最後の再読み込みボタン1回だけ。仕組みの正体はキットに入っている説明書 (AIが読む用)に書いてあります。

🔍 出荷する前に、コードそのものを検査する「診断キット」

ここまではアプリが動いているときの診断でした。もう1つ、出荷する前のコードそのものを 機械的に検査する診断キットも同梱されています。「ローカルではちゃんと動いていたのに、 本番デプロイやストア提出だけ失敗する」——たいていローカルの作業フォルダと git clone直後の状態(CI・Vercel・ストアビルドが見る実体)がズレていることが原因です。
📁好きな
プログラム
→
🩺コマンド
1つで診断
→
✅出荷事故を
未然に防ぐ

このキットで作ったアプリでなくても使えます。
既にある JS/TS プロジェクトのフォルダを指定するだけで、そのまま走ります(実測: 無関係の3リポジトリに当てて、それぞれ実際の問題を検出しました)。

チェック見つけること
check-tracked-imports 新しく作ったファイルをgit addし忘れたまま使っている箇所。ローカルではディスクにあるので動いてしまうが、git clone直後(CI/Vercel)だけ「解決できません」と失敗する
check-lockfile-sync package.jsonに足したパッケージがpackage-lock.jsonに反映されていない(npm install後のコミット忘れ)
check-secrets-not-tracked .envや秘密鍵ファイルが、意図せずgitに追跡(コミット)されてしまっている
check-large-tracked-files ビルド成果物や動画など、サイズの大きいファイルの誤コミット(リポジトリ肥大化の原因)
check-selftest-coverage ★検査そのものが「サボると赤くなるか」を確かめていないもの。検査は在るのに壊れても緑を返す状態を数えます(増えたときだけ赤)。
check-symptom-index ★症状の言葉で過去の原因を引けないもの。症状IDが原因索引に登録されていない数を数えます(症状の仕組みがまだ無ければ skip し、入れ方を案内します)。
check-cross-checked ★1つの手段だけで断定していないか。「別の手段でも確かめた」とコミットに書かれた回数を数えます。★間違えた回数ではなく、確かめた回数を数えるので、正直に訂正を書くほど不利になることがありません(減ったときだけ赤)。
check-inline-script-syntax ★HTMLの中に直接書いたJavaScriptの構文を検査します。ESLintは「対象の設定が無い」として見ずに緑を返すため、ここは全リポで死角になっていました。★構文が1つ壊れるとそのブロックは丸ごと実行されず、画面が真っ白になります。★依存ゼロ(Node標準のみ)なので、外部プラグインが将来なくなっても動き続けます。
check-timing-instrumented ★「遅い」と言われる経路に、時間を測る計器が無いもの。件数だけの計器では「何msかかったか」が分からず、遅さの報告に答えられません。実損として、計器の無い経路を推測で3回直そうとして3回とも外しました(増えたときだけ赤)。
check-instruments-reachable ★計器が「あるのに動かない」もの。分岐の片側でしか作られない値を計器が参照していると、例外に飲まれて1件も記録されません。計器が無いなら「無い」と分かりますが、あるのに動かないと「0件だから正常」と読み違えます(実際にそう報告してしまった事故から作りました)。
check-heartbeat-present ★製品が「異常なし」を自分で名乗れないもの。症状が出たときだけ書くログでは、「何も起きなかった」と「計器そのものが動いていなかった」が同じ見た目になります。一定間隔で1行だけ書く仕組み(心拍)が在るかを見ます(ログを書かない小さなツールは skip)。
check-docs-match-code ★説明した置き場所と、コードが実際に探す場所のズレ。説明はコードより先に腐るので、人の記憶に頼らず機械で突き合わせます。
check-silent-hang-guard ★コンソールが無い場所で「固まって返ってこない」形。PowerShell は進捗バーを描こうとしますが、描く先が無いと待ち続けます。1KB のファイルでも固まるので「重いから遅い」と誤診しがちです(実測: 既定=返ってこない/抑止あり=402ms)。CI や自動化から呼ぶスクリプトで効きます。
check-hotkey-scope ★AutoHotkey製の常駐アプリで、キーボードを奪ったまま返さないホットキー。前面判定(WinActive)を持たない条件で登録されたキーは、常駐ウィンドウが閉じきれずに残ったときメモ帳でもブラウザでもそのキーを奪います(実際に「スペースキーを打っても変換されない」という実害が同じ日に2回発生)。他アプリのキー入力に手を出さないマウス専用ホットキーは対象外です。.ahkが無いプロジェクトは skip(対象外・合格ではない)。
check-build-fresh ★直したはずなのに直っていない形。配る実体(exe / app / apk 等)がソースより古いままになっていないかを見ます。実際に、キーボードを奪う不具合を直したのに同じ日に2回目が発生しました——コードは直っていたのに、製品が常駐したまま exe を掴んでいてビルドが無言で失敗し、古い実体が残って起動されていたためです。ソース側の検査(ハッシュ一致・構文)は全部緑だったので、この区間だけが無防備でした。多段ビルド(src → 中間生成物 → 実体)の中間も見ます。成果物を作らないプロジェクトは skip(対象外・合格ではない)。
check-gates-are-wired ★検査を作ったのに、誰もそれを呼んでいない状態。呼ばれない検査は、存在しない検査と同じです。実際に、アプリの審査却下を捕まえるための検査が登録されておらず、検出役が動かないまま却下を通したことがあります。別の場所へ格上げしただけでは配線になりません——移した先で呼ばれているかまでを数えます。
check-shared-parts-used ★共有部品があるのに使わず、同じ名前の関数を自前で書いている数。重複の代償は行数ではなく、一度直したはずのバグが別の画面では直っていないことです(共有部品に入った修正が、その部品を読み込まない画面には永久に届きません)。重複禁止はルールとして既に3箇所に書かれていましたが守られませんでした ——検査していない規範は守られないため、数える側に回しました。統合すべきかは判定しません(描画戦略の違いなど、分けている理由が正当なものも混ざります)。
check-near-duplicates ★同名ではない「少しずつ違う実装」が複数箇所に増えている数。check-shared-parts-usedは同じ名前の関数しか拾えませんが、実際に増えるのはコピー&ペーストで名前や変数だけ変えた画面・カードです。行を正規化して連続する一致の塊を検出し、3ファイル以上に同じ塊があれば共通化のサインとして数えます。統合すべきかは判定しません(構造が違う同目的コードは拾えず、意図的な複製が混ざることもあります)。
check-doc-rot ★指示書(CLAUDE.mdなど)が「使うこと」と書いているファイルやスクリプトが、すでに存在しない状態を数えます。指示書は人が書いて人が守るものなので、書いた人がいなくなると黙って腐り、CIも赤になりません。実際に、最上位の指示が存在しない3つの実体を「使え」と命じていたのに誰も気づかなかったことがあります。リポ内パス・スクリプト名・npm scriptの呼び出しのように実在を確かめられる主張だけを見て、方針や思想といった文章の中身は判定しません。
check-orphan-worktrees ★git worktreeが片方向だけ切れた「孤児」になっている数。ディレクトリの移動やリポジトリの改名のたびに、登録側とフォルダ側のどちらかだけが古いパスを指したまま残ります。gitのどのコマンド(worktree remove/prune/list)でも自動修復されず、しかも異常には見えません。実際にディレクトリ整理作業で3つのworktreeが気づかないまま壊れました。双方向(登録→フォルダ/フォルダ→親リポ)を確認します。孤児を消してよいかは判定しません(データ消失リスクがあるため、検出のみに留めます)。
check-decision-receipt ★新規ファイルを作ったのに、既存を探して比べた記録(Decision Receipt)が無い状態を数えます。「共有部品があるのに使わない」を検知するcheck-shared-parts-usedとは別の問題——こちらはそもそも既存を探したかどうかを見ます。記録するのは REUSE / ESTABLISH_REHOME / CONTRACT / SYNC / KEEP_SEPARATE / LOCAL の6種類の判断のいずれかを選んだという客観的な事実だけで、その判断が正しかったかは判定しません(責務が本当に同じか等の判断は人・AIが行うものです)。
check-gate-bypass ★Gateを無効化・迂回して成功扱いにしている状態を数えます。.github/workflows/内のcontinue-on-error: trueや、コメントアウトされた検証ステップ(#- run: npm run verifyのような形)を検出します。正当な理由(実験的ステップ等)による使用か、Gate迂回の意図によるものかは判定しません——検出はあくまで客観的な事実(そのパターンが存在するか)に限ります。
check-hooks-wired ★Claude Codeのフック(.claude/hooks/)が「作ったのに設定から呼ばれていない」孤児になっている数を数えます。check-gates-are-wiredはpackage.json・CI・診断ランナーだけを見ており、.claude/hooks/は対象外でした。さらに、プロジェクト内では配線したのに、このPC全体に効くグローバル設定には反映し忘れるというズレも警告します(このキット自身が実際にこの取りこぼしを起こしました)。グローバル未反映が意図的かどうかは判定しません(プロジェクト固有のフックである可能性もあるため、警告に留めます)。
check-external-constants-freshness ★外の誰かが決めた数字(API単価・無料枠・審査要件など)をコードに写したまま古くなっている状態を見張ります。請求APIや価格ページは読まず、人が最後に確かめた日だけを見て「そろそろ確かめて」と知らせます。設定ファイルが無ければ「測れなかった」で、緑にはしません。
check-auth-domains-allowed ★アプリ内ログインが外部ブラウザへ飛ぶ設定を数えます。Capacitor の allowNavigation に、そのアプリが使っているログイン手段のドメインが入っているかを見ます(使っていない手段は要求しません)。iOS 固有で、設定ファイルを読むだけです。実機でログインが成功するかは見ません。
check-file-header-comment ★新しく追加したソースファイルの先頭に、役割・使い方・なぜ要るかのコメントが無い状態を数えます。新規だけが対象で、既存ファイルは見ません。コメントの中身が正しいかは、機械では見られないので判定しません。
check-claude-md-budget ★指示書(CLAUDE.md)の「必ず読む核」が太りすぎている状態を数えます。core:end マーカーまでの行数が上限(450行)を超えると赤。マーカーが無いプロジェクトは対象外です。核に入れる内容の良し悪しは見ません。
# まとめて診断(対象フォルダを指定)
node templates/diagnostics/run.mjs /path/to/your-project
💡 このキット専用の仕組みではありません。nodeが動く環境なら、 このリポジトリの外にあるどんなプログラムのフォルダに対してもそのまま実行できます。 追加インストールも不要(Node標準機能だけで動きます)。

🌅 起動画面は「自作しない」。世の中の標準どおりに作る

アプリを開いた直後に出る画像を起動画面(スプラッシュ)と呼びます。 世の中のアプリの起動画面は、たいてい普通にきちんと出ています。 それは各社が自作しているからではなく、逆に公式の標準どおりに作っているからです。

Capacitor には公式のアセット生成ツール @capacitor/assets があり、assets/ に元の画像を置くだけで、iPhone・Android・Webの全サイズを自動生成します。 ダークモード用も splash-dark.png という決まった名前を置けば公式が対応します。 ここに自前の生成処理を書き足す必要はありません。

実際に @capacitor/assets を動かした結果です。元の画像2枚から 26ファイル(通常13+ダーク13)が自動生成されました。自分で書いたコードは0行です。
誰がやるか内容
人(1回だけ)元の画像(2732×2732)をデザインしてリポジトリに置く
公式ツールiPhone・Androidの全サイズへ展開/ダークモード対応
このキット公式ツールが取りこぼす所だけを確認(下記3点)

公式に任せても、次の3つだけは自動で埋まりません。ここだけをキットが確認します。

確認すること放置するとどうなるか
元の画像があるか公式ツールは元画像が無いときエラーを出さず黙って飛ばすため、既定の画像のまま公開されます
既定の画像のままでないかネイティブ側は毎回作り直されるので、初期状態の画像が毎ビルド復活します
表示方法と背景色ここはプラグイン側の設定で公式ツールの管轄外。既定のままだとAndroidだけ縦に伸びます
npm run splash:check

★2026-08-24に方針を変えました。以前はこのキット自身が起動画面の画像を生成しており、 その自作部分が原因の不具合を、さらに自作の検査で見つける状態になっていました。 自作をやめて公式ツールに寄せ、約500行を削除しました。 残したのは上の3点だけです。

★この自動検査は設定と画像ファイルを確認します。端末ごとの色味や大きさの好みまでは判定できないため、 全部合格した後もiPhone・Android実機で最後に1回だけ目視します。

実際のアプリの起動画面(2026-08-27 実機で撮影・地色は実測)

「きちんと出ている起動画面」がどういうものかを、実機の画面録画から取り出しました。 地色は画像から実際に測った値です(推測ではありません)。 並べてみると、有名アプリほどやっていることは少ないと分かります。

8本を並べて分かったこと設計への意味
地色は「暗い色」か「ほぼ白」だけ
実測は #000000 / #111113 / #171B1E / #FEFEFE の4種類だけだった
凝った色やグラデーションは使われていません。ブランド色1色で十分です
置くものはロゴ1つ。多くて社名か待ちの印
(Instagram だけロゴを出さない)
キャッチコピー・説明文・ボタンは1本もありません。読ませる画面ではありません
ロゴを出す7本は、全て中央・大きすぎない 端まで広げず、周囲に十分な余白を取ります
1〜2秒で消える
録画8本はいずれも4〜7秒で、起動画面はその一部だけ
長く見せる画面ではありません。「読み込み中です」と伝えるだけの役目です
★Instagram だけ「ロゴを出さない」やり方
暗い地に、これから中身が入る場所を薄い箱で先に見せる(骨組み表示)
ロゴを出すのが唯一の正解ではありません。すぐ本画面の形を見せて待たせないという別の考え方です。ただし実装は重く、ネイティブの起動画面だけでは作れません

★やってはいけないことも、この8本が示しています。 文字を詰め込む・地色と画像の色を食い違わせる・ロゴを画面いっぱいに広げる—— どれも1本もやっていません。「地色1色+中央にロゴ」から外れたら、まず疑ってください。

★画像は見本であり、著作権は各社に帰属します。 設計の参考として実機の見え方を記録したものです。真似すべきは構図と情報量であって、 ロゴやデザインそのものではありません。

📁 使う前に:どこに置くか(これだけ守れば自動で繋がります)

このキットは1つの親フォルダの下に、プロジェクトを横に並べる形を前提にしています。 この形なら、検査は症状の定義も原因の索引も自分で見つけます(引数を渡す必要がありません)。

github/            ← 親フォルダ(名前は何でもよい)
  ├ ai-hub/         ← 原因の索引(index.json)★これが横に居ることが大事
  ├ web-ios-android/← このキット
  ├ your-app-a/     ← あなたのプロジェクト
  └ your-app-b/

探す場所は決め打ちしていません。下の順に見て、最初に見つかったものを使います。

探すもの見る場所(上から順に)
症状の定義 src/lib/symptomVerdicts.js → src/lib/symptoms.js → lib/symptomVerdicts.js
原因の索引 ../ai-hub/index.json → ai-hub/index.json → _docs/index.json

別の場所に置きたいときは、場所を渡してください。

node templates/diagnostics/check-symptom-index.mjs \
  --symptoms path/to/symptoms.js \
  --index    path/to/index.json

★見つからなくても、勝手に「問題なし」にはしません。 症状の仕組みをまだ入れていなければ「まだありません(skip)」と入れ方を案内し、 症状はあるのに索引だけ見つからないときは 「測れませんでした」として区別します (=入れたのに繋がっていない合図です)。

★検査そのものが「サボると赤くなるか」を確かめているか

2026-08-23、このキット自身が自分の掟を破っていることが分かりました。 診断3本に selftest が1つも無く、--selftest を渡しても 引数が無視されて「skip」で終了コード0を返していました。 = 壊れていても緑に見える状態です。

3本に手で足すだけでは、次に4本目を作った人が忘れたら終わりです。 そこで check-selftest-coverage.mjs が selftest を持たない検査の数を機械が数え、増えたときだけ赤くします。 いまの本数を上限として固定してあるので、減らすのは自由です。

★名前だけを見ません。コメントを除いた実コードで 引数を実際に読んでいるかまで確かめます (コメントに書いただけで通る穴を塞ぐため)。

★「共有するほど不具合が減る」を成り立たせる1本

症状が起きたとき、アプリは 症状ID(例 panel-black)を出します。 その言葉で過去の原因の索引を引ければ、次に同じ症状を見た人は 調べ直す往復が要りません。これが「共有するほど減る」の中身です。

ところが実測すると、症状ID 7件で索引を引いて ヒット率は 0% でした。索引には245件の登録があるのに、 症状の言葉と索引の言葉が別々だったためです。

check-symptom-index.mjs が 索引に無い症状の数を数えます。上の run.mjs を回せば一緒に走ります(症状定義と索引の場所は自動で探します)。原因が分かった症状を索引に足すと 緑になります(実演で 0% → 100% を確認済み)。 = 正しい方向にだけ報われる形にしてあります。

★「登録して」と頼む仕組みにはしません。頼む形(オプトイン)は このキットで3ヶ月で登録1件のまま死んだ実績があります。 ★この検査は索引の中身が正しいかは判定しません(正しさは人が確かめます)。

🔒 出荷前に「セキュリティ診断で満点」を内部確認+本体実測する

セキュリティ診断サービス(malwarecheck.siteなど)に自分のWebサイトを投げると、 セキュリティヘッダーの設定漏れや .env ファイルの公開放置などで 減点されることがあります。そこで、内部の先取り検査で直す場所を見つけ、 最後に malwarecheck.site 本体でも実測する2段階の検査にしています。

🌐公開URLに
GETするだけ
→
🔒ヘッダー・
露出を確認
→
🛡️本体でも
実測
→
💯両方100点を
確認
攻撃・侵入・総当たりは一切しません(外形の確認のみ)
# app.config.json の productionDomain を自動で読んでチェック
node templates/scripts/verify-security-score.mjs

★外部サービスへ送るのは公開URLだけです。秘密情報やローカルファイルは送りません。 SQLi/XSSの実注入テストやポートスキャン、パスワードの総当たりも一切行いません。 100点は外部から見える簡易診断の満点であり、「絶対安全」を意味しないことも 検査結果に毎回明記されます。

📱 レスポンシブ設計を抜け漏れなくチェックする

スマホ・タブレット・PCなど画面サイズが違うだけで、横スクロールが出たり 文字が読めないほど小さくなったりすることがあります。崩れやすい書き方を コードのまま先に見つけ、最後に実際のブラウザで見た目を確認する 2段階の検査にしています。

📄CSSを
静的解析
→
📱崩れやすい
書き方を検出
→
🖥️実ブラウザで
375〜1440pxを実測
→
✅横スクロール
ゼロを確認
見た目の最終判定は、自作の判定エンジンではなく実際のブラウザに任せます
# site/ 配下のCSS・HTMLを静的解析
node templates/scripts/verify-responsive-design.mjs

★「実際にどう見えるか」の判定は自前で再実装しません。ブラウザのレイアウト 計算をコードで完全再現するのは車輪の再発明であり、必ずズレます。 静的解析は「固定px幅」「viewportタグの欠如」「メディアクエリの不在」といった 崩れやすい既知パターンの先取りゲートに留め、正式な判定は実ブラウザでの 実測(375px・768px・1024px・1440pxで実際に開いて横スクロール・見切れを確認) に委ねています。

🛡️ ストアに出す直前だけ効く「出荷事故ゲート」

前の章の4本はどんなプログラムにも使える汎用でした。ここからは iOS/Androidアプリをストアに出すときだけ起きる事故を止めるゲートです。 いずれも「誰かが実際に踏んだ事故」から作られていて、想像で書いた項目は1つもありません。
(templates/scripts/ に全10本。うち下表の7本がストア提出専用、残りは前後の章で扱っています)

💥
実際に
踏んだ事故
→
🔒
ゲートに
する
→
✅
二度と
起きない

「気をつける」で終わらせず、機械が止めるところまでやる

ストア審査で弾かれる前に止める

ゲート止める事故(出典)
verify-ios-splash-not-default Capacitorの青いデフォルト起動画面がそのまま出荷される。 スプラッシュ用の元画像を置き忘れると生成がスキップされ、既定の画像のまま world に出る。 しかも生成ツールは旧ファイルを上書きせず別名で書くため、ファイル名のハッシュ比較では検出できない。 生成の「前」に既定画像のsha256を記録し、後で置き換わったかを直接照合する方式で解決している。
verify-android-splash-not-default 上のAndroid版。cap add android が置くプレースホルダ画像がそのまま残る事故を、同じ直接証拠方式で止める。
check-splash-config Androidだけ起動画面が縦に伸びる。 引き伸ばし設定(androidScaleType)の既定値は「引き伸ばし」で、 正方形の素材を縦長端末に敷くと歪む。iOS側は中央を切り抜くので、 放置するとiOSとAndroidで見た目が食い違う。 あわせて、背景色が4箇所で食い違っていないか(=起動直後に一瞬まっ白がチラつく条件)も見る。
check-splash-safe-circle 起動画面に「色の付いた円」だけが出る。 Android 12以降は起動画面のアイコンを円形に切り抜くため、 背景を焼き込んだ不透過の画像を渡すと全面が塗られて円になる。 素材が透過か、絵柄が安全円の内側かを確かめる。
verify-android-signing-config 未署名のAABができあがり、Play Consoleがアップロードを拒否する。 bubblewrapもCapacitorも build.gradle に署名設定を書いてくれないため、 何もしないと必ず未署名になる。ビルドの前に検査して、Playに弾かれる前に止める。
verify-signing-material-path 「CIが鍵を置く場所」と「build.gradleが鍵を読む場所」がズレる。 パスは相対解決されるため、ズレていても署名設定の注入自体は成功してしまい、 最後のビルドで初めて失敗が発覚する。1階層目で検出する。
verify-webdir-consistency capacitor.config.ts の webDir と、CIが実際に成果物を作る場所の不一致。 空のアプリが出来上がる事故を防ぐ。
verify-manual-setup-done 自動化できない手作業(ストアのアプリ枠作成など)が本当に終わったかを、APIで実在確認する。 「画面に手順を出すだけ」で終わらせず、終わったことを機械が確かめる。
lint-pre-submission 提出前の総点検。過去に却下された観点をまとめて再検査する。
💡 ゲートは「実際に踏んだ事故」からしか作られていません。 たとえば署名のゲートは「未署名AABをPlayに弾かれた」実体験、 スプラッシュのゲートは「デフォルト画像のまま出荷した」実体験が出典です。 だから項目が少なく、そのぶん1本ずつが確実に効きます。

「緑なのに何も検査していない」を潰す

いちばん怖いのは失敗が赤くなることではなく、何も見ていないのに緑になることです。 テストが「該当なし」で全部スキップされていても、画面上は緑のチェックマークが並びます。 これを見逃すと「ゲートを通したから大丈夫」という確信だけが残り、事故はそのまま出荷されます。

対策

check-instrument-ran が「その検査が本当に走ったか」を確かめます。 件数ゼロの緑・条件が合わず全スキップの緑を、合格として扱わせません。

⚠️ 実際にあった例:認証状態の保存ファイルが無いまま検査が走り、 中身のテストが全部スキップされていたのに CI は緑だった。 「ゲートが緑なのに症状が続くときは、そのゲートが何を見ていないかを読む」—— これはキットの設計原則として残してあります。

前提が無いときは、赤にせず「対象外」にする

gitリポジトリでない、package.json が無い——そういう「そもそも検査対象ではない」ものを 赤で止めると、赤が日常になり、誰も赤を見なくなります。 このキットは前提が無い場合を skip として扱い、 本物の赤だけが赤になるようにしてあります。

⏱️ 診断は「押したとき」ではなく、ずっと動いています(壊れて開けないときの備えつき)

不具合は、こちらが見ている時だけ起きるわけではありません。 キットで作るアプリは2秒ごとに自分の状態を測り続け、 気づいた異常をコピー1回で開発者に渡せる形にまとめます。この2つで1組です。 さらに、いちばん知りたい「重いとき」に診断画面そのものが開かなくなる弱点に備え、 ユーザーに頼まず開発側が自分で測る手順も同じ仕組みの一部として持っています。
⏱️2秒ごとに
自分を測る
→
📋コピー
1回
→
🔍原因が
分かる
鍵 1

見ていないときは止まります。画面が隠れているあいだは測定を停止するので、 電池もCPUも食いません。「ずっと動く」と「ずっと重い」は別です。

鍵 2

読む間隔は「書く側の間隔」で決めます。 「1秒でも遅れたら困る」といった感覚で決めると、人によって答えが変わり、根拠が残りません。 データを書いている側が何秒ごとに更新するか——これだけが動かない事実なので、そこから決めます。

鍵 3

コピーには「いつの値か」を必ず入れます。 30秒前の数字を「今の状態」として読むと誤診になります。 判定も正常/注意/異常/まだ測れていないの4つに分け、 「測れていない」を「正常」に混ぜません。

⚠️ 計器を増やすほど良い、ではありません。 実例では計器を100個まで増やしましたが、実際に原因を突き止めたのはごく一部でした。 1本足すたびに「この計器は原因に導いたか」で判定し、導かないものは消す——これが続けるコツです。

🚨 その診断画面が「重すぎて開かない」ときは?

🥵重くて
開かない
→
🖥️別の窓で
同じ規模を再現
→
📏数字が
出る
鍵 1

症状の出ている画面では測らない。重い画面をさらに操作すると、測ること自体が症状を悪化させます。 別のブラウザ窓に出荷物だけを読ませて、そこで測ります。

鍵 2

必要なのは「実データ」ではなく「実規模」。 たとえば「参加者857人」で崩れるなら、857個ぶんの部品を合成すれば再現できます。 本物の配信を待つ必要はありません。

鍵 3

「効いているはずの対策」の実文を読む。 実例では「25個目から小さくする」という対策が入っていましたが、実際の指定を読むと 小さくするだけで、個数は1個も減らしていませんでした。思い込みはここで壊れます。

⚠️ 測れなかったものは「測れなかった」と書く。 別の窓では画面の配置が本物と違うので、高さなどは正しく測れないことがあります。 そこで出た「0」を「異常なし」と読むと、誤診になります。

📈 その診断、バージョンを重ねるたびに「進化」させる

直しても直しても、別の場所がこっそり悪くなっていたら意味がありません。 ここからは「1回直す」だけで終わらせず、版を重ねるほど良くなったと数字で言い切るための 仕組みを、できるだけかみくだいて説明します。
📏新しい版で
数字を測る
→
📒台帳に
書き足す
→
🔍過去いちばん
良い版と比べる
→
🟢良くなった
ときだけ緑
悪くなっていたら、出荷する前に赤で止まります

①「前の版」ではなく「今までで一番良かった版」と比べる。
直前の版とだけ比べると、1版ごとの悪化はほんの少しなので誰も気づけません。 1→2→3→4と少しずつ悪くなっても、隣同士だと「+1」にしか見えないからです。 このキットは常に「これまでで一番良かった記録」と比較するので、 じわじわ悪化して元の悪い状態に戻っても必ず気づけます。

版測った数字くらべた相手判定
v1 2,400 KB(アプリの重さ) ―(最初の記録) 🟢 記録
v2 1,360 KB 過去最良 2,400 KB 🟢 改善(1,040 KB 軽くなった)
v3 2,000 KB 過去最良 1,360 KB 🔴 悪化(出荷前に止まる)
🛑 v3が赤になっても、直すか・悪化してよい理由を書くかのどちらかを選べます。 ただし理由を書いて通しても、次に比べる相手は「1,360 KB」のままです。 一度大目に見た値がそのまま新しい基準になってしまう(=基準がじわじわ緩む)ことを防ぐためです。

②「小さいほど良い」とは限らない。数字の向きは指標ごとに先に決めておく。
「軽い方がいい」「速い方がいい」は直感的ですが、すべての数字がそうとは限りません。 向きを間違えると、正しく直した人を「悪化させた」と誤判定して止めてしまうという 一番やってはいけない事故になります。

実際にあった数字の動き正しい判定もし「小さい方が良い」と決め打っていたら
エラー率 100% → 0% 🟢 改善(エラーが消えた) 🔴 誤って「退化」判定
描画の成功回数 2回 → 13回 🟢 改善(ちゃんと動くようになった) 🔴 誤って「退化」判定
読み込み間隔 3秒 → 12秒 🟢 改善(取りこぼしがなくなった) 🔴 誤って「退化」判定

だからこのキットは、数字が動いた「見た目」から良し悪しを推測しません。 指標ごとに「大きい方が良いか・小さい方が良いか」を先に人が決めて宣言してから、 その方向でだけ比較します。

仕組みの土台

この台帳は「間違った数字を書いたときだけ赤くなる」設計です。 「毎回書かないと赤くなる」ようにはしていません。書くこと自体を強制すると、 面倒なときにとりあえずの嘘の数字が入ってしまい、台帳の信頼が一度で崩れるためです。 記録を忘れた版は「悪化」ではなく「まだ測っていません」という別の扱いになり、 忘れたことに後から気づける形にしてあります。

💡 この台帳は、審査や申請の場面でもそのまま使えます。「軽くしました」「速くなりました」ではなく 「2,400KBが1,360KBになりました」「817秒かかっていた診断が5秒になりました」と、 実際に測った数字だけを並べて説明できるからです。
★台帳自体が死ぬ

台帳を作っても、手で書く数字は書き忘れた瞬間に死にます。 実例では、台帳を入れて8日後に調べたところ—— 10種類のうち自動で記録される2種類しか動いていませんでした。 その間に診断の所要時間は29.3秒→0.019秒と1,500倍も良くなっていたのに、 記録は1件も残っていませんでした。 つまり台帳は「改善している」と表示しながら、ほとんど何も測っていませんでした。

対策

「測れている数 / 全体」を常に出します。 放置されている数字は名前と「何版前か」を添えて見せます。 ただし書くことは強制しません——強制すると、面倒なときに 「とりあえず埋める」で嘘の数字が入るからです。

💡 「一度も記録が無い」と「測れるのに測っていない」は別々に出します。 前者は「まだ測る手段が無いだけ」かもしれないので、 同じ扱いにするとどちらから手をつければいいか分からなくなります。

🚨 その見張り役が「そもそも動いていない」ときは?

ここまでの仕組みには、最後に1つ穴が残ります。見張り役そのものが動かなくなっていたら、 何も起きないということです。赤くなって止まっているのに誰も気づかない状態は、 緑と同じくらい危険です。
✅通ったときだけ
印を残す
→
📌更新が
積み重なる
→
🔔離れすぎたら
知らせる
「悪くなった」ではなく「最近ちゃんと調べていない」を知らせます
⚠️ 実際にあったこと。ある開発現場で、測った数字を1つ書き間違えたまま 8日間ずっと赤になっていました。別の日には、単に走らせ忘れて また赤のまま。どちらも「品質が落ちた」のではなく、誰も見ていなかっただけです。
なぜ内側では気づけないか

動かなかったものは、何も言いません。 「無言だった」ことは、それ自身には分かりません(動いていないのだから)。 だから外側に記録を置き、必ず前へ進むもの(更新の履歴)と照らし合わせます。

通ったときだけ記録する

検査がちゃんと通ったときにだけ印が残る形にしてあります。 赤で止まっていれば印は残らないので、放置するほど差が開き、やがて知らせが出ます。

これも「赤」にはしない

知らせは「調べていません」であって「悪くなりました」ではありません。 ここを赤にすると、とりあえず印だけ付けて黙らせる動機を作ってしまうためです (台帳を無理に書かせると嘘の数字が入るのと、まったく同じ理由)。

💡 この仕組みの限界も書いておきます。印は手作業でも付けられるので、 本気で回避しようと思えば回避できます。これは「うっかり」を拾うための仕組みであって、 意図的なごまかしを防ぐものではありません。

🧭 作業前に「全文脈」をつかみ、作業後の学びを次へ戻す

数字を測るだけでは、なぜその直し方を選んだか・前に何を試して失敗したかが残りません。 完全版の計器は、作業を始める前にリポジトリの過去と現在を出典つきの1枚へまとめ、 検証後の結果を次の作業へ戻します。
🗺️全ソース・
Git全履歴
→
🧠確定・却下・
未確定を分離
→
🧪診断と実測で
確かめる
→
📚証拠つきで
次回へ戻す
同じ失敗をもう一度提案せず、前回の続きから始められます
取得できる全文脈

Git追跡ファイルとGitが表示する未追跡ファイルを全件数え、Gitの全コミット件名、現在の変更、 指示書、設計・事故の記録、数字の進化台帳を1枚にします。 各項目には元のファイルと行番号・hashが付くため、AIが要約だけで断定せず原文へ戻れます。

知識を3つに分ける

confirmed(証拠があり次回も守る)、rejected(実測で却下し、 もう繰り返さない)、pending(まだ仮説)を混ぜません。 確定と却下は証拠が無いと台帳へ書けないので、推測がいつの間にか仕様になる事故を防ぎます。

🔐 「全部読む」にも安全の境界があります。 .env、鍵、証明書、ローカル設定は存在だけを数え、本文もhashも読みません。 会話だけの判断・外部サービス・実機は自動取得できないため、取得していないものを 「把握済み」や「正常」に混ぜません。
💡 node scripts/run-instruments.mjs --deep --report .instrument-report.json の1本で、全文脈パケット、汎用診断、 数字の進化台帳、計器が走ったか、各selftestを最後まで実行します。 途中が黄色や赤でも止まらず、最後に赤 > 測れなかった > 緑の順でまとめます。

📊 そして、各アプリに「準備が何%まで進んだか」を出す

確認機能があっても、開発者しか結果を読めなければ進み具合は分かりません。 新しく作るすべてのアプリに、最新版・準備状況・問題の有無が分かるページを標準で作ります。
🧪動作を
確認
→
📄公開用の
要約を生成
→
📊本体で
進捗を表示
アプリ名・色・版・実測に合わせて、同じURL規則で自動生成
URLは全アプリ共通

https://<アプリ本体のドメイン>/check-shindan-version/ です。

たとえば soushin-suggest.link なら /check-shindan-version/、app.reply-suggest.link でも 同じ /check-shindan-version/ が本体の一部として作られます。

今回の導入事例:送信サジェスト

soushin-suggest.link の本体LPを具体例にします。

導入後は、利用者が知りたい短い更新情報を本体LPへ、詳しい動作確認を /check-shindan-version/ へ、同じ情報から同時に反映します。

進み具合と問題の有無を分ける

進み具合は、必要な確認がいくつ終わったかを表します。 現在の状態は、確認済み/確認中/問題あり/まだ未確認の4つです。 そのため「まだ確認していない」を問題なしにせず、何が残っているかと次にすることまで分かります。

💡 このキット自身にも同じ仕組みを適用しています。 固定の数字を説明文へ写さず、更新のたびに変わる実物を 更新情報と動作チェック で確認できます。Next.jsではApp Router、静的サイトでは index.html を生成します。
🔐 公開するのは状態・件数・短い根拠だけです。 .env、トークン、鍵、絶対パス、診断の生ログは公開レポートへ入れません。

💓 そもそも「重いテスト」を回さなくて済む形へ

ここまでの診断は、どれも数秒で終わります。いっぽう多くの現場には、 アプリを実際に起動して外から覗く重いテストが積み上がっています。 それは本当に必要なのか——実際に数えてみました。
⚠️ 実測(2026-08-24・実在の製品)。アプリを起動する検査が76本・1回22分ありました。 最後の完走で出た赤4本を1つずつ読んだところ、製品の不具合は0件。 3本は「仕様を変えたのに検査の期待値が古い」、1本は検査そのものの不具合でした。
では、実際の不具合は何が見つけたのか

同じ期間に見つかった本物の不具合5件の内訳です。

・使っている本人の報告…3件(「反応が悪い」「クリックで入らない」)
・アプリ自身が書き出した記録…2件(一覧が真っ白になる症状。数字から原因が確定)

重いテストが見つけたものは、0件でした。

🐢外から起動して
覗く(22分)
→
💓アプリが自分で
記録する
→
⚡数秒の検査+
実際の記録
「外から覗く」より「中から記録する」ほうが、実際に原因へ届いていました
★ただし、捨ててはいけない穴が1つある

記録は症状が出たときに書かれます。すると、

・本当に何も起きなかった
・記録する仕組みそのものが動いていなかった

この2つがまったく同じ見た目(無言)になります。 実際にある製品では、起動直後の異常が記録の仕組みを一度も通らず、 ログに何も残らないことが確かめられています。

だから「心拍」を置く

症状が無くても、一定間隔で1行だけ書く。それだけです。 こうすると最後の心拍から「いつ動かなくなったか」が分かり、 無言と正常をようやく区別できます。 これを見るのが check-heartbeat-present です。

💡 順番を間違えないでください。先に重いテストを捨ててから 「実は見えなくなっていた」は取り返せません。 心拍を入れ、実際に症状を捕まえられることを確かめてから、 対応する重いテストを1本ずつ外します。
⚠️ この検査自身が、作っている最中に「合格」を3回まちがえて出しました。 ①同じファイルに部品が2つ在るだけ ②1回しか実行されない記録を心拍と誤認 ③別の関数の記録を拾っていた——の3つです。 3つとも自己検査に固定してあるので、同じ嘘は二度と出ません。

📵 「スマホを手で触って確認する」を無くす

不具合を見つける方法が「実機を手で操作して、気づいたらChatworkにスクショと メモを残す」だけだと、記録が人によって残ったり残らなかったりします。 後から見返せず、直ったのか不安になる原因はここでした。
⚠️ これまで起きていたこと。実機を外に持ち出して操作 → 気づいた不具合を Chatworkに書く → 直したつもりで終わる → 同じ不具合が後日また見つかる。 一次情報がチャットの投稿に散らばっていて、後から誰も見返せません。
代わりにやること

確認・再現・記録・修正・再確認は、すべてAIがPC上で完結させます。 ユーザーに「触ってみてください」と依頼しません。

🖥️PC上の
ブラウザで確認
→
🔌足りない分だけ
PC接続の実機
→
📁証拠を
リポジトリに保存
Chatworkは共有用。一次情報は必ずリポジトリに残す
優先順確認環境と使いどころ
1 PC上のブラウザ。本キットはCapacitor server.url連動型なので、 アプリの中身はほぼ本番Webそのもの。日常確認はここが基本で、UI不具合の大半は スマホを触らずに再現・確認できる。
2 PCに繋いだ実機。ブラウザで再現できないとき(通知・カメラ・位置情報・ 課金・機種依存の挙動、iOS/Android固有のネイティブUI)だけ使う。外に持ち出さず、 PCに繋いだ状態で確認する。
3 CI(GitHub Actions)上の検証。iOSシミュレータ等、Mac環境が要る確認は ここに任せる(例: ios-blackscreen-check.yml)。PC上で直接は測れないが、 自動化はできる場合。
4 手持ち実機を人が外で操作する確認。原則禁止。
推測で「大丈夫です」と言わない

不具合の有無はAIが自分で確認します。コードを読んで「動くはず」で済ませず、 実際に動かして確認してから報告します(「完膚なきまでの裏取り」の実行)。 「見た」「直したつもり」で終わらせず、修正後は同じ手順で再確認し、 比較用の証拠(before/after)も残します。

💡 一次情報の置き場所は固定です: qa/evidence/YYYY-MM-DD_機能名/{ios,android}_{before,after}.png と qa/evidence/<機能名>/notes.md、不具合台帳はqa/bugs.md。

🪞 この仕組みは、まず自分自身に使っています

道具をくばる側が自分で使っていない道具は、渡された側もまず使いません。 ここで説明した仕組みは、このキット自身の中で毎回動いています。
📦くばる
→
🪞自分でも
使う
→
🔧使えないと
自分が困る
だから放置されません
⚠️ くばっただけの道具は死にます。このキットには前科があります。 診断の土台は前から同梱されていたのに、入口が説明書の1行だけで誰も使いませんでした。 別の仕組みは配ったあと3か月で登録1件のまま止まりました。

いま実際に見ている数字は次の3つです。どれもこのリポジトリの中だけで数えられるものに 限っています(実機の速さのように、測るたび条件が変わる数字は自動では記録しません。 条件の違う数字を並べると、比べてはいけないものを比べることになるからです)。

見ている数字いまの値と、なぜ見るのか
診断キットの検査本数 6本(多いほど良い)。以前、検査が1本も走っていないのに 「全チェック緑」と表示されていた時期がありました。本数が減れば、 配っている検査が静かに消えたということです。
自己検査を持たない配布物 8本(少ないほど良い)。わざと壊しても赤くならない検査は、 気づかないうちに全部を通してしまいます。これから減らしていく対象です。
自己検査を持たない診断 3本(少ないほど良い)。新しい検査に自己検査を付け忘れると ここが増えるので、その場で気づけます。
💡 この3つは実際にコマンドを走らせて数えた値だけです。 見込みや目標は書きません。測らずに「こちらが良い」と決めてしまうと、 正しく直した人を「悪くした」と判定して止めてしまうためです。