💻 システム開発
SCALE_FORM_最新基準点
最終更新 2026年07月22日 / 31_システム開発部/_SCALE_FORM_最新基準点.md
SCALE FORM 最新基準点
これは何: フォーム営業の完全自動化ツール(リストを入れれば企業HPの問い合わせフォームを見つけて自動送信)。SCALE CRM(scale-lead)の姉妹システム。
正本コード:~/dev/scale-form-sales/(GitHubscale-group-jp/scale-form-sales・private)
本番: https://form.scale-group.co.jp/
設計の正本: _SCALE_FORM_開発依頼書
スタートカード: リポ直下CLAUDE.md(現在地はコードとgit logが真実)
基本情報
| 項目 | 値 |
|---|---|
| ローカルパス | ~/dev/scale-form-sales/ |
| GitHub | scale-group-jp/scale-form-sales(private) |
| Cloudflare Pages project | scale-form-sales |
| Cron Worker | scale-form-sales-cron(別Worker・worker-cron/) |
| D1 | scale-form-sales-db(8d541db4-a8c3-4c43-a5d4-30d55c976cb6) |
| R2 | scale-form-sales-shots(送信証跡スクショ) |
| デプロイ | git push origin main で自動デプロイ(2026-07-22〜・GitHub Actions が deploy.sh を実行・約40秒)。ローカル bash deploy.sh も併用可 |
| 命名注意 | 旧世代 Next.js 製「SCALE Form」(~/株式会社SCALE/scale-form/)とは別物。旧世代は触らない |
wrangler の D1 操作は環境変数 CLOUDFLARE_API_TOKEN(~/.cf_token)だとD1権限がなく 7403 エラー。unset して wrangler の OAuth 認証(~/.wrangler/config/default.toml)を使うこと。
UIルール(恒久・2026-07-21 大串指示)
UI/UXは SCALE CRM と完全に同じにする。変えるのは各セクションの中身と機能だけ。
style.cssは CRM のものとバイト単位で同一を維持(FORM独自の書き足しをしない)- 新画面はCRMに実在するクラスだけで組む(無いクラスを新造しない)
- フォーム=
.form-row/2カラム=.form-grid/絞り込み=.filter-row+.search-box - ページ上部ボタン=
.page-actions/バッジ=.badge+.badge-{色}/数値=.stats-grid>.stat-card - 本文は
.contentで包む/見出しは.page-header > .page-title-area + .page-actions - 開閉は
.showクラス方式(.modal-overlay・.mobile-overlay) - index.html(器)と app.js(描画)は必ずセットで更新
2026-07-22 09:24 v0.4.0 退化復旧+法務ゲート(本番LIVE)
大串「他残っているタスクはテスト以外ないの?完璧?」を受けて、依頼書(正本)と実装を全項目で突き合わせた結果、v0.3.0のUI刷新で §3-2 の必須要件が3つ落ちていたことが判明(UIを作り替えた際に旧実装の機能を持ち越せていなかった)。
- ①仮想スクロール復活(
.slice(0,1000)の一括描画に退化していた)
CRMlib/calllist_core.jsの_clVirtualRenderと同じスペーサー行方式。120件超で自動有効・
可視範囲+上下14行だけDOM化・行高は実測(16〜80pxのみ採用)・clientHeightが0のときは600pxフォールバック・
例外時は全件描画にフォールバック。実測: 1000件でDOM実行行が常に24〜38行。 - ②差分同期+③30秒ポーリング復活
since(10秒オーバーラップ)で更新行だけ取得/無変化はJSON比較でスキップ/digest(count・max_updated)が
一致したら取得自体をスキップ/30分に1回はfull/document.hidden中は休む。
これが無いと Cron自動送信でステータスが変わっても画面に反映されない。 - 法務要件のバグ(依頼書§5):
!body.includes(sender.company || '')は社名未設定時に
includes('')が常に true になり、送信元情報もオプトアウト文も一切挿入されなかった。
社名がある時だけ重複回避する形に修正(新旧比較スクリプトで再現・解消を確認)。 - live送信の前段ゲート: 会社名/連絡先(メールor電話)/オプトアウト文が欠けていたら実送信を中止。
dryrun は止めずに警告トーストを出す(silent fail 禁止)。 send-core.tsに NULバイト1個が混入していた(sender.company || '\0'という壊れたリテラル)。
→file(1)が "data" 判定になり grep が一切効かず、コード調査が空振りしていた。
教訓(他システムにも効く)
- UIを作り替える時は「旧実装が持っていた非機能要件」を必ず棚卸しする。
見た目は新しくなっても、仮想スクロール・差分同期・ポーリングのような画面に映らない機能は静かに消える。
旧版と新版でgit show <旧commit>:app.jsを突き合わせ、キーワード(digest/since/仮想スクロール/setInterval)の
出現数を機械比較すると一発で分かる。 str.includes('')は常に true。「空ならスキップ」のつもりの条件が「常にスキップ」になる古典的バグ。
!!x && str.includes(x)の形にする。- grepが空振りしたらファイルにNULバイトが混入していないか疑う(
fileが "data" と言ったら黒)。
tr -dc '\000' < f | wc -cで検出できる。
2026-07-22 09:04 GitHub Actions 自動デプロイ設定+deploy.sh の silent fail 根治
git push origin mainで本番自動反映(約40秒)。workflow はdeploy.shをそのまま実行するので、
ローカル手動と完全に同じ退化検知がCIでも必ず走る(器チェック・.show方式チェックを含む)。
repo secret にCLOUDFLARE_API_TOKEN/CLOUDFLARE_ACCOUNT_IDを登録。.md/docsのみの変更ではデプロイしない。- deploy.sh に U1/U2 の機械チェックを実装(前日の事故の根治)。わざと
sectionRootを消す/
style.display方式に戻す、を仕込んで両方 FATAL で止まることを実証済み。 - 設定過程で silent fail を2件発見して根治(他システムにも効く教訓):
1.npx wrangler ... | tail -3でデプロイ失敗の終了コードが握りつぶされていた。
パイプの終了コードは最後のコマンド(tail)のものになるため、set -eがあっても止まらない。
→set -o pipefailを追加+出力を切り詰めない(エラー本文が消えると原因が追えない)。
実際これでCIが「緑なのに本番未反映」という最悪の状態になっていた。
2. 本番検証が「バージョンマーカーの有無」だけで、古い版が残っていても検知できなかった。
→ 「今回のキャッシュバスター?v=が本番に出ているか」をポーリング照合(5秒×最大18回=90秒)に強化。
Cloudflare Pages の反映は十数秒かかることがあり、固定sleep 8では誤判定していた。 - 初回CI失敗の真因は
@cloudflare/puppeteer未インストール(form-engine.tsが import)→ workflow にnpm ci追加。 - 実測: Actions グリーン・本番
?v=202607220003反映確認・/api/healthok。
2026-07-21 10:17 v0.3.1 UIをSCALE CRMと完全同一に統一(d69f42a・本番LIVE)
大串「UI/UXめっちゃ大事。ログイン画面で指摘したように全く同じにして、各セクションの中身と機能だけ変えたい」を受けて全面統一。
- 見つかった事故: v0.3.0 で
app.jsだけ CRMシェル前提に書き換えて本番デプロイしていたが、
index.htmlが旧レイアウトのままで、app.js が要求するDOM(sidebar/sidebarNav/sectionRoot/
projectSelect/mobileOverlay/modalOverlay)が本番に1つも存在しなかった。
つまりログイン後の画面が機能しない状態で公開されていた(deploy.sh の必須ファイル・必須関数チェックは
app.js 側しか見ないので素通りした)。 - index.html を CRM と同一骨格に全面置換:
mobile-header/mobile-overlay/sidebar(sidebar-header
.logo-row/project-selector/sidebar-nav/sidebar-footer/appVersionBadge)/main > sectionRoot/
modal-overlay > modal。ログイン画面にもCRM同様の「ログインできない場合はこちら」(バックアップURL
scale-form-sales.pages.dev・ハードリロード手順)を追加。 - app.js の独自クラスを全廃してCRMの style.css 準拠に:
.field→.form-row/class="input"廃止
(.form-row配下で自動適用)/ flex2カラム→.form-grid/.toolbar→.filter-row+.search-box/
ボタンは.page-actions/.status-badge→.badge+badge-{色}/.stat-grid .kpi-row→.stats-grid/
.page-sub→.page-desc/ 本文は.contentで包む。FORM固有CSSは authBanner と toast だけに縮小。 - モーダル・サイドバーが「開いているのに見えない」不具合を修正(下の教訓参照)。
- 要対応キューの説明文を削除(恒久FB「セクションに説明文を置かない=タイトルと件数のみ」を適用)。
- 検証: ローカル実描画(ナビ5件・テーブル4行・バッジ8個・モーダル form-row 7 / form-grid 2・コンソールエラー0)→
本番 SFS-VER=v0.3.1・CRM骨格DOM全存在・独自クラス残骸0件・API 401ゲート・health ok を実測。
教訓(他システムにも効く)
.modal-overlay/.mobile-overlayは.showクラスで開閉する。CRMの style.css では
opacity:0; pointer-events:noneがデフォルトで.showが付いて初めて見える。
style.display='flex'だけ変えると開いているのに透明・クリック不可という気づきにくい壊れ方をする。- 器(index.html)と描画(app.js)は必ずセットで更新・検証する。
「app.js の必須関数チェックが通る=動く」ではない。app.js が参照するDOM IDが index.html に実在するかの
機械チェックを退化検知に入れるべき(SCALE FORM では未実装・要対応)。 - CRMを写経するときは style.css だけでなくHTML骨格ごと写す。style.css は子孫セレクタ
(.sidebar-footer .avatar等)が多く、親の構造が違うとスタイルが一切当たらない。
2026-07-21 午前 UI刷新(サイドバーナビ+5セクション化)本番反映・git整合(f33278c / 9db93b7)
- 前セッションで本番デプロイまで済んでいたが git commit だけ未実施の状態を発見(本番は
app.js?v=202607210900を配信済み・未コミット差分が app.js 561行変更+新規API2本)。構文・必須関数チェックを通してコミット+push し、本番とGitHub履歴を一致させた。 - UI刷新の中身:
renderNav/gotoSection/renderSectionによるセクション切替(対象リスト / キュー / キャンペーン / テンプレート / 送信ログ)+モーダル編集(openModal/closeModal)+モバイルはサイドバー開閉。 - 新API 2本:
/api/campaigns(文面×リスト×レート設定の単位)・/api/templates(差し込み変数+送信元情報)。どちらもproject_id必須+canAccessProjectゲート・per-row UPSERT・c_deleted論理削除(依頼書§3の地雷回避に準拠)。 - deploy.sh の
REQUIRED_FILES/REQUIRED_FUNCSを新UI・新APIに合わせて更新(退化検知が新構成を守る状態に)。 - 本番実測(wranglerの成功表示を信じない方針で全部実測): 新UI関数8種すべて本番 app.js に存在/
/api/campaigns・/api/templates・/api/sends・/api/meは未ログインで 401(認証ゲート有効)//api/health={"ok":true,"db":"ok"}/トップ HTTP 200。
2026-07-21 早朝 Phase 2 残タスク実装(6f9b438)
- Slack通知:
functions/_lib/slack.ts+/api/slack/setup。Bot Token 3段フォールバック/チャンネル自動作成/招待は1件ずつ個別フォールバック/送信サマリ通知(silent fail させない方針)。 - Cron自動送信Worker: Pages に cron が無いため別Workerで実装(
worker-cron/)。CF上にscale-form-sales-cronとしてデプロイ済(2026-07-21 08:13 JST)・スケジュール*/15 0-10 * * 1-5(JST平日 9〜19時に15分毎)・Worker内でJST営業時間/週末を再チェック。 - 必須radio非選択の改善:
required属性がなく「※必須」表記だけのラジオを検出/「その他」を優先選択。
2026-07-21 Phase 2 送信エンジン コア稼働(v0.2.0)
form-engine.ts: 検出(描画待ち強化)→差し込み→確認画面完遂→証跡ベース成功判定(完了文言/URL遷移が取れて初めて success。no-completion-evidenceは失敗扱い)。send-core.ts: 冪等(UNIQUE+事前チェック)・ドメインクールダウン・営業時間(JST)・レート制御・R2証跡スクショ・form_sends追記型ログ・KPI(検出率/送信完了率)。- API:
/api/send/run(admin/pmゲート・live はconfirmLive:true必須)・/api/sends(ログ+KPI)。 - UI: フォーム検出/ドライラン送信ボタン。live送信はUI非公開(大串承認後に開放)。
- ログイン画面を SCALE CRM と完全同一デザイン化(login-wrap/login-box/ロゴ/グラデボタン)。
2026-07-21 正式ドメイン公開
- form.scale-group.co.jp 公開(DNS CNAME追加=大串手動・SSL発行済・本番200/ログイン/health 実測済)。
2026-07-20 Phase 1 完了(大串レビュー済み)
- 認証(PBKDF2 + HMAC署名cookie + スライディング延長 + 名簿照合)/D1 per-row スキーマ(projects / member_rows / form_targets / form_campaigns / form_templates / form_sends / app_config)。
- フロント: ログイン→案件選択→対象リスト(仮想スクロール)→CSV取込。401バナー・verバッジ・トースト。
- Browser Rendering PoC 実証済み(実在3種・
docs/Phase1_PoCレポート.md): TERASU/contactで全フィールドマッピング成功。
D1 実データ現況(2026-07-21 10:05 実測)
| テーブル | 件数 | 備考 |
|---|---|---|
| projects | 1 | scale-internal |
| member_rows | 1 | 初期admin(大串) |
| form_targets | 3 | PoC対象 |
| form_templates | 1 | |
| form_campaigns | 1 | camp_test |
| form_sends | 1 | dryrun success・TERASU contactに5項目差し込み・R2スクショ実体あり |
フェーズ進捗
| Phase | 状態 |
|---|---|
| 1. 基盤+PoC | 完了・大串レビュー済み |
| 2. 送信エンジン | コア+Slack+Cron+UI 実装完了。残るは「少量の実送信(live)テスト」のみ |
| 3. 精度改善 | 未着手(失敗分類ループ・AIマッピング補助・人間フォールバックキュー・KPIダッシュボード) |
| 4. CRM連携+外販準備 | 未着手(channel=form・リストプール連携・アポ報告接続・テナント境界検証) |
live送信は実在企業のフォームに実際にメッセージが届く不可逆アクション。大串の明示承認が出るまで実行しない(UI非公開+API confirmLive:true の二重ゲートで物理的に防いでいる)。
既知の未了
- GitHub Actions 自動デプロイ未設定(今は
deploy.sh手動)。CRM/Base と揃えるなら要対応。 - 少量実送信テスト(大串承認待ち)→ その後 Phase 2 完了レビュー → Phase 3。
関連
- _SCALE_FORM_開発依頼書(設計の正本)
- _SCALE_全システム実装ルール
- _SCALE_共通_トラブルシューティング集(A10〜A13・E1〜E2 を継承)
- _SCALE_CRM_最新基準点(写経元
~/dev/scale-lead/)