概要

項目内容
案件IDMAS-019
カテゴリFP&A・レポーティング(AI活用)
対象ファイル500_import/503_signal_importer.js(新規)、600_report/610_datamart_predictive.js(新規)
変更ファイル100_config/101_sys_config.js(スキーマ追加)、000_infra/001_env.js(外部APIキー accessor 追加)
新規シート95_ext_signals(外部シグナル格納)、66_pl_predictive(予測結果出力)
前提案件なし
所要時間2〜3 営業日(外部データソース選定・APIキー取得は除く)

目的

売上実績(JournalRepository.findAll() 経由の JournalEntryDTO)と外部シグナル(外部 API から取得するマクロ経済指標・業界指標等)を YYYY-MM キーで結合し、GAS 上の簡易重回帰分析による売上予測を実現する。

生成される予測値は意思決定支援の参考情報であり、最終判断は人間が行う(CLAUDE.md プロダクトポリシー「Human-in-the-Loop」準拠)。予測値を自動で予算シート等に反映することはせず、66_pl_predictive 上で可視化するのみに留める。

将来的には Vertex AI(ADR-0008)への移行を視野に入れるが、初期実装は GAS 内で完結する単純な重回帰モデルとし、相関係数・回帰係数を明示することでブラックボックス化を防ぐ。

前提とする既存実装

  • JournalRepository.findAll()200_data/202_repository.js L270-L272): 戻り値 { headers: string[], dtos: JournalEntryDTO[] }readSheetAsDtos_() による読み取り。
  • JournalEntryDTO000_infra/003_contracts.js L97-L129): 発生日(P/L計上日) / 科目名 / 税抜金額_実績 / 収支区分 等を含む。売上フィルタは 収支区分 === "収入" かつ 科目名 === "売上高" を基本とする(実データ検証で確認)。
  • Utils.parseDateToYm(val)000_infra/004_utils.js L92-L99): Date / "YYYY/MM" / "YYYY-MM" / "YYYY年MM月""YYYY-MM" 形式。パース不可なら空文字。全時系列データの年月キー統一に使用。
  • Contracts.toDtoList(data)000_infra/003_contracts.js L197-L204): getDataRange().getValues() の結果(ヘッダー含む)→ { headers: string[], rows: Object[] }
  • Contracts.toRows(headers, dtos)000_infra/003_contracts.js L229-L231): DTO 配列 → ヘッダー順の 2 次元行配列。
  • Contracts.toRow(headers, dto): 単一 DTO → 1 行配列。ヘッダー未定義項目は空文字で埋まる。
  • Env モジュール000_infra/001_env.js): 環境依存値の一元アクセス。現状の accessor は spreadsheetId() / geminiApiKey() / receiptFolderId() / backupFolderId() の 4 種。本案件では Env.estatApiKey() を新設する(scriptProperty 名は ESTAT_API_KEY)。PropertiesService.getScriptProperties() の直接呼び出しは CLAUDE.md 規約で禁止。
  • Utils.logInfo(funcName, message)000_infra/004_utils.js L232-L234): 通常ログ出力。
  • Utils.logError(funcName, error, context)000_infra/004_utils.js L242-L256): エラーログ + スタックトレース + 永続ログ記録。
  • Utils.toastResult(funcName, message, duration)000_infra/004_utils.js L258-L261): トースト通知 + console.log。デフォルト 5 秒。
  • UrlFetchApp.fetch(url, options): 500_import/502_receipt_reader.js L218-L224 のリトライパターンを参考にする(HTTP ステータス確認 + リトライ上限 + sleep)。
  • setupAllSchemas100_config/101_sys_config.js L749 以降): 宣言的にスキーマを追加する。schemas オブジェクト(L826-L901)の末尾 'CAT_MENU' エントリ(L900)の直後(L901 の閉じブレース直前)に新規エントリを挿入する。confSheet.appendRow による 01_sys_config へのキー登録(L772-L823)にも新規シートキー 2 件を追加する。

新規実装方針(Step 1〜4)

Step 1: 外部データ取得(500_import/503_signal_importer.js

  • エントリ関数: importExternalSignals()
  • API 呼び出し: UrlFetchApp.fetch(url, options) で外部 API を呼ぶ。502_receipt_reader.js L218-L224 のリトライパターン(HTTP ステータス確認 + 最大 2 回リトライ + Utilities.sleep())を踏襲する。
  • API キー取得: Env.estatApiKey()(新規 accessor)で取得。未設定時は Utils.toastResult() で通知し処理中断。
  • 月次化: 取得データを Utils.parseDateToYm()YYYY-MM 形式に変換。日次・週次データは月平均で集計する。
  • 書き込み方式: 洗い替え方式。
    1. 95_ext_signals の既存データ行(ヘッダー行以降)を sheet.getRange(2, 1, maxRows - 1, headers.length).clearContent() でクリア。
    2. Contracts.toRows(headers, dtos) で行配列に変換し、一括 setValues() で書き込む。
  • エラーハンドリング: API タイムアウト / HTTP 4xx・5xx / JSON パース失敗時は Utils.logError(funcName, error, context)Utils.toastResult() で通知し処理中断(部分書き込みによるデータ破損を防ぐため、clearContent 前にエラー検知すれば書き込みを行わない)。

Step 2: データマート構築(600_report/610_datamart_predictive.js

  • エントリ関数: buildPredictiveDataMart()
  • 売上実績取得: JournalRepository.findAll()dtos を走査し、収支区分 === "収入" かつ 科目名 === "売上高" かつ 仕訳ステータス !== "仕訳振替" の行を抽出。発生日(P/L計上日)Utils.parseDateToYm() で年月キー化し、月別に 税抜金額_実績 を合計。
  • 外部シグナル取得: 95_ext_signals シートから Contracts.toDtoList(data) で DTO 化。対象年月 列を Utils.parseDateToYm() で正規化。
  • 結合: 年月キー(YYYY-MM)で { 月: { sales, signal1, signal2, ... } } の辞書を構築。

Step 3: 予測モデル(同 610_datamart_predictive.js 内に関数として分離)

  • 関数: runLinearRegression_(y, X)(内部関数。将来 Vertex AI 連携で差し替え可能なよう分離)
  • アルゴリズム: 簡易重回帰分析(正規方程式 β = (XᵀX)⁻¹ Xᵀy を 2〜3 変数までに制限して GAS 上で解く)。変数が 1 つなら単回帰に縮退。
  • ゼロ除算ガード: 特徴量の分散 = 0(全行で同値)の場合は当該変数をモデルから除外し、結果シートに「除外変数: XX」を記載。XᵀX の逆行列計算で行列式 = 0 になる多重共線性も同様に検知し該当変数を除外。
  • 出力指標: 各変数の回帰係数、全体の相関係数(R)、決定係数(R²)、MAPE(将来月の実績取得後に計算する欄として用意)。

Step 4: 結果出力(66_pl_predictive への書き込み)

  • 列構成: 対象年月 / 売上実績 / ベースライン予測(トレンドのみ) / 外部シグナル考慮後予測 / 外部シグナル1 / 外部シグナル2 / 補完フラグ / 注記 / 計算時刻
  • 書き込み方式: Step 1 と同じ洗い替え方式(clearContent → 一括 setValues)。
  • 将来月の外挿: 外部シグナルが未取得の将来月は、過去 6 ヶ月の線形トレンドから外挿した仮値を用いる。該当セルの 注記 列に「外挿値(参考)」を明記する。

影響範囲

  • 新規ファイル: 2 本
    • 500_import/503_signal_importer.js
    • 600_report/610_datamart_predictive.js
  • 変更ファイル: 2 本
    • 100_config/101_sys_config.jssetupAllSchemasschemas オブジェクト末尾(L900 直後)にスキーマ 2 件を追加。01_sys_config への confSheet.appendRow 登録(L820 付近)にシートキー 2 件を追加。
    • 000_infra/001_env.jsEnv.estatApiKey() accessor を追加(L72 付近の setBackupFolderId の直後に挿入)。
  • 新規シート: 2 枚
    • 95_ext_signals(シートキー: EXT_SIGNALS) — 外部シグナル時系列データ格納
    • 66_pl_predictive(シートキー: PL_PREDICT) — 予測結果出力
  • 既存機能への影響: JournalRepository は読み取りのみ利用のため既存動作に影響なし。setupAllSchemas は追記のため既存シートのスキーマ変更なし。

注意事項

  1. PropertiesService.getScriptProperties() を直接呼ばない(CLAUDE.md 規約)。外部 API キーは必ず Env.estatApiKey() 経由で取得する。
  2. 新規シートの命名規則: 95_ext_signals は 90 番台(システム補助)の空き番号、66_pl_predictive は 61〜65 番台 P/L 系の直後に配置。シートキー EXT_SIGNALS / PL_PREDICT101_sys_config.js 既存命名規則(4〜10 文字、大文字 + アンダースコア)に合わせる。
  3. 列参照はヘッダー名ベース(CLAUDE.md 規約)。indexOf で解決し、列番号のハードコード禁止。
  4. 有効フラグ=FALSE の行は全処理でスキップ(CLAUDE.md 規約)。95_ext_signals のスキーマにも 有効フラグ 列を先頭に配置する。
  5. setupAllSchemas への追加後は DDL 再実行が必要。動作確認手順に 📋 サイドバー: 🔧 開発・設定 → DDL 全更新 (Full) の実行を含める。
  6. 造語禁止: 仕様書内に登場する全てのメニュー名・関数名・シート名・シートキーは、Phase 1 の Read で確認した実在する文字列のみ使用。
  7. API 費用の上限監視: 外部 API は従量課金の可能性がある。本実装では月次バッチ 1 回のみ呼び出す設計とし、スクリプト内から頻繁に呼ばれない構造にする(ユーザー手動起動を基本)。
  8. 冪等性: importExternalSignals() および buildPredictiveDataMart() は複数回実行してもシートに重複行が残らないことを保証する(洗い替え方式を厳守)。

エッジケース

条件挙動・表示値理由
外部APIタイムアウト / HTTP 4xx-5xx処理中断。Utils.logError + Utils.toastResult でユーザー通知し、95_ext_signals には書き込まない洗い替え前に中断することで部分書き込みによるデータ破損を防ぐ
レートリミット超過(HTTP 429)Utilities.sleep(2000) で待機後リトライ(上限 2 回)。上限超過時は処理中断・通知無限ループ防止。502_receipt_reader.js L218-L224 のパターンを踏襲
API キー未設定Env.estatApiKey() が空文字を返したら Utils.toastResult で「ESTAT_API_KEY をスクリプトプロパティに設定してください」と通知し処理中断CLAUDE.md 規約に従い PropertiesService 直接参照はしない
特定月の外部シグナル欠損直近有効値で前値補完し、該当行の 補完フラグ 列に TRUE をセット線形補間は初期実装のコストに対してメリットが小さいため前値補完を採用
外部シグナルが日次・週次データ503_signal_importer.js 内で月平均(単純平均)に集計して書き込み売上実績は月次のため粒度を統一する
将来月の外部シグナル未取得過去 6 ヶ月の線形トレンドから外挿した仮値を用い、66_pl_predictive注記 列に「外挿値(参考)」を明記Human-in-the-Loop: 外挿値を採用するか否かは人間が判断
重回帰の特徴量の分散 = 0(ゼロ除算)当該変数をモデルから除外し、結果シートに 除外変数: XX(分散ゼロ) を警告表示ゼロ除算によるランタイムエラー防止
多重共線性で XᵀX の行列式 ≒ 0逆行列計算前に行列式を確認し、閾値(例: 1e-10)未満なら最も相関が高い変数のみに縮退。警告表示数値不安定性の回避
外部シグナルと売上の相関が低い(r < 0.3)結果シートに 予測精度が低い可能性があります(相関係数: X.XX) を警告表示ブラックボックス化防止。ユーザーが予測値の信頼度を判断できるようにする
売上実績データが 6 ヶ月未満モデル学習をスキップし、Utils.toastResult で「実績データ不足(6 ヶ月未満)のため予測を実行できません」を通知最低サンプル数未満では予測精度が保証できないため
売上データが 収支区分 === "収入" で 0 件「売上実績が見つかりません。科目名 マスタおよび仕訳振替設定を確認してください」を通知し処理中断誤った科目名フィルタによる空データでの実行を防ぐ
仕訳振替ステータスの混入仕訳ステータス === "仕訳振替" の行は売上集計から除外CLAUDE.md 会計ロジック規約「仕訳振替の判定は === "仕訳振替" の完全一致」準拠
洗い替え処理の冪等性同一処理を複数回実行しても 95_ext_signals / 66_pl_predictive に重複行が残らないclearContent → 書き込みの順序を厳守
有効フラグ = FALSE の外部シグナル行読み取り時にスキップCLAUDE.md 規約「有効フラグ=FALSE の行は全処理でスキップ」準拠

実データ検証

実装前に以下を MCP(Google Sheets MCP 等)または GAS エディタで確認する:

  • 11_mst_account の科目マスタ: 売上実績フィルタに使う科目名が実データでどう登録されているか確認する(例: 「売上高」単独か、「ソフトウェア売上」「コンサル売上」等が並存するか)。DDL コード値(MST_ACCT ヘッダーの 科目名)と実データの乖離がないかをチェックし、必要ならフィルタ条件を配列一致に拡張する。
  • 101_sys_config.jssetupAllSchemas(L826-L901): 既存シートキーの命名形式を再確認し、新規キー EXT_SIGNALS / PL_PREDICT が命名規則(4〜10 文字、大文字 + アンダースコア、意味が自明)に合っているか確認。
  • 000_infra/001_env.js: Env.estatApiKey() 追加にあたり、既存 accessor(spreadsheetId / geminiApiKey / receiptFolderId / backupFolderId)の実装パターン(L50-L71)を流用する。
  • 42_trn_journal の実データ: 売上仕訳の 発生日(P/L計上日) 列が Date 型で保存されているか、文字列として保存されているかを Utils.parseDateToYm() の両対応で確認する(この関数は両対応済)。
  • 空き番号の最終確認: 95_ext_signals / 66_pl_predictive が既存シートと衝突しないことを 01_sys_config シート上で目視確認する。

関連ドキュメント

ドキュメント関連箇所
docs/_internal/failure_patterns.md#18-#20(コード未読による固有名詞誤記)、#21-#24(Sheets 数式設計の落とし穴)
docs/prd.mdプロダクトポリシー(Human-in-the-Loop、予測値の役割定義)
docs/adr/0008-vertex-ai-consolidation.md将来的な Vertex AI 移行時のモデル差し替え方針
CLAUDE.mdPropertiesService 直接参照禁止、列参照ヘッダー名ベース、有効フラグ=FALSE スキップ、仕訳振替判定
docs/dev/dev_mas-016_funnel_forecast.md売上予測系機能の既存仕様書。本案件との予測アプローチの違い(MAS-016 はパイプライン確度、MAS-019 は外部シグナル)を認識するため参照

人間が検討すべき事項

  1. 外部データソースの選定(最重要・実装ブロッカー): どの外部シグナル(e-Stat 等の政府統計、Google Trends、業界指標、天候 API 等)をどの API から取得するかは、ビジネス判断に基づき人間が決定する必要がある。本仕様書では e-Stat API(政府統計 API。ESTAT_API_KEY で認証)を仮の実装例として進めるが、確定前にステークホルダーの承認を得ること。取得する指標は売上との理論的因果関係があるもの(例: 法人サービス業向けなら「企業向けサービス価格指数」等)を優先する。
  2. 外部 API キーの管理: Env.estatApiKey() を追加した後、GAS スクリプトプロパティに ESTAT_API_KEY を設定する必要がある。Env.isDev() で dev/prod を判別し環境別に設定する運用を確立すること。動作確認手順に含める。
  3. 予測精度の合格基準: MAPE(平均絶対誤差率)等の精度指標と合格ライン(例: MAPE < 20%)を事前に定義する。合格基準未達の場合に結果シートへ警告を出す閾値も決める(エッジケーステーブルでは仮に r < 0.3 を低相関の閾値としている)。
  4. 取得頻度・トリガー設定: 月次バッチ(GAS 時間ベーストリガー、毎月 1 日 AM 3:00 等)で自動実行するか、手動実行のみとするかを決定する。API 費用の観点からは手動実行が無難。
  5. 予測値の運用上の位置づけ: 生成される予測値はあくまで意思決定支援の「参考情報」であり、自動で 41_trn_budget(予算シート)等に反映しない。最終的な予算・計画は人間が責任を持って策定する(CLAUDE.md プロダクトポリシー「Human-in-the-Loop」準拠)。
  6. 個人情報・秘匿データの扱い: 外部 API レスポンスにアクセスログ等の個人情報が含まれないか、また取得データをスプレッドシートに保存することがコンプライアンス上問題ないかを確認する(特に取引先データとの組み合わせで個人特定可能性が生じないか)。

実装プロンプト(Claude Code 用)

あなたはGAS会計システム(bizlp-gas-accounting)のシニア開発者です。
案件 MAS-019「予測的分析と外部シグナル統合」を実装してください。

## 実行前タスク
以下のファイルを Read で確認してから実装を開始すること(推測で書かない):
- `000_infra/001_env.js` — Env モジュールの公開メソッド一覧を確認(既存: spreadsheetId / geminiApiKey / receiptFolderId / backupFolderId)。`Env.estatApiKey()` 新設時の実装パターンを `geminiApiKey` から流用
- `000_infra/003_contracts.js` — `Contracts.toDto` / `toDtoList` / `toRow` / `toRows` のシグネチャ確認(L182-L231)
- `000_infra/004_utils.js` — `Utils.parseDateToYm` (L92-L99) / `logInfo` (L232-L234) / `logError` (L242-L256) / `toastResult` (L258-L261) の引数形式を確認
- `200_data/202_repository.js` — `JournalRepository.findAll()` (L270-L272) の戻り値型 `{ headers, dtos }`。`readSheetAsDtos_` (L19-L29) / `appendDtosToSheet_` (L85-L101) のパターン確認
- `100_config/101_sys_config.js` — `setupAllSchemas` の `schemas` オブジェクト末尾 (L900 `'CAT_MENU'` エントリ直後、L901 の閉じブレース直前) への追記位置を確認。`confSheet.appendRow` 登録 (L772-L823) の既存命名規則も確認
- `500_import/501_cc_importer.js` — `UrlFetchApp.fetch()` 使用パターン
- `500_import/502_receipt_reader.js` L218-L224 — HTTP リトライパターン(最大 2 回 + `Utilities.sleep`)

## 修正対象ファイル
- 新規作成: `500_import/503_signal_importer.js`
- 新規作成: `600_report/610_datamart_predictive.js`
- 変更: `100_config/101_sys_config.js`
  - `schemas` オブジェクトに `EXT_SIGNALS` / `PL_PREDICT` の 2 件を追加(L900 直後)
  - `confSheet.appendRow(['EXT_SIGNALS', '', '95_ext_signals', '外部シグナル(F-19)'])` と `confSheet.appendRow(['PL_PREDICT', '', '66_pl_predictive', 'P/L予測分析(F-19)'])` を `SYS_TEST` や `WRK_CARD` 登録の近傍(L820 周辺)に追加
- 変更: `000_infra/001_env.js`
  - `setBackupFolderId` の直後(L72 付近)に `Env.estatApiKey()` を追加(`geminiApiKey` と同じパターンで `ESTAT_API_KEY` を読む)

## 実装内容

### 503_signal_importer.js(新規作成)
- エントリ関数: `importExternalSignals()`
- `UrlFetchApp.fetch(url, options)` で外部 API 呼び出し。HTTP リトライは `502_receipt_reader.js` L218-L224 のパターンを踏襲(最大 2 回 + sleep 2000ms)
- API キーは `Env.estatApiKey()` で取得。空文字なら `Utils.toastResult` で通知し中断
- 取得データを `Utils.parseDateToYm()` で月次化(日次・週次は月平均で集計)
- `95_ext_signals` への書き込みは洗い替え方式:
  1. ヘッダー行を除く既存データ行を `sheet.getRange(2, 1, maxRows - 1, headers.length).clearContent()` でクリア
  2. `Contracts.toRows(headers, dtos)` で行配列に変換し、`setValues()` で一括書き込み
- エラー時は `Utils.logError(funcName, error, context)` → `Utils.toastResult()` で通知し処理中断(`clearContent` 前にエラー検知した場合は書き込み自体を行わない)

### 610_datamart_predictive.js(新規作成)
- エントリ関数: `buildPredictiveDataMart()`
- `JournalRepository.findAll()` で仕訳を取得し、`収支区分 === "収入"` かつ `科目名 === "売上高"` かつ `仕訳ステータス !== "仕訳振替"` を満たす行のみ抽出
- `Utils.parseDateToYm()` で `発生日(P/L計上日)` を年月キー化し、月別に `税抜金額_実績` を合計
- `95_ext_signals` から `Contracts.toDtoList(data)` で DTO 化し、`対象年月` を `Utils.parseDateToYm()` で正規化
- 年月キーで結合し `{ ym: { sales, signal1, signal2, ... } }` 辞書を構築
- 内部関数 `runLinearRegression_(y, X)` で簡易重回帰分析:
  - 正規方程式 `β = (XᵀX)⁻¹ Xᵀy`。変数 1 つなら単回帰に縮退
  - 特徴量の分散 = 0 なら当該変数を除外し結果シートに警告
  - `XᵀX` の行列式が閾値(1e-10)未満なら多重共線性と判定し最相関変数のみに縮退
  - 相関係数 R、決定係数 R²、各変数の回帰係数を返す
- `66_pl_predictive` への書き込みも洗い替え方式
- 将来月の外部シグナル未取得部分は過去 6 ヶ月の線形トレンドから外挿し、`注記` 列に `外挿値(参考)` を明記
- 相関係数 r < 0.3 なら「予測精度が低い可能性があります(相関係数: X.XX)」を結果シートに警告表示

### 101_sys_config.js(変更)
- `schemas` オブジェクト末尾に以下の 2 件を追加(仕様書の行番号に従って L900 `'CAT_MENU'` エントリ直後に挿入):
  ```
  'EXT_SIGNALS': { headers: ["有効フラグ","対象年月","指標カテゴリ","指標名","数値","補完フラグ","データソース","取得時刻"], color: "#674ea7" },
  'PL_PREDICT':  { headers: ["対象年月","売上実績","ベースライン予測","外部シグナル考慮後予測","外部シグナル1","外部シグナル2","補完フラグ","注記","計算時刻"], color: "#674ea7" },
  ```
- `confSheet.appendRow` 登録をシートキーに合わせて 2 件追加

### 001_env.js(変更)
- `setBackupFolderId` の直後に `Env.estatApiKey` を追加(`geminiApiKey` と同じ 3 行パターン)

## 制約
- `PropertiesService.getScriptProperties()` を直接呼ばない(CLAUDE.md 規約)
- 列参照はヘッダー名ベース(`indexOf`)。列番号ハードコード禁止
- 有効フラグ = FALSE の行はスキップ
- `仕訳ステータス === "仕訳振替"` の行は売上集計から除外(CLAUDE.md 会計ロジック規約)
- 既存の `JournalRepository` / `Contracts` / `Utils` の実装を変更しない
- `setupAllSchemas` 以外の `101_sys_config.js` 既存コードを変更しない
- 仕様書・CLAUDE.md に記載されていない設計判断が必要な場合は実装を止めてユーザーに確認する

## エッジケース
仕様書「エッジケーステーブル」の全件を実装で対応すること。特に以下を確実に実装:
- API タイムアウト / HTTP 4xx・5xx でも `95_ext_signals` に部分書き込みが残らない
- ゼロ除算ガード(分散 = 0、行列式 ≒ 0)
- 売上実績 6 ヶ月未満時のスキップ通知
- 洗い替えの冪等性(複数回実行で重複行が残らない)

## 動作確認
1. `npm run push:dev` で開発環境にデプロイ
2. GAS エディタ左の「プロジェクトの設定」→ スクリプトプロパティに `ESTAT_API_KEY` を登録
3. スプレッドシートを開き直し、メニュー `📋 サイドバー: 🔧 開発・設定` → `DDL 全更新 (Full)` を実行。`95_ext_signals` / `66_pl_predictive` が作成されることを確認
4. GAS エディタから `importExternalSignals` を手動実行し、`95_ext_signals` にデータが書き込まれることを確認
5. GAS エディタから `buildPredictiveDataMart` を手動実行し、`66_pl_predictive` に実績・ベースライン予測・外部シグナル考慮後予測が出力されることを確認
6. 手順 4-5 を再実行し、どちらのシートも行数が増えない(重複しない)ことを確認(冪等性)
7. `42_trn_journal` の売上データが 6 ヶ月未満の状態で `buildPredictiveDataMart` を実行し「実績データ不足」通知が出ることを確認
8. `ESTAT_API_KEY` を一時的に未設定にして `importExternalSignals` を実行し、エラー通知が出て `95_ext_signals` に書き込まれないことを確認
9. `📋 サイドバー: 🧪 テスト` → `全テスト実行` を実行し、関連テストが通ることを確認

### 拡張思考の使用状況
| フェーズ | 拡張思考 | 備考 |
|---------|---------|------|
| 実行前タスク(Read) | あり | ファイル構造・実在パターンの把握 |
| 実装(Write/Edit) | なし | Read で確定済みの内容を清書 |

推奨実行モデル

工程推奨モデル理由
Phase 1(調査・設計)Claude Sonnet複数ファイル横断の既存パターン調査と設計確定が必要
Phase 2(新規ファイル実装)Claude Sonnet新規ファイル 2 本・既存ファイル変更の設計判断が必要。重回帰分析の数値計算ロジックも含む
外部データソース選定支援人間判断ビジネス要件に依存するため AI には委任しない

変更履歴

日付変更内容
2026-04-21初版作成

仕様書作成プロンプト(再現性・監査性のため必ず記録)

展開して表示

この仕様書は tasks/prompts/task_F-19.md<instruction> タグ配下の指示に従って Claude Code (Opus 4.7) が自律実行した結果作成された。

実行原則(v1.7):

  1. Phase 1(設計)で拡張思考を活用し、ファイル名・シート名・関数名・行番号・エッジケース一覧・Step 分割粒度を完全に確定。Phase 2(清書)では Phase 1 で確定済みの内容の書き下しに徹する。
  2. テキスト報告の禁止。tool_use なしに turn を終了しない。
  3. 4-5 分割の Write/Edit 実行(骨格 ~20 行 / 概要〜注意事項 ~300 行 / エッジケース〜人間検討事項 ~200 行 / 実装プロンプト〜変更履歴 ~250 行 / <details> プロンプト記録)。
  4. 各 Step で書く内容を具体指示。設計判断を Phase 2 実行時に持ち込まない。

Phase 1 で確定した値

項目確定値根拠
新規インポートモジュール500_import/503_signal_importer.js500_import/ に 501_cc / 502_bank / 502_receipt が存在、次の空き番号は 503
新規データマートモジュール600_report/610_datamart_predictive.js600_report/ に 601〜609 が存在、次の空き番号は 610
外部シグナルシート名・キー95_ext_signals / EXT_SIGNALS90 番台で 90_test_results / 91_fs_bs / 92_fs_pl / 93_kpi_dashboard / 98_audit_log が使用済。95 は空き
予測結果シート名・キー66_pl_predictive / PL_PREDICT61〜65 番台 P/L 系の直後。66 は空き
Env accessor 追加Env.estatApiKey() (scriptProperty: ESTAT_API_KEY)既存 accessor(geminiApiKey / receiptFolderId / backupFolderId)のパターンを踏襲
setupAllSchemas 追加位置101_sys_config.js L900 'CAT_MENU' エントリ直後(L901 閉じブレース直前)schemas オブジェクト末尾への追記
confSheet.appendRow 追加位置L820 付近(SYS_TEST / WRK_CARD 登録近傍)既存のシートキー登録ブロック内
DDL 実行メニュー📋 サイドバー: 🔧 開発・設定DDL 全更新 (Full)Constants.MENU_DEFINITION 内の実在文字列