💻 システム開発

SCALE_FORM_最新基準点

最終更新 2026年07月22日 / 31_システム開発部/_SCALE_FORM_最新基準点.md

SCALE FORM 最新基準点

これは何: フォーム営業の完全自動化ツール(リストを入れれば企業HPの問い合わせフォームを見つけて自動送信)。SCALE CRM(scale-lead)の姉妹システム。
正本コード: ~/dev/scale-form-sales/(GitHub scale-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) の一括描画に退化していた)
    CRM lib/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.tsNULバイト1個が混入していた(sender.company || '\0' という壊れたリテラル)。
    file(1) が "data" 判定になり grep が一切効かず、コード調査が空振りしていた。

教訓(他システムにも効く)

  1. UIを作り替える時は「旧実装が持っていた非機能要件」を必ず棚卸しする
    見た目は新しくなっても、仮想スクロール・差分同期・ポーリングのような画面に映らない機能は静かに消える
    旧版と新版で git show <旧commit>:app.js を突き合わせ、キーワード(digest/since/仮想スクロール/setInterval)の
    出現数を機械比較すると一発で分かる。
  2. str.includes('') は常に true。「空ならスキップ」のつもりの条件が「常にスキップ」になる古典的バグ。
    !!x && str.includes(x) の形にする。
  3. 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/health ok。

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 / sidebarsidebar-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-rowclass="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 を実測。

教訓(他システムにも効く)

  1. .modal-overlay / .mobile-overlay.show クラスで開閉する。CRMの style.css では
    opacity:0; pointer-events:none がデフォルトで .show が付いて初めて見える。
    style.display='flex' だけ変えると開いているのに透明・クリック不可という気づきにくい壊れ方をする。
  2. 器(index.html)と描画(app.js)は必ずセットで更新・検証する
    「app.js の必須関数チェックが通る=動く」ではない。app.js が参照するDOM IDが index.html に実在するか
    機械チェックを退化検知に入れるべき(SCALE FORM では未実装・要対応)。
  3. 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.shREQUIRED_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-5JST平日 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。

関連