最終更新: 2026/06/22 18:56
MAS-019: 予測的分析と外部シグナル統合
概要
| 項目 | 内容 |
|---|---|
| 案件ID | MAS-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.jsL270-L272): 戻り値{ headers: string[], dtos: JournalEntryDTO[] }。readSheetAsDtos_()による読み取り。JournalEntryDTO(000_infra/003_contracts.jsL97-L129):発生日(P/L計上日)/科目名/税抜金額_実績/収支区分等を含む。売上フィルタは収支区分 === "収入"かつ科目名 === "売上高"を基本とする(実データ検証で確認)。Utils.parseDateToYm(val)(000_infra/004_utils.jsL92-L99):Date/"YYYY/MM"/"YYYY-MM"/"YYYY年MM月"→"YYYY-MM"形式。パース不可なら空文字。全時系列データの年月キー統一に使用。Contracts.toDtoList(data)(000_infra/003_contracts.jsL197-L204):getDataRange().getValues()の結果(ヘッダー含む)→{ headers: string[], rows: Object[] }。Contracts.toRows(headers, dtos)(000_infra/003_contracts.jsL229-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.jsL232-L234): 通常ログ出力。Utils.logError(funcName, error, context)(000_infra/004_utils.jsL242-L256): エラーログ + スタックトレース + 永続ログ記録。Utils.toastResult(funcName, message, duration)(000_infra/004_utils.jsL258-L261): トースト通知 +console.log。デフォルト 5 秒。UrlFetchApp.fetch(url, options):500_import/502_receipt_reader.jsL218-L224 のリトライパターンを参考にする(HTTP ステータス確認 + リトライ上限 + sleep)。setupAllSchemas(100_config/101_sys_config.jsL749 以降): 宣言的にスキーマを追加する。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.jsL218-L224 のリトライパターン(HTTP ステータス確認 + 最大 2 回リトライ +Utilities.sleep())を踏襲する。 - API キー取得:
Env.estatApiKey()(新規 accessor)で取得。未設定時はUtils.toastResult()で通知し処理中断。 - 月次化: 取得データを
Utils.parseDateToYm()でYYYY-MM形式に変換。日次・週次データは月平均で集計する。 - 書き込み方式: 洗い替え方式。
95_ext_signalsの既存データ行(ヘッダー行以降)をsheet.getRange(2, 1, maxRows - 1, headers.length).clearContent()でクリア。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.js600_report/610_datamart_predictive.js
- 変更ファイル: 2 本
100_config/101_sys_config.js—setupAllSchemasのschemasオブジェクト末尾(L900 直後)にスキーマ 2 件を追加。01_sys_configへのconfSheet.appendRow登録(L820 付近)にシートキー 2 件を追加。000_infra/001_env.js—Env.estatApiKey()accessor を追加(L72 付近のsetBackupFolderIdの直後に挿入)。
- 新規シート: 2 枚
95_ext_signals(シートキー:EXT_SIGNALS) — 外部シグナル時系列データ格納66_pl_predictive(シートキー:PL_PREDICT) — 予測結果出力
- 既存機能への影響:
JournalRepositoryは読み取りのみ利用のため既存動作に影響なし。setupAllSchemasは追記のため既存シートのスキーマ変更なし。
注意事項
PropertiesService.getScriptProperties()を直接呼ばない(CLAUDE.md 規約)。外部 API キーは必ずEnv.estatApiKey()経由で取得する。- 新規シートの命名規則:
95_ext_signalsは 90 番台(システム補助)の空き番号、66_pl_predictiveは 61〜65 番台 P/L 系の直後に配置。シートキーEXT_SIGNALS/PL_PREDICTは101_sys_config.js既存命名規則(4〜10 文字、大文字 + アンダースコア)に合わせる。 - 列参照はヘッダー名ベース(CLAUDE.md 規約)。
indexOfで解決し、列番号のハードコード禁止。 - 有効フラグ=FALSE の行は全処理でスキップ(CLAUDE.md 規約)。
95_ext_signalsのスキーマにも有効フラグ列を先頭に配置する。 setupAllSchemasへの追加後は DDL 再実行が必要。動作確認手順に📋 サイドバー: 🔧 開発・設定 → DDL 全更新 (Full)の実行を含める。- 造語禁止: 仕様書内に登場する全てのメニュー名・関数名・シート名・シートキーは、Phase 1 の Read で確認した実在する文字列のみ使用。
- API 費用の上限監視: 外部 API は従量課金の可能性がある。本実装では月次バッチ 1 回のみ呼び出す設計とし、スクリプト内から頻繁に呼ばれない構造にする(ユーザー手動起動を基本)。
- 冪等性:
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.jsのsetupAllSchemas(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.md | PropertiesService 直接参照禁止、列参照ヘッダー名ベース、有効フラグ=FALSE スキップ、仕訳振替判定 |
docs/dev/dev_mas-016_funnel_forecast.md | 売上予測系機能の既存仕様書。本案件との予測アプローチの違い(MAS-016 はパイプライン確度、MAS-019 は外部シグナル)を認識するため参照 |
人間が検討すべき事項
- 外部データソースの選定(最重要・実装ブロッカー): どの外部シグナル(e-Stat 等の政府統計、Google Trends、業界指標、天候 API 等)をどの API から取得するかは、ビジネス判断に基づき人間が決定する必要がある。本仕様書では e-Stat API(政府統計 API。
ESTAT_API_KEYで認証)を仮の実装例として進めるが、確定前にステークホルダーの承認を得ること。取得する指標は売上との理論的因果関係があるもの(例: 法人サービス業向けなら「企業向けサービス価格指数」等)を優先する。 - 外部 API キーの管理:
Env.estatApiKey()を追加した後、GAS スクリプトプロパティにESTAT_API_KEYを設定する必要がある。Env.isDev()で dev/prod を判別し環境別に設定する運用を確立すること。動作確認手順に含める。 - 予測精度の合格基準: MAPE(平均絶対誤差率)等の精度指標と合格ライン(例: MAPE < 20%)を事前に定義する。合格基準未達の場合に結果シートへ警告を出す閾値も決める(エッジケーステーブルでは仮に r < 0.3 を低相関の閾値としている)。
- 取得頻度・トリガー設定: 月次バッチ(GAS 時間ベーストリガー、毎月 1 日 AM 3:00 等)で自動実行するか、手動実行のみとするかを決定する。API 費用の観点からは手動実行が無難。
- 予測値の運用上の位置づけ: 生成される予測値はあくまで意思決定支援の「参考情報」であり、自動で
41_trn_budget(予算シート)等に反映しない。最終的な予算・計画は人間が責任を持って策定する(CLAUDE.md プロダクトポリシー「Human-in-the-Loop」準拠)。 - 個人情報・秘匿データの扱い: 外部 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):
- Phase 1(設計)で拡張思考を活用し、ファイル名・シート名・関数名・行番号・エッジケース一覧・Step 分割粒度を完全に確定。Phase 2(清書)では Phase 1 で確定済みの内容の書き下しに徹する。
- テキスト報告の禁止。tool_use なしに turn を終了しない。
- 4-5 分割の Write/Edit 実行(骨格 ~20 行 / 概要〜注意事項 ~300 行 / エッジケース〜人間検討事項 ~200 行 / 実装プロンプト〜変更履歴 ~250 行 /
<details>プロンプト記録)。 - 各 Step で書く内容を具体指示。設計判断を Phase 2 実行時に持ち込まない。
Phase 1 で確定した値
| 項目 | 確定値 | 根拠 |
|---|---|---|
| 新規インポートモジュール | 500_import/503_signal_importer.js | 500_import/ に 501_cc / 502_bank / 502_receipt が存在、次の空き番号は 503 |
| 新規データマートモジュール | 600_report/610_datamart_predictive.js | 600_report/ に 601〜609 が存在、次の空き番号は 610 |
| 外部シグナルシート名・キー | 95_ext_signals / EXT_SIGNALS | 90 番台で 90_test_results / 91_fs_bs / 92_fs_pl / 93_kpi_dashboard / 98_audit_log が使用済。95 は空き |
| 予測結果シート名・キー | 66_pl_predictive / PL_PREDICT | 61〜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 内の実在文字列 |