SCALE_全システム実装ルール
SCALE 全システム実装ルール
「機能追加が退化を生む」を絶対に防ぐためのルール集。
過去完成した機能が、新しい実装で巻き戻る現象を体系的に潰す。
全システム編集時、このページを最初に Read。問題発生時は最初に 31_システム開発部/_SCALE_共通_トラブルシューティング集 を Read
v9.155 反省(架電リスト消失17回失敗)から作成した「過去エラー要因リスト + しらみつぶしチェックリスト + 再利用可能なトレーサ/ガード関数パターン集」。
推測で対策を積む前に、必ず過去パターンに該当するか確認すること。
30秒で全体像
| 観点 | 一言 |
|---|---|
| 核心 | 機能を「足す」だけ・絶対に「戻さない」ためのルール |
| キーワード | 保護資産 / changelog / 過去FB / スモークテスト / バックアップ |
| 使う人 | Claude(最優先)/ 全開発者 |
| 読了目安 | 5分(必読部だけなら2分) |
なぜこのルールが必要か
大串から繰り返し受けてるFB
- 「前にやった指摘の修正が、過去verに戻ってる」
- 「機能追加するたびに、過去の機能が消えてる」
- 「常に機能を足していくはずが、退化してる」
退化が起きる主な原因
| # | 原因 | 対策 |
|---|---|---|
| 1 | Claude が既存ファイル全体を書き換えて過去修正を上書き | 必ず Read → Edit(Write全体書き換え禁止) |
| 2 | 古いバックアップから復元してしまう | 復元前に最新の tar.gz を必ず作成 |
| 3 | 複数の場所に同じファイルがある(Drive/ローカル等) | 配置マップを正本 にして単一マスター運用 |
| 4 | 過去FBが認識されず、再発 → 再修正失敗で逆戻り | 過去FB集大成 を必読化 |
| 5 | changelog 追記漏れで何が変わったか追跡不能 | changelog必須(最上段に追記) |
| 6 | デプロイ前にスモークテストしてない | 保護資産スモークテストを必須化 |
退化禁止フロー(編集の標準動作)
Step 1. セッション開始時(古いコンテキストを持ち込まない)
1. <a href="/n/b0dcb770c6.html" class="wikilink">31_システム開発部/_SCALE_全システム配置マップ</a> Read(パス把握)
2. 該当システムの _README Read(**特に「保護資産」セクション**)
3. 該当システムの changelog 最新10件 Read(直近の変更内容把握)
4. 該当システムの「過去FB」リスト Read(指摘済みポイント全部)
5. 本番URL アクセス → 現状動作確認(退化検知の基準を作る)
Step 2. 編集中(既存を絶対に消さない)
| ルール | 理由 | NG例 |
|---|---|---|
| 必ず Read → Edit | Write 全体書き換えで既存修正が消える | Write でファイル全体置換 |
| 既存関数の削除前に grep | 関数消失を防ぐ | 「不要そう」で削除 |
| 影響範囲を grep してから変更 | 他機能を巻き込まない | 単一ファイルしか見ずに変更 |
| 大規模変更は git diff 確認 | 意図しない変更を検出 | diff見ずにcommit |
| 保護資産リストを変更前に確認 | 「絶対変えない」を踏まない | 保護資産を不用意に編集 |
Step 3. デプロイ前(最終チェック)
1. tar.gz バックアップ(タイムスタンプ付き・必須)
例: scale-lead-backups/scale-lead-2026-04-28-1430.tar.gz
2. changelog.ts に追記(最上段に・必須)
3. grep で全関数存在チェック
4. 保護資産スモークテスト(後述スクリプト)
5. 過去FBチェックリスト確認(このシステムの過去FB全部)
6. git diff で意図しない変更がないか確認
Step 3.5. Preview Deploy 必須(2026-05-28 大串FB・恒久ルール・絶対遵守)
大串FB原文:
「正式なドメインで公開したやつを修正指示した場合は毎回プレビューデプロイでやって正式にOKでたら、本番に反映というルールにして!」
1. 修正指示を受けたら → 必ず preview deploy から開始
bash ~/Obsidian/scripts/scale_deploy.sh <system> preview
→ wrangler --branch=preview で固有URL生成・本番ドメイン無影響
2. preview URL を大串に共有 → 動作確認待ち
3. 大串が「OK / いいね / これで反映」と承認した後だけ prod deploy
bash ~/Obsidian/scripts/scale_deploy.sh <system> prod
→ wrangler --branch=main で本番ドメイン反映
承認なし prod deploy 禁止。ミス修正が本番に出て、ちょうど見ているユーザー(商談相手・パートナー・受注見込)に影響する事故を物理的に防ぐ。
対象: 公開ドメインを持つ全システム (scale-hp-showcase / scale-lead / scale-base / terasu-mgmt / lab-terasu / terasu-lens / scale-partner-* / scale-lead-manual / scale-hp-corporate / scale-hp-demo 他)
例外 (preview 経由不要):
- 大串が「すぐprodで」と明示 (緊急バグ等)
- typo 1行直し + 影響極小 + 即見て分かる
- cron等自動化からの定期同期 (修正指示由来でない)
- 大串自身が手動 prod 直叩きすると言った時
Vercel Pro 採用案件: vercel (preview) → 大串OK後 vercel --prod で同フロー
詳細: 90_Meta/CLAUDE_global Preview Deploy必須ルール / feedback_preview_deploy_required.md
Step 4. デプロイ後(退化検知)
最優先:デプロイ「成功」表示を信じず、本番への反映を実バイトで検証する(2026-06-24 大串FB「このミスおきないようにちゃんと学習して・システム開発のルールよ」)。wrangler/CLIが「Deployment complete / Success」と出てもデプロイ未達のことがある(実際 2026-06-24 TERASU CRMで、固有URLは新版なのに canonical 未更新・本番(crm.terasu.scale-group.co.jp)は古いv3.0.318のまま「直した」と完了報告した事故。大串が実機ブラウザで指摘して発覚)。
1. 本番URL(custom domain)のHTMLを実バイト取得(curl→ファイル保存→python/grepでverスタンプ抽出)して新verか確認。curl直のgrep表示は破損しうるのでファイル保存→python実バイトが確実。
2. Cloudflare Pagesは CF APIのcanonical_deploymentが今回のデプロイIDに更新されたか確認(accounts/9c601cdb4666c746e5cb97fa00187f06/pages/projects/{proj}・token=~/.cf_token)。固有URLが新版でも canonical(本番が指す)が古いままなら未反映。
3. デプロイ直前にローカルの実バイト状態(行数・キー関数grep -c)を再確認。Drive同期正本(~/株式会社SCALE/配下・Vault)は編集→デプロイ間に旧版へ巻き戻り得る(→~/devへgit移行が根治・SCALE Base横展開)。
4. ユーザーが「本番が古い/おかしい」と言ったら、自分のcurl確認より実機(ユーザーのブラウザ)を正とし、デプロイ先・反映を根本から疑う。自分の「確認できた」を過信しない。
1. 本番URL アクセス → 主要機能動作確認
2. 保護資産が全部動くか確認(チェックリストで1つずつ)
3. 過去FB項目の再確認(リスト順)
4. 失敗時は即ロールバック(最新バックアップから復元)
5. デプロイログを Daily / changelog に記録
保護資産(システムごとに定義)
各システムの _README.md に以下を必ず記載:
## 保護資産(絶対に消さない・変えない)
### 機能
- ◯◯機能(理由:◯◯ / 過去FB日付:YYYY-MM-DD)
- ◯◯機能(理由:◯◯)
### 関数
- function ◯◯()(grep で必ず存在確認)
- function ◯◯()
### 過去FB対応済みポイント
- 「◯◯はこうしてある」(FB日付:YYYY-MM-DD)
- 「◯◯はこうしてある」(FB日付:YYYY-MM-DD)
### スモークテスト項目
1. ログインできるか
2. 主要画面が描画されるか
3. 主要機能◯◯ がエラーなく動くか
→ 各システム _README にこのセクションを必ず置く。Claude はセッション開始時にこれを Read する。
changelog の書き方(全システム共通)
必須ルール
| ルール | 説明 |
|---|---|
| 最上段に追記 | 最新が最上段(時系列逆順) |
| 日時 + 変更タイプ + 内容 | 2026-04-28 [feat/fix/refactor] ◯◯機能を追加 |
| 退化リスクのある変更は警告 | [breaking] ◯◯ 削除(理由:◯◯) |
| デプロイURL 記録 | デプロイ後の本番URL(ハッシュなし) |
例(SCALE Base)
// lib/changelog.ts
export const CHANGELOG = [
{
date: "2026-04-28",
type: "feat",
summary: "Recruit機能に応募者ステータス管理追加",
details: "/recruit/applicants 画面に StatusBadge 追加",
deployedUrl: "https://scale-base.pages.dev/home/",
},
{
date: "2026-04-27",
type: "feat",
summary: "Finance ダッシュボードに月次P/L追加",
details: "/finance/dashboard に PLChart 追加",
deployedUrl: "https://scale-base.pages.dev/home/",
},
// ...
];
過去FB集大成(システム横断)
各システム _README に「過去FB対応済みポイント」を残すが、横断的なFBもここに集約:
大串からの全システム共通指摘
| FB | 対応 |
|---|---|
| デプロイ後は必ず本番URL確認 | npx wrangler pages deploy 後、URL アクセスして主要機能テスト |
| ハッシュ付きデプロイURL は送らない | 必ず pages.dev/home/ 等の本番URLを使う |
| 関数を勝手に消さない | grep で全関数チェック → 削除前に確認 |
| 既存システムの編集前にバックアップ | tar.gz 必須(特に SCALE CRM) |
| changelog 追記忘れ | SCALE Base の lib/changelog.ts 必須 |
| 1アカウント=1デバイス前提(SCALE Base) | KV同期不要・active-progress 等 |
| AI生成システム系のファイル整理時 | 触らず、手動編集ファイルのみ対象 |
過去FBの活用と横展開(2026-06-13 大串FB・恒久・最重要)
大串FB原文: 「過去したFBを活かしたアウトプット出すことと、ほかのシステムのFBで共通する部分は直すこと」
新機能・新画面・新システムを作るとき、ゼロから書くと過去のFBが全部抜け落ちる。実際 2026-06-13 の TERASU CRM PM部署 新実装で、過去に直したはずのFB(カクつき根治・モーダル入力消失防御・補足文章削除・削除確認・名前列sticky・グラデ廃止)が 7件まるごと再発し、事後監査で全部直す羽目になった。これを構造的に防ぐ。
ルールA: 過去FBを活かしたアウトプットを出す(実装の「前」に通す)
新しいコードを書く前に、そのシステムの過去FB+共通FBチェックリストを必ず一読して、最初から織り込む。事後監査ではなく事前適用。
全システム共通の「FB由来・実装デフォルト」チェックリスト(新UIを作るたびに通す):
| # | 過去FB由来のデフォルト | 出典FB |
|---|---|---|
| 1 | インライン編集は全体再描画せず該当セル/行だけ差し替え(カクつき防止) | 2026-06-09 |
| 2 | 重要入力モーダルは画面外クリックで閉じない + 入力ドラフト保持(_modalNoBackdropClose) |
2026-06-12 |
| 3 | モーダル/画面内に補足説明文を置かない(システム上に説明文は不要) | 2026-05-26 |
| 4 | 削除など不可逆操作は自前の確認(native confirm は出ない環境あり→2タップ/モーダル) | 複数回 |
| 5 | 一覧テーブルの名前/会社列は sticky(横スクロールで固定) | 2026-05-26 |
| 6 | バー/グラフはグラデーション禁止・単色 | 2026-05-25 |
| 7 | select は showPicker で即開く + blur 200ms 遅延(option選択を拾う) | 2026-06-08 |
| 8 | 文字色は薄すぎ/白すぎNG(#cbd1da 系)・絵文字は Vault外UIのみ | 複数回 |
| 9 | 設定/並び順は全員共有データ(個人ローカルに閉じない) | 2026-06-10 |
| 10 | フォームは 2段階防御(action="javascript:void(0)" + onsubmit で preventDefault) |
2026-05-26 |
→ このリストは各システム _README / 最新基準点の「過去FB対応済みポイント」と合わせて読む。新FBが来たらここにも追記して育てる。
ルールB: 他システムのFBで共通する部分は横展開して直す
あるシステムで受けたFBが他システムにも該当するなら、言われなくても横展開して直す。1システムで直して終わりにしない。
- 例: SCALE CRM で「名前列 sticky」を直した → TERASU CRM の一覧にも同じ問題があれば直す
- 例: TERASU CRM で「モーダル入力消失防御」を入れた → SCALE Base / SCALE CRM の重要モーダルにも展開
- FBを受けたら「これは他のどのシステム・どの画面に該当するか?」を必ず1度自問する
- 横展開はそのセッションで全部やらなくてよいが、該当箇所を洗い出して spawn_task / handoff / Vault に残す(取りこぼし防止)
運用
- 新機能実装の着手前に本セクション + 該当システムの過去FBを Read(退化禁止フロー Step 1 に統合)
- 実装後に自己監査(上記リストで1件ずつ照合)してからデプロイ
- 新しいFBは「①このシステムの基準点 ②本共通リスト ③他システムへの横展開要否」の3点で処理
スモークテストチェックリスト(全システム共通)
デプロイ後に必ず動作確認:
共通チェック項目
□ 本番URL でログイン画面が出るか(crm.scale-group.co.jp/base/ 等)
□ ログインできるか(PW: ●●●●●●)
□ メイン画面が描画されるか
□ 主要ナビゲーションが動くか
□ 主要 API が叩けるか(CRM/Form/Call等の機能)
□ コンソールエラーが出てないか(F12 で確認)
□ 既存ユーザーのデータが消えてないか
システム別 重要チェック
各システム _README に固有のスモークテスト項目を記載。
自動化(後で実装)
check_deployment.sh(保護資産スモークテスト)
# 例: SCALE Base の保護資産チェック
~/Obsidian/scripts/check_deployment.sh scale-base
# 内部動作:
# 1. 本番URL アクセス → HTTP 200 確認
# 2. 主要エンドポイントの存在確認
# 3. 保護資産リスト(_README から抽出)の grep 検証
# 4. changelog 最新が今日の日付か確認
# 5. 失敗があれば Slack 通知(ノイズなら大串だけ)
緊急時のロールバック
退化が本番で発覚したら:
# SCALE CRM の例
cd /Users/oogushiyuuki/株式会社SCALE/scale-lead
ls /Users/oogushiyuuki/Library/CloudStorage/.../scale-lead-backups/ | tail -5
# 最新の動作確認済みバックアップを選んで展開
tar -xzf scale-lead-2026-04-27-1500.tar.gz
# デプロイ
./deploy.sh
→ 常に直前のバックアップを残しておくことが命綱。
関連ノート
- _SCALE_システム開発書 — 開発全体ルール
- _SCALE_全システム配置マップ — システム配置・パス全集
- _SCALE_全システム標準モジュール — 標準モジュール
- Claude_動き方ガイド — Claude動き方統合ガイド
- Claude_先回りパターン辞典 — Pattern 2 (コード変更) 参照
- CLAUDE (Vault) — Vault運用ルール
- 各システム _README の「保護資産」セクション
再発防止ルール(事故記録 + 対策)
過去の事故事例
事故 1: changelog.ts 全置換による履歴消失(2026-05-01)
何が起きた: pristine バックアップから changelog.ts の差し替え時に、3049行の過去履歴を188行に削減してしまった。getCategoryColor 関数も消失してビルドエラー。
原因:
- pristine バックアップを「最新」と誤認
- 配列全体を新内容で書き換える操作を行った
- 末尾のユーティリティ関数(getCategoryLabel / getCategoryColor)の存在を見落とした
対策:
- changelog.ts の編集は必ず最上段への append のみ(既存配列の閉じ括弧 ] より前に新規エントリを追加)
- 配列全体を書き換える Write 操作は禁止
- 末尾のユーティリティ関数は触らない
- 不安なら編集前に wc -l で行数を控えておき、編集後と比較
事故 4: 漢字ユーザー名を fetch ヘッダーに直入れして全 D1 PUT が失敗(2026-05-05・SCALE CRM)
何が起きた: fetch('/api/data/members', { headers: { 'X-User': '大串' } }) の形で 漢字を直接ヘッダーに入れていた。ブラウザは HTTP ヘッダーを ISO-8859-1 でしか送れないため、TypeError: String contains non ISO-8859-1 code point で fetch がブロックされ、全 D1 PUT (members 編集 / 自動同期 / スナップショット / エラーログ) が一切届いていなかった。
症状の出方:
- PM が漢字名 (大串) でログイン中の保存操作 → ローカルは更新されるが D1 に届かない
- _syncToSupabase 内の try/catch で握りつぶされてエラーが見えない
- 別端末でログインすると保存前の値が見える → 「保存したのに反映されない」と気付く
- マイグレーション以降数日間、PM の編集がほぼ全部 localStorage 止まりだった
原因:
- HTTP ヘッダーの ISO-8859-1 制約を知らなかった
- 漢字 (大串) / 絵文字 / 全角文字 をそのままヘッダーに入れる実装が複数箇所にあった(クライアント6箇所)
- try/catch で fetch エラーを握りつぶしていて、実害が表面化するのが遅れた
対策:
- fetch ヘッダーは必ず ASCII safe: encodeURIComponent(currentUser || 'system') でラップ
- サーバー側は decodeURIComponent で復元(try/catch で安全化):
ts
const user = (() => {
const raw = request.headers.get('X-User') || 'unknown';
try { return decodeURIComponent(raw); } catch { return raw; }
})();
- fetch を握りつぶす try/catch には必ず console.warn を出す(隠蔽するな)
- 保存系の重要処理は HTTP status を確認 + 失敗時に alert 警告(v9.14 で追加した方針)
事故 3: index.html のキャッシュバスター固定によるブラウザ古JS実行(2026-05-04・SCALE CRM)
何が起きた: SCALE CRM の index.html で <script src="pages.js?v=20260424a"> のように ?v=を固定値にしていた。4/25 以降に追加した関数(getSectionPerm 等)をデプロイしても、ブラウザは「同じURL = キャッシュ済み」と判断して 古いJS(4/24版)を読み続けた。F12 Console には ReferenceError: getSectionPerm is not defined がずっと出ていたが、admin/PM ログイン時は症状が見えにくく、約1週間気付かれなかった。
症状の出方:
- y-ogushi@scale-group.co.jp(admin/PM)でログイン → 左下バッジが「PM」固定なので症状が見えない
- backoffice@scale-group.co.jp(パートナー)でログイン → 左下バッジが「パートナー(LinkedIn)」になるべきが「パートナー」のままで初めて症状表面化
原因:
- 静的キャッシュバスターを手動更新する運用にしていた → 更新を忘れた
- デプロイ後の確認を「動作するか」だけで済ませており、F12 Console エラー確認の習慣がなかった
- admin 権限ユーザーでしか動作確認していなかった
対策:
- キャッシュバスターは固定値で書かない。deploy.sh が node 経由で ?v=YYYYMMDDh を毎回自動更新する仕組みを必須化
- デプロイ後は必ず F12 Console を開いて console.error/warn がないか確認
- admin と非admin(パートナー等)の両方でログイン確認する
該当 deploy.sh パターン(他システムにも展開推奨):
CACHE_VER="$(date +%Y%m%d)$(date +%H%M | head -c 1)"
node -e "
const fs=require('fs');
let html=fs.readFileSync('index.html','utf8');
html=html.replace(/\\?v=\\d{8}[a-z]/g,'?v=${CACHE_VER}');
fs.writeFileSync('index.html',html);
"
事故 2: pristine 復元による Task ナビ巻き戻し(2026-05-01)
何が起きた: 「最新」と思って復元した pristine が実は古い時点のスナップショットで、Task ナビが旧構成(14項目)に巻き戻った。CLAUDE.md の「Task ナビ構成変更禁止」ルールに違反する状態に。
原因:
- バックアップタイムスタンプだけで「最新」を判断
- 復元時に対象ファイルの内容差分を確認しなかった
対策:
- 復元時は対象ファイルを限定(systems.ts や changelog.ts はファイル単位で個別判断)
- 復元元の特定ファイルが「最新仕様」を持つか必ず内容確認
- Task ナビは 5 項目構成(作業報告 / タスク管理 / レポート / カレンダー / 設定)が確定。これと違ったら復元元が古い
必須ルール(毎回守る)
0. 編集前の現状チェック(必須・最初)
SCALE Base なら以下を必ず実行してから編集を始める:
cd "/Users/oogushiyuuki/Library/CloudStorage/GoogleDrive-y-ogushi@scale-group.co.jp/マイドライブ/AI/scale-base"
bash scripts/check-current-state.sh
これで CLAUDE.md の最新スタンプ vs changelog.ts 最上段 を機械的に比較。古ければ復元してから作業。
_SCALE_Base_最新基準点 も必ず読む(最新スナップショットのラベルと当日変更が書いてある)。
1. 編集ルール
- Read → Edit のみ。
Writeで全体書き換え禁止 - 大きな配列ファイル(changelog.ts 等)は 既存内容に append が原則
- 末尾のユーティリティ関数を触る編集は行ごとに確認
2. 更新履歴の記載(毎回必須・4箇所セット)
システムをアップグレードしたら以下4箇所すべて更新:
1. lib/changelog.ts 最上段に新エントリ append
2. scale-base/CLAUDE.md の「最新スタンプ」を上書き (最新changelog ID と日時)
3. Vault の _SCALE_<システム名>_最新基準点.md の baseline_ts と「当日の変更」を更新(SCALE Base なら _SCALE_Base_最新基準点)
4. Vault の _SCALE_<システム名>_設計書.md の統合済み機能テーブルに追記(SCALE Base なら _SCALE_Base_設計書)
3. システム設計書を最新に保つ
- システム編集の都度、Vault の設計書を更新する
- 主要なシステム設計書:
- _SCALE_Base_設計書 — SCALE Base 仕様(編集の都度更新)
- _SCALE_Base_最新基準点 — SCALE Base 最新スナップショットラベル + 当日変更
- _SCALE_全システム配置マップ — 全システム配置・パス
- _SCALE_全プロダクト一覧 — プロダクト一覧
- 仕様変更(ナビ構成・データ層・認証等)は必ず設計書に反映
4. バックアップ運用
- 大きな変更前は
bash scripts/snapshot.sh --label=<作業名>でラベル付きスナップショット - 復元前に「最新」のスナップショットがどれかを内容で確認(タイムスタンプだけで判断しない)
- pristine 復元時は systems.ts と changelog.ts は手動確認 してから上書き
5. キャッシュバスター運用(2026-05-04 ルール化)
- HTML から JS/CSS を読み込むシステム(SCALE CRM・SCALE Base 等)では
?v=を固定値で書かない - deploy.sh で
?v=YYYYMMDDhを自動更新する処理を入れる - デプロイ毎に新しいバージョン文字列にすることで、ブラウザの古キャッシュを確実に無効化
6. デプロイ後の確認手順(2026-05-04 ルール化)
- 本番URLにアクセスして HTTP 200 確認(deploy.sh が自動)
- F12 Console を開いて
console.error/warnが出ていないか目視確認(ReferenceError等の致命傷を見逃さない) - admin と非admin(パートナー等)の両権限でログインして挙動を実機確認
- SCALE CRM の場合:
y-ogushi@scale-group.co.jp+backoffice@scale-group.co.jpの両方で確認
7. fetch ヘッダーは ASCII safe(2026-05-05 ルール化)
- HTTP ヘッダーは ISO-8859-1 制約あり。漢字・全角文字・絵文字を直接入れると fetch が TypeError で失敗する
- ユーザー名等の動的値は
encodeURIComponent()でラップ してから入れる - サーバー側は
decodeURIComponent()+ try/catch で復元 try/catchで fetch エラーを握りつぶす場合、必ずconsole.warn(e)で痕跡を残す(隠蔽すると今回のような事故になる)- 保存系の重要 fetch は
await+ status 200 確認 + 失敗時 alert で気付ける形にする
8. HTML form は2段階防御 必須(2026-05-26 ルール化)
- 事故: TERASU CRM ログインフォームで
<form method="post" onsubmit="handleLogin()">のみだったため、JS が undefined になった瞬間にデフォルト送信 → POST/→ HTTP 405 で全ユーザーログイン不可 - ルール: 全 form タグに以下の2段階防御を必須化
1. 第1層:action="javascript:void(0)"— デフォルト送信を物理的に無効化 (URL が javascript: プロトコルで no-op)
2. 第2層:onsubmit="event.preventDefault();try{...}catch(e){console.error(e)}return false"— JS 内のエラーを try-catch で握りつぶし + return false で送信防止 - どちらか1つが機能不全でも、もう1つで守る = 二重バリア
- 例:
```html