MAS-231: GAS パフォーマンス最適化パス 1(バッチ I/O + キャッシュ + 数式静的化)
概要
| 項目 | 内容 |
|---|---|
| 案件 ID | MAS-231 |
| 案件名 | GAS パフォーマンス最適化パス 1(バッチ I/O + キャッシュ + 数式静的化) |
| カテゴリ | DevOps・パフォーマンス |
| 優先度 | P1 ★★★(全機能波及・SPA 化 / GCP 移行の前段として最小投資で最大効果) |
| 所要時間 | 約 2-3 週間(週 10h 前提・段階適用可) |
| 対象ファイル(新規) | 200_data/cache_layer.js(CacheLayer 名前空間・約 100 行)/ 900_test/perf_regression_tests.js(約 150 行) |
| 対象ファイル(変更・主要) | 200_data/202_repository.js(キャッシュ HOF 適用)/ 400_domain/407_rpa_orchestrator.js / 400_domain/410_subledger_engine.js / 600_report/601-608_datamart_*.js(10-15 ファイル合計) |
新規 03_sys_params キー | MAS231_CACHE_TTL_SECONDS(default 21600 = 6h)/ MAS231_CACHE_ENABLED(default true) |
| 前提案件 | MAS-233(パフォーマンス診断ツール)— 完了待ち or 並行実装。MAS-233 が 99_perf_log シートと Utils.perfStart/perfEnd を提供する想定 |
| 後続連携 | MAS-232(サイドバー SPA 化・最適化後にレイテンシ計測)/ MAS-236-240(GCP 移行・本案件で習得したパターンを Cloud Run / BigQuery 移行で再利用) |
| 吸収・再定義対象 | なし(既存最適化案件 dev_mas-134_setup_all_schemas_optimization.md は DDL 専用で本案件と非重複) |
目的
既存コードの 10-20% の書換で体感 3-5 倍の高速化を達成し、SPA 化(MAS-232)や GCP 移行(MAS-236-240)の前段基盤として最小投資で最大効果を実現。
CacheServiceレイヤー導入で マスタ取得を 10-30 倍高速化 (PartnerRepository.findAsMap等)- バッチ I/O 化で Action A/B / マート更新 / RPA 起票を 5x 高速化
flush()/ Volatile 関数 / 重い条件付き書式の削減でスプレッドシート全体のレンダリングを改善- Jr 採用(MAS-230)後のハンズオン教材として 「読みやすい最適化パターン」 を蓄積する副次効果
現在のコード
利用する既存 API
| API | 定義場所 | シグネチャ | 用途 |
|---|---|---|---|
Utils.getSheetByKey(key, fallbackName) | 000_infra/004_utils.js:302 | (key, fallback) → Sheet | バッチ I/O 対象シート取得 |
Utils.persistLog(level, funcName, message, detail) | 000_infra/004_utils.js:577 | (level, fn, msg, detail) | キャッシュ HIT/MISS / 最適化前後の計測ログ |
Constants.getParam(key, defaultVal) | 000_infra/002_constants.js:147 | (key, default) → string|number | MAS231_CACHE_TTL_SECONDS 等取得 |
CacheService.getScriptCache() | GAS 標準 | — | キャッシュ層の基盤 |
LockService.getDocumentLock() | GAS 標準 | — | 並行実行時のキャッシュレース対策(v2 候補) |
SpreadsheetApp.flush() | GAS 標準 | — | 削除対象(途中の flush)or 末尾 1 回保持 |
既存 Repository 群(キャッシュ適用候補・全 6 件)
| Repository | 用途 | 呼出頻度 (推定) | キャッシュ HIT 期待効果 |
|---|---|---|---|
PartnerRepository.findAsMap() | 取引先マスタ・全 RPA で使用 | 高 (1 実行で 10+ 回) | 10-30x |
AccountRepository.findAsMap() | 科目マスタ・全 RPA + マートで使用 | 最高 (1 実行で 50+ 回) | 20-50x |
PositionTemplateRepository.findAsMap() | HC ポジション | 中 | 5-10x |
HurdleRateRepository.findAsMap() | 投資ハードル | 中 | 5-10x |
SocialInsuranceTierRepository.findAsMap() | F-57 社保等級 | 中 | 5-10x |
PerDiemPolicyRepository.findAsMap() | F-57 出張規程 | 低 | 3-5x |
バッチ I/O 化対象関数 (Top 候補)
grep -nE "for.*getValue\(\)|getValue\(\).*for|for.*setValue\(\)|appendRow\b" 400_domain/*.js 600_report/*.js で抽出:
400_domain/410_subledger_engine.js(Action A/B・大量仕訳生成)400_domain/407_rpa_orchestrator.js(RPA 一括起票)600_report/601_datamart_ingest.js〜608_datamart_render.js(マート更新)200_data/202_repository.js(save/append)
実装着手時に grep で Top 20 関数を絞り込み、各関数の現状の I/O パターンと書換例を spec 着手前に確認する (Phase 1-3 のタスク)。
修正方針
Step 1: バッチ I/O 化(Top 20 関数の書換)
before (典型例):
for (var i = 0; i < n; i++) {
var v = sheet.getRange(i + 2, 1).getValue();
if (matches(v)) sheet.getRange(i + 2, 5).setValue('OK');
}
after (バッチ化):
var range = sheet.getRange(2, 1, n, sheet.getLastColumn());
var values = range.getValues();
for (var i = 0; i < n; i++) {
if (matches(values[i][0])) values[i][4] = 'OK';
}
range.setValues(values);
I/O 回数を 2n + 1 → 2 に削減。n=1000 で約 500x 改善。
Step 2: マスタキャッシュ層(200_data/cache_layer.js 新設)
// 200_data/cache_layer.js (新設)
var CacheLayer = (function () {
function _ttl_() {
return Number(Constants.getParam('MAS231_CACHE_TTL_SECONDS', 21600));
}
function _enabled_() {
var v = Constants.getParam('MAS231_CACHE_ENABLED', 'true');
return /^(true|1|yes)$/i.test(String(v));
}
function get(key, loaderFn) {
if (!_enabled_()) return loaderFn();
var cache = CacheService.getScriptCache();
var cached = cache.get(key);
if (cached) {
try { return JSON.parse(cached); } catch (_) { /* fallthrough */ }
}
var value = loaderFn();
try {
var serialized = JSON.stringify(value);
if (serialized.length < 100000) cache.put(key, serialized, _ttl_());
else Utils.persistLog('WARN', 'CacheLayer.get', 'Value > 100KB skipped: ' + key, '');
} catch (e) { Utils.persistLog('WARN', 'CacheLayer.get', 'put failed: ' + e.message, key); }
return value;
}
function invalidate(key) { CacheService.getScriptCache().remove(key); }
function invalidateAll(keys) { CacheService.getScriptCache().removeAll(keys); }
return { get: get, invalidate: invalidate, invalidateAll: invalidateAll };
})();
各 Repository に HOF パターンで適用:
// 200_data/202_repository.js (PartnerRepository 抜粋)
PartnerRepository.findAsMap = function () {
return CacheLayer.get('partner_map', function () {
return _findAsMapImpl_(PartnerRepository._getSheet());
});
};
PartnerRepository.save = function (dto) {
var result = _saveImpl_(PartnerRepository._getSheet(), dto);
CacheLayer.invalidate('partner_map'); // 書込時無効化
return result;
};
Step 3: flush() 削減
grep -nE "SpreadsheetApp\.flush\(\)" *.js **/*.js で全件抽出し、削除/保持を判定:
- ループ内の
flush()→ 削除 (パフォーマンス劣化主因) - 関数末尾の
flush()→ 保持または最終 1 回に集約 - トランザクション境界の
flush()→ 保持 (整合性のため)
各箇所の意図を spec § 注意事項に明示し、削除根拠を記録。
Step 4: Volatile 関数(NOW() / TODAY() / RAND())の除去
Volatile 関数はシート開閉や任意の編集で全シート再計算を引き起こすため、行数増加で乗数的に劣化する。
GAS 側で静的値セットに置換:
- ヘッダー行の「最終更新日時」セル →
setupAllSchemas実行時にsetValue(new Date())で固定 - 試算用
RAND()→ 廃止 (試算は GAS 側Math.random())
Step 5: 条件付き書式の削減
grep -nE "addConditionalFormatRule|newConditionalFormatRule" 100_config/*.js で全件抽出。
- 数式条件 (
whenFormulaSatisfied) で複雑なもの → GAS 側setBackground()置換 - 単純な値範囲条件 → 保持(パフォーマンス影響小)
特にマート系・財務 3 表シートで条件付き書式が多い場合、行数 × 条件数で乗数的にレンダリングコストが増えるため優先削減。
Step 6: onEdit 軽量化
重い処理を onEdit(e) 本体に書くと毎編集ごとに実行され UX を阻害する:
before:
function onEdit(e) {
// 重い処理 (5 秒以上)
recalculateAll(e.range.getSheet());
}
after:
function onEdit(e) {
CacheService.getScriptCache().put('pending_recalc', e.range.getA1Notation(), 60);
// 即時 return (< 100ms)
}
// Installable trigger で 1 分後に非同期実行
function processPendingRecalc() {
var pending = CacheService.getScriptCache().get('pending_recalc');
if (pending) recalculateAll(...);
}
Installable trigger は ScriptApp.newTrigger('processPendingRecalc').timeBased().everyMinutes(1).create() で登録。
Step 7: 効果測定
MAS-233 の 99_perf_log シートで以下を計測し、合格基準を確認:
| 領域 | 現状 P95 (推定) | 最適化後目標 | 改善率 |
|---|---|---|---|
| Action A (INV 起票) | 5-10 秒 | 1-2 秒 | 5x |
| Action B (消込確定) | 5-15 秒 | 1-3 秒 | 5x |
マート全更新 (runDataMart) | 30-60 秒 | 6-15 秒 | 5x |
RPA 起票 (407_rpa_orchestrator) | 10-30 秒 | 2-6 秒 | 5x |
マスタ取得 (PartnerRepository.findAsMap) | 1-3 秒 | < 0.1 秒 (HIT) | 10-30x |
合格基準: 全関数で P95 が現状の 1/3 以下 (= 3x 改善)。
影響範囲
| 対象 | 種別 | 変更内容 | リスク |
|---|---|---|---|
200_data/cache_layer.js | 追加 | CacheLayer 名前空間 (約 100 行) | 純粋関数・既存ロジックへの影響なし |
200_data/202_repository.js | 変更 | 全 Repository 6 件に HOF 適用 (約 30 行追加) | キャッシュ無効化漏れがあると古いマスタ参照リスク → テストで網羅 |
400_domain/410_subledger_engine.js | 変更 | バッチ I/O 化 (Top 関数 5-7 件) | 仕訳ロジックの I/O パターンのみ変更・計算結果は不変 |
400_domain/407_rpa_orchestrator.js | 変更 | バッチ I/O 化 + マスタ取得キャッシュ HIT | 同上 |
600_report/601-608_datamart_*.js | 変更 | バッチ I/O 化 + 条件付き書式削減 | マート結果の数値は不変・書式のみ変更 |
100_config/101_sys_config.js | 変更 | 条件付き書式定義の単純化 / Volatile 関数除去 | DDL 整合性は setupAllSchemas テストでカバー |
900_test/perf_regression_tests.js | 追加 | 各最適化前後の I/O 回数・実行時間比較 (約 150 行) | 既存テストへの影響なし |
03_sys_params | 変更 | MAS231_CACHE_* 2 キー追加 | 既存キーには影響なし |
appsscript.json | 変更なし | script.cache / script.scriptapp 既存スコープ内で完結 | failure_patterns #26 遵守 |
docs/_config.json | 変更 | nav 1 行追加 | PR 競合に注意 |
注意事項
- #18-#20(命名造語禁止):
CacheLayer/withCacheInvalidation_/_findAsMapImpl_は既存命名規則 (SocialInsuranceTierEngine/PersonalTaxEngine等) と整合する命名。GAS API (CacheService) と衝突しない名前空間。 - #21(
getLastColumn()列範囲膨張): バッチ I/O ではgetDataRange()または明示的列数指定を強制。getLastColumn()を毎回呼び出すと隠れ性能低下を招く。 - #25(並列実装対称性): 全 6 Repository で同一の HOF パターンを適用。
save/append後のinvalidate()呼出も完全対称に配置。 - #26(oauthScopes 部分宣言禁止):
appsscript.jsonを一切編集しない。CacheService/LockService/ScriptApp.newTriggerは既存cloud-platformスコープでカバー。 - #27(Admin SDK API 変動): 該当なし。
- #29(V8→Java Infinity null): 該当なし (本案件は計算結果の値域変更なし・既存挙動を保持)。
- キャッシュサイズ上限:
CacheServiceは単一値 100KB / 全体 100MB。取引先 1000 件超のような大きなマスタは分割保管 (partner_map_part1/partner_map_part2等) を v2 で検討。v1 ではJSON.stringify(value).length < 100000で skip + WARN ログ。 - キャッシュ TTL 6h の妥当性: 税理士月次レビュー周期と整合 (1 日内のマスタ更新は十分カバー・月跨ぎは新セッションで再取得)。実運用で短縮要件が出たら
MAS231_CACHE_TTL_SECONDSで調整可。 - トランザクション境界での
flush()保持: 整合性 vs パフォーマンスのトレードオフ。仕訳起票 (Action A/B) のような副作用大きい処理は末尾 1 回flush()を保持し、再実行可能性を担保。 - 段階適用戦略: Step 1-7 を独立 PR 化 + 各 PR で回帰テスト必須。まとめて 1 PR にしない (rollback 困難)。順序: Step 1 (バッチ I/O) → Step 2 (キャッシュ) → Step 3 (flush) → Step 4-6 → Step 7 (測定)。
- 回帰テスト:
900_test/perf_regression_tests.jsで最適化前後の I/O 回数・実行時間を比較。期待値テーブルベースで合否判定 (各関数でexpectedIOCallCountを spec 化)。 - CI ガード: Jr が誤って
flush()を再追加 /getValue()ループを書くのを防ぐため、scripts/pre-push-check.shにgrep -E "for.*getValue\(\)" 400_domain/等のガードを追加 (任意・MAS-224 と連動)。 - 数式静的化で失われる再計算自動性:
NOW()/TODAY()を削除すると「常に最新時刻」を表示する機能が消える。spec で**「最終更新日時は手動 or バッチ更新」**と明示し、実運用に問題ないことを確認 (人間検討事項 #4)。 - onEdit 非同期化による UX 変化: 即時反映 → 1 分後反映に変わるため、UX に「処理中」表示で補完。Installable trigger の 1 分間隔で許容できないケース (リアルタイム要求) は対象外とする。
エッジケース
実装時に必ず以下 12 件を単体テストでカバーする (perf_regression_tests.js)。
| # | 条件 | 検知方法 | 期待される挙動 | ログ出力 |
|---|---|---|---|---|
| 1 | キャッシュ HIT 時に古いデータ参照 | Repository.save 後の findAsMap で旧値返却 | save が cache.invalidate を呼出する設計で対処 | テストで HIT/MISS パターン検証 |
| 2 | キャッシュ書込が 100KB 超過 | JSON.stringify(value).length >= 100000 | 例外捕捉 + WARN ログ + キャッシュなしで loaderFn 結果返却 | Utils.persistLog('WARN', 'CacheLayer.get', 'Value > 100KB ...', ...) |
| 3 | 並行実行時のキャッシュレース | 同時に findAsMap + save 呼出 | v1 では受容 (最終書込み優先で OK)・v2 で LockService 検討 | — |
| 4 | バッチ I/O で空配列を setValues([]) | values.length === 0 | スキップ + return | — |
| 5 | flush() 削除後の不整合 | 連続書込で旧値が新値で上書きされない | 末尾 1 回 flush() で対処 | — |
| 6 | Volatile 関数を残す必要があるシート | 監査ログ等の =NOW() を意図的に保持 | spec で明示 + 削除対象から除外 | — |
| 7 | 条件付き書式削減で書式情報消失 | 削減前にスナップショット (背景色 / 文字色) を Sheet.getBackgrounds() で記録 | 削減後に GAS 側で setBackgrounds() 復元 | — |
| 8 | onEdit 非同期化で UX 変化 | 即時反映を期待していたユーザーの戸惑い | 「処理中」表示 + 1 分後完了通知で補完 | — |
| 9 | キャッシュ無効化漏れ (Repository.save → cache.invalidate 抜け) | テストで HIT パターン検証 | save 後に findAsMap を呼んで新値が返ることを単体テストで保証 | — |
| 10 | 99_perf_log 計測自体の overhead | perfStart / perfEnd 自体の処理時間 | 計測 OFF/ON フラグで運用 + overhead < 1ms 確認 | — |
| 11 | CacheService クォータ枯渇 | cache.put 例外 (Cache service quota exceeded) | 当日のみキャッシュ無効化 + 24h 後に自動回復 | Utils.persistLog('WARN', ...) |
| 12 | Jr が誤って flush() を再追加 | pre-push-check.sh で grep flush() ガード | CI で push を弾く | CI ログ |
実データ検証
実装完了後に以下を MAS-233 計測ツールで実行し、合格基準と一致することを仕様書完成の必須条件とする。
1. Action A (INV 起票) 100 件バッチ実行
| 計測指標 | 現状 P95 | 最適化後目標 |
|---|---|---|
| 実行時間 | 5-10 秒 | < 2 秒 |
getValue 呼出回数 | 約 500 回 | 約 5 回 (バッチ化) |
| マスタ取得回数 | 100 回 | 1 回 (キャッシュ HIT) |
2. マート全更新 (runDataMart) 5 年分
| 計測指標 | 現状 P95 | 最適化後目標 |
|---|---|---|
| 実行時間 | 30-60 秒 | < 15 秒 |
flush() 呼出回数 | 10+ 回 | 1 回 |
3. キャッシュ HIT/MISS 比率
セッション内で findAsMap を 50 回呼出 → 1 回目 MISS / 残り 49 回 HIT を確認。
4. 条件付き書式削減後のレンダリング速度
財務 3 表シート (P/L 60 行 × 12 ヶ月 + B/S 80 行 × 12 ヶ月) を開いて表示完了までの時間:
- 現状: 5-10 秒
- 削減後: < 2 秒
5. onEdit 軽量化後の UX
任意セル編集 → onEdit 完了までの時間 < 100ms (現状 5+ 秒)。
6. 回帰テスト (perf_regression_tests.js)
全 12 件のエッジケースが PASS することを確認。
関連ドキュメント
- MAS-233: パフォーマンス診断ツール — 本案件の前提依存 (計測基盤)
- MAS-232: サイドバー SPA 化 — 本案件で習得した最適化パターンを SPA 側にも適用
- MAS-236-240: GCP 移行基盤 — 本案件で蓄積したパターンを Cloud Run / BigQuery 移行で再利用
- MAS-230: Jr 採用要件定義 — 本案件は Jr ハンズオン教材として適切 (パターン化された最適化)
- MAS-224: GitHub Actions CI パイプライン —
pre-push-check.shに CI ガード追加候補 - failure_patterns:
docs/_internal/failure_patterns.md— #18-20 / #21 / #25 / #26 - dev_spec_prompt_template.md v1.10: 仕様書作成標準テンプレート
- CLAUDE.md: ファイル番号体系・コーディング規約
- PRD: プロダクトポリシー
docs/_internal/biz/financial_metrics_guide.md: パフォーマンス改善が安全性指標 (ランウェイ) に与える間接効果
人間が検討すべき事項
- 着手順序: Step 1 (バッチ I/O) → Step 2 (キャッシュ) → Step 3 (flush) → Step 4-6 → Step 7 (効果測定) → Jr ハンズオン
- キャッシュ TTL の最適値: 6h vs 1h vs 24h — 実運用後にチューニング
- キャッシュ無効化の粒度: Repository 単位 vs 全マスタ一括 — テスト容易性 vs パフォーマンスのトレードオフ
- 数式静的化で失われる再計算自動性の許容範囲: 「最終更新日時」セルが手動更新になることの UX 影響
- onEdit 非同期化による UX 変化の許容: リアルタイム要求がある機能 (例: 即時バリデーション) を spec で明示分離
- Volatile 関数の検知手法: grep vs 実行時 listener (Apps Script
getOnValueChange等) の比較 - 効果測定の合格基準: P95 半減 vs 1/5 — 案件価値の定量化
- Jr 入社後のハンズオン教材としての適合性: 最適化パターンを
docs/ops/perf_handbook.mdに整理するか - CI ガード (
grep flush()) の実装方針: pre-push-check.sh への追加 or.github/workflows/ci.ymlへの組込 - 段階適用 PR の分割粒度: Step 1-7 を別々 PR vs 関連 Step をまとめて 1 PR
- MAS-233 完了待ち vs 並行実装: 並行実装の場合、計測 API シグネチャを spec で fix する必要あり
- キャッシュ HIT 率モニタリング:
99_perf_log拡張で HIT/MISS 率を継続モニタリングするか
実装プロンプト(Claude Code 用)
Claude Opus 4.7 推奨 (Step 2 キャッシュ層は HOF + Repository 横断で複雑)。それ以外の Step は Claude Sonnet 4.6 で OK。
## 案件
MAS-231 — GAS パフォーマンス最適化パス 1(バッチ I/O + キャッシュ + 数式静的化)
## 事前調査(必ず Read する)
1. `200_data/202_repository.js`: 全 6 Repository の `findAsMap` / `save` / `append` 実装パターン
2. `400_domain/410_subledger_engine.js`: Action A/B のバッチ I/O 化対象
3. `400_domain/407_rpa_orchestrator.js`: RPA 起票のキャッシュ HIT 適用候補
4. `600_report/601-608_datamart_*.js`: マート更新のバッチ I/O 化対象
5. `100_config/101_sys_config.js`: 条件付き書式 + Volatile 関数の現状定義
6. `000_infra/004_utils.js`: `persistLog` シグネチャ + `Constants.getParam` パターン
7. MAS-233 spec (存在すれば): `Utils.perfStart` / `perfEnd` API + `99_perf_log` シート構造
8. `failure_patterns.md`: #18-20 / #21 / #25 / #26 の文言
## 実装対象 (8 Step・段階 PR 化推奨)
Step 1: バッチ I/O 化 (Top 20 関数の書換)
Step 2: 200_data/cache_layer.js 新設 + 6 Repository に HOF 適用
Step 3: flush() 削減 (全件抽出 + 削除/保持判定)
Step 4: Volatile 関数除去 (NOW/TODAY/RAND を GAS 側静的化)
Step 5: 条件付き書式削減 (数式条件を setBackground 置換)
Step 6: onEdit 軽量化 (Installable trigger 非同期化)
Step 7: 900_test/perf_regression_tests.js 新設 (各 Step の前後比較)
Step 8: 効果測定 (MAS-233 計測 + 99_perf_log 確認)
## デプロイ手順
- 各 Step を独立 PR 化・dev でテスト → prod
- 各 PR で perf_regression_tests.js が PASS することを必須化
- コミットメッセージ: feat(MAS-231 Step N): <内容>
## failure_patterns チェック
- #18-20: CacheLayer / withCacheInvalidation_ 命名根拠
- #21: バッチ I/O では getDataRange() または明示列数指定を強制
- #25: 全 6 Repository で同一 HOF パターン適用
- #26: appsscript.json を一切編集しない
- #29: 該当なし (計算結果の値域変更なし)
推奨実行モデル
| Phase | 推奨モデル | 根拠 |
|---|---|---|
| Step 1 バッチ I/O 化 (機械的書換) | Claude Sonnet 4.6 | パターン適用・判断要素少 |
| Step 2 キャッシュ層新設 (HOF + Repository 横断) | Claude Opus 4.7 | 設計判断複雑・全 Repository 対称性確保 |
| Step 3-6 各最適化 | Claude Sonnet 4.6 | 個別パターン適用 |
| Step 7 回帰テスト実装 | Claude Sonnet 4.6 | 期待値テーブル既定義・パターン化 |
| Step 8 効果測定 | Claude Haiku 4.5 | 計測実行 + 数値比較のみ |
仕様書レビュー (scripts/4_review_specs_by_gemini.js) | Gemini 3 Pro Preview + Deep Think | パフォーマンス影響の第三者検証 |
変更履歴
| 日時 | バージョン | 変更内容 |
|---|---|---|
| 2026-04-30 | v0.1 (仕様書完了) | 初版作成。tasks/prompts/task_MAS-231.md (PR #438・手動骨格 281 行) + tasks/prompts/task_MAS-231.gemini.md (PR #439・Gemini 3 Pro Preview Deep Think 85 行) を統合 input として Claude Opus 4.7 (1M context) で本体起草。14 セクション全網羅: 概要 + 目的 + 現在のコード (利用 API 6 件 + Repository 6 件 + バッチ I/O 化対象関数) + 修正方針 7 Step (バッチ I/O / キャッシュ層 / flush / Volatile / 条件付き書式 / onEdit / 効果測定) + 影響範囲 + 注意事項 14 件 + エッジケース 12 件 + 実データ検証 6 ケース + 関連ドキュメント 10 件 + 人間検討事項 12 件 + 実装プロンプト + 推奨実行モデル + 変更履歴。主要設計判断: (a) 新規ファイル 200_data/cache_layer.js (CacheLayer HOF パターン) / (b) 段階 PR 化必須 (Step 1-8 を独立 PR + 各 PR で回帰テスト) / (c) MAS-233 完了待ちまたは並行実装 / (d) 効果測定 KPI = 全関数 P95 が 1/3 以下 (3x 改善) を合格基準。実装規模: 約 100 行 (cache_layer) + 各 Repository 修正 30 行 + 既存ファイル 10-15 個のバッチ I/O 化 + テスト 150 行 + 工数 2-3 週間。実装着手可能状態 (MAS-233 並行実装で OK)。 |
仕様書作成プロンプト
task_MAS-231.md (手動骨格・PR #438) を展開して表示
本仕様書の作成指示プロンプト全文は tasks/prompts/task_MAS-231.md を参照。Gemini Deep Think 比較資料は tasks/prompts/task_MAS-231.gemini.md (PR #439) を参照。パイプラインの再現性確保のため、仕様書末尾への転載は省略し、Git 履歴上の元ファイルを参照する方針とする。
関連コマンド:
# Gemini Deep Think で代替案再生成する場合
TARGET_ID=MAS-231 node scripts/gen_gemini_alt_oneshot.js
# Gemini レビュー実行
SPEC_FILES=docs/dev/dev_mas-231_gas_perf_optimization.md node scripts/4_review_specs_by_gemini.js