MAS-057: Solo-CEO Financial Navigator アンブレラ(BRD 派生・MAS-056 / MAS-011 / MAS-013 / MAS-048 / MAS-141 統括)
概要
| 項目 | 内容 |
|---|---|
| 案件 ID | MAS-057 |
| 案件名 | Solo-CEO Financial Navigator アンブレラ(BRD docs/brd_solo_ceo_financial_navigator.md 派生) |
| カテゴリ | シミュレーション・UX |
| 優先度 | P2 ★★★(商用化時の第 2 UX 差別化機能・BRD Vision「財務のコックピット」を完成させるアンブレラ) |
| 関連案件(統括対象) | MAS-056(意思決定対話 UI・Chat UX)/ MAS-011(What-if 5 カ年)/ MAS-013(投資分析 NPV/IRR)/ MAS-048(採用 TCO & BEP)/ MAS-141(節税・共済効果シミュレーター) |
| 新規追加ファイル(Phase 1-3 合計) | Phase 1: 400_domain/442_social_insurance_tier_engine.js(標準報酬月額マスタ検索 + 厚生年金上限突破 BEP 計算、純粋関数)、000_infra/002_constants.js に Constants.INCOME_TAX_BRACKETS 定数追加(個人所得税累進・法人税 TAX_RATES.brackets と対称に Constants 一元管理)、200_data/202_repository.js に SocialInsuranceTierRepository 追加、100_config/101_sys_config.js に MST_SOCI スキーマと confSheet.appendRow 登録を追加Phase 2: 400_domain/443_corporate_housing_optimizer.js(社宅家賃の個人↔法人按分計算)、400_domain/444_per_diem_policy_engine.js(出張規程ベース非課税日当計算)、200_data/202_repository.js に PerDiemPolicyRepository 追加、100_config/101_sys_config.js に TMPL_PDIEM スキーマ追加Phase 3: templates/financial_cockpit.html(Vite+React SPA・ドロップダウン + サンキーダイアグラム UI(離散単位選択・ai_agent_tips.md §7 準拠)・計算はクライアントサイド JS で実行)、400_domain/440_conversational_ui.js の doGet(e) にマスタ配信 API を追加(Phase 3 時点で MAS-056 実装済を前提)、000_infra/002_constants.js の MENU_DEFINITION に Web アプリ URL コピー項目を追加 |
| 新規シート(DDL 管理) | 17_mst_soci_tier(健保 50 等級 + 厚年 32 等級 = 82 行の全国一律マスタ)、13_tmpl_per_diem_policy(出張日当規程テンプレ・社内規程書 PDF 化のソースデータ兼用)。番号空き確認済(2026-04-24 grep): 既使用 11/12/14/15 mst / 16 wrk / 18/19 tmpl / 21-28 bud / 29 mst → 13/17 が空き。個人所得税テーブルはシートではなく Constants.INCOME_TAX_BRACKETS 定数で管理(Gemini レビュー v1.1 反映・法人税 Constants.TAX_RATES.brackets と対称)。 |
| 前提依存 | ✅ 全 Phase + Step 6 実装完了(v2.1 で Step 6 完了を反映・PR #394 / commit 94d9c71・2026-04-27)。MAS-057 Phase 1/2 は MAS-056 実装状態に依存せず独立完成(Gemini レビュー v1.1 反映・依存方向を逆転)。Phase 3 UI は MAS-232 Vite+React SPA 基盤上に templates/financial_cockpit.html + webapp_client/src/cockpit/*.tsx として実装完了。MAS-011/MAS-013/MAS-048 連動は runFiveYearForF57 経由で実装。Step 6 は 3 区分テーブル UI に加え Y1-Y5 単年タブ・ |
| 実装ステータス | Phase 1(✅ PR #354)/ Phase 1.5(✅ PR #356)/ Phase 2(✅ PR #360)/ Phase 3(✅ PR #379・2026-04-27)/ Step 6(✅ PR #394・2026-04-27・3 区分テーブル + 15 細項目大型拡張・33 コミット) |
| 吸収・再定義対象 | 該当なし(MAS-005 は MAS-056 が吸収済)。BRD §5 の 5 カ年推移は MAS-011/MAS-013 を連動呼び出しする形で実現。 |
BRD docs/brd_solo_ceo_financial_navigator.md 派生案件(v1.2 で年収最適化スコープに転換・v1.4 でフロー × ストックのバランス最適化に再整理・v1.8 で UI を離散単位ドロップダウンに統一)。MAS-056 が提供する Chat ベース UX(対話で任意数シナリオを探索)を補完する「ドロップダウン + サンキーダイアグラム型のビジュアル財務コックピット」をアンブレラ仕様として定義し、1 人社長の「年収(月額報酬 × 12 + 賞与)の単純最大化 → 単年の手取り(フロー)と累積純資産(ストック)のバランス最適化」へのパラダイムシフトを実現する。両指標はトレードオフしうる(法人留保でストックを積めば今期手取りは減る)ため、システムは単一最大化ではなく両軸の同時可視化とユーザーによる最適点選択を中核価値とする。UI は連続スライダーではなく離散単位ドロップダウン(ai_agent_tips.md §7 準拠)で構成し、税務・社保等級境界との整合性を確保する。
MAS-056 は自然言語でシナリオを会話的に探索する意思決定ハブであり、MAS-057 は同じ計算エンジン(SocialInsuranceTierEngine.calcPremiums / calcBonusPremiums / PersonalTaxEngine 等)を年収ドロップダウン + 月額/賞与配分ドロップダウン + リアルタイム流出可視化という視覚優位の UX で再提供する第 2 レイヤーとなる(離散単位選択・ai_agent_tips.md §7 準拠)。商用化時は両者が「Chat タブ」「Visual Cockpit タブ」として共存する Web アプリとなり、BRD Vision の「財務のコックピット」を完成させる。
目的
- BRD 全体(Solo-CEO Financial Navigator)のエントリポイントとしてスコープ管理: MAS-056 / MAS-011 / MAS-013 / MAS-048 / MAS-141 の個別案件を「1 人社長の単年手取り(フロー)と累積純資産(ストック)のバランス最適化」という単一の経営課題に束ね、機能重複・抜け漏れを可視化する(v1.4 でフロー × ストックの 2 軸評価に再整理)。
- BRD §3.1「社会保険料の壁」ロジックの初期実装(年収の月額 × 賞与 2 軸最適化): (a) 標準報酬月額等級表をマスタ化し厚生年金保険料の月額上限(標準報酬月額 65 万円等級・2026 年時点)突破戦略の損益分岐点を計算、(b) **賞与側の上限ロジック(厚年 1 回上限 150 万・健保年累計上限 573 万)**を
calcBonusPremiumsとして並列実装し、「月額を抑えて賞与に振る逆方向最適化」の効果を定量化する。年収を固定した配分最適化と年収そのものの最適化を等価に扱う。MAS-056 のcalculateOptimalCompensation()からも呼び出せる共通コアエンジンとして設計する。 - BRD §3.2「法人 vs 個人税率のデッドヒート」可視化:
Constants.TAX_RATES.brackets(法人税)とConstants.INCOME_TAX_BRACKETS(個人所得税・本案件で新設)を対比し、年収の交点(デッドヒート分岐点)を UI 上で強調表示する。税制改正時の更新箇所を002_constants.js一元化(Gemini レビュー v1.1 反映)。 - BRD §4.3 生活最適化パラメータの追加: 社宅家賃(賃貸料相当額ベース按分)、出張日当(規程テンプレベース非課税枠計算)、共済(小規模企業共済 + 経営セーフティ共済、MAS-141 ロジックを参照)を主要 3 ドロップダウン(離散単位選択・
ai_agent_tips.md §7準拠)として実装する。 - BRD §6 UX 戦略「2 段ドロップダウン + サンキー + インサイト」の具体化(v1.8 でスライダー全廃に統一・
ai_agent_tips.md §7準拠): 年収ドロップダウン(50-100 万円単位)+ 月額/賞与配分ドロップダウン(月額 5 万円単位で標準報酬月額等級境界と整合・賞与 50 万円単位)の 2 段構成。パラメータ変更(onChange)と同時に手残り推移がリアルタイム反映される UI(クライアントサイド計算で即時応答・google.script.run通信レイテンシ排除)。年収 → 所得税/住民税/健保/厚年(賞与分・月額分)/法人税 → 手残りの流出をサンキーダイアグラムで可視化(厚年賞与 1 回上限突破部分は「社保ゼロ流入」として色分け)。callClaudeApiOnVertex_()またはcallGeminiForReasoningOnVertex_()でインサイト「年収 600 万のうち月額 30 万 × 12 + 賞与 240 万に再配分すると、厚年賞与上限突破で社保が年 N 万円減り、手残りが X 万円増加」を自動生成する。 - 齋藤 Baseline(BRD §8・v1.2 更新)の手残り最大化ポイントを数値証明: 年商 1,680 万 / 原価 0 / 固定費 240 万 / **年収 600 万(月額 50 万 × 12 + 賞与 0)**を起点に、(1) **年収 600 万固定 × 配分 4 パターン(A: 全額月額 / B: 夏冬賞与各 60 万 / C: 賞与 240 万 × 1 回 / D: 賞与 150 万 × 2 回)**の社保総額逆転点、(2) 年収を 300 万〜1,000 万で上下させた場合のデッドヒート分岐点、の 2 軸で合算純資産の最大値を特定する。
現在のコード
既存の財務計算エンジン(MAS-057 から Tool Use で横断呼び出し)
| 案件 | 関数・名前空間 | 状態 | MAS-057 連携時の用途 |
|---|---|---|---|
| MAS-011 What-if MVP | WhatIfSimulator.run(drivers, opts)(400_domain/430_what_if_simulator.js) | 実装済 PR #315/#320 | 5 カ年推移ドロップダウン用 |
| MAS-013 投資分析 | runInvestmentAnalysis()(400_domain/431_investment_analyzer.js) | 実装済 PR #329 | 法人内部留保の運用シミュレーション |
| MAS-048 採用 TCO | HiringTcoSimulator.runHiringTcoSimulation(input)(400_domain/412_hiring_tco_simulator.js) | 仕様書完了 PR #334/#341 | 社長以外の給与がゼロ → 参考のみ(本案件スコープ外) |
| MAS-049 賃上げ税制 | WageTaxCreditSimulator(400_domain/414_wage_tax_credit_simulator.js) | 実装済 PR #342 | 役員報酬増による税額控除効果を補助情報として表示 |
| MAS-056 意思決定対話 UI | calculateOptimalCompensation() (要調査・400_domain/440_*/441_* は未実装) | 仕様書完了・実装未着手 (PR #350 / dev_mas-056_conversational_scenario_ui.md) | 本案件は MAS-056 Phase 3 で同関数が実装された後に UI 層を提供 |
400_domain/ の採番状況(2026-04-24 時点・grep 確認)
実装済ファイル: 400_rpa_common / 401-406_rpa_* / 407_rpa_orchestrator / 410_subledger_engine / 412_hiring_tco_simulator / 413_invoice_matcher / 414_wage_tax_credit_simulator / 420_project_profitability / 430_what_if_simulator / 431_investment_analyzer。
MAS-056 用の 440_conversational_ui.js / 441_compensation_optimizer.js は仕様書に記載されているが実装未着手(ディレクトリに存在しない)。MAS-057 は 442/443/444 台を新規カテゴリとして確保する。
参照する既存 API(コアコード実在関数のみ・failure_patterns #18-#20 遵守)
| API | 定義ファイル | シグネチャ | MAS-057 での用途 |
|---|---|---|---|
Constants.getParam(key, defaultVal) | 000_infra/002_constants.js:147 | function(key, defaultVal) → string|number | F57_* キー取得、F56_FUKUI_* キー参照 |
Constants.TAX_RATES.brackets | 000_infra/002_constants.js:22 | [{ upTo, national, local }](法人税用) | デッドヒート可視化のうち法人税側 |
Constants.INCOME_TAX_BRACKETS | 000_infra/002_constants.js(本案件 Phase 1 で新設) | [{ upTo, rate, deduction }](個人所得税用・総合課税ブラケット) | デッドヒート可視化のうち個人所得税側。毎年 3 月税制改正時に 002_constants.js を直接編集して更新 |
Utils.getSheetByKey(key, fallbackName) | 000_infra/004_utils.js:302 | function(key, fallbackName) → Sheet|null | 新設 3 シートの取得 |
Utils.parseDateToYm(val) | 000_infra/004_utils.js:354 | function(val) → "YYYY-MM" | 適用年度・開始年月の正規化 |
Utils.parseAmt(val) | 000_infra/004_utils.js:453 | function(val) → number | ドロップダウン選択値のパース(カンマ・全角対応) |
Utils.persistLog(level, funcName, message, detail) | 000_infra/004_utils.js:577 | function('ERROR'|'WARN'|'INFO', funcName, message, detail) | エッジケース発生時のログ永続化 |
callClaudeApiOnVertex_(prompt, options) | 000_infra/004_utils.js:51 | グローバル関数 (prompt, options) → string|null | インサイト自動提示(自然言語アドバイス) |
callGeminiForReasoningOnVertex_(prompt, options) | 000_infra/004_utils.js:132 | グローバル関数 (prompt, options) → string|null | インサイト JSON 構造化応答 |
readSheetAsDtos_(sheet) | 200_data/202_repository.js:19 | private ヘルパー(200_data/ 内からのみ使用) | SocialInsuranceTierRepository.findAll() 実装(個人所得税用 Repository は新設しない・v1.1 Critical 2 反映) |
appendDtosToSheet_(sheet, headers, dtos, lastRowCol) | 200_data/202_repository.js:85 | private ヘルパー | 新設 Repository の書き込み(将来拡張用) |
Contracts.toDto(headers, row) | 000_infra/003_contracts.js | (headers, row) → DTO | readSheetAsDtos_ 内部で使用 |
参考にする既存 Repository 構造(対称実装の手本・failure_patterns #25)
AccountRepository(200_data/202_repository.js:304)/ PartnerRepository(同:356)/ PositionTemplateRepository(同:433)/ HurdleRateRepository(同:505)が読み取り専用マスタの共通構造を持つ:
var XxxRepository = {
_getSheet: function() { return Utils.getSheetByKey('SYS_KEY', 'fallback_sheet_name'); },
findAll: function() { return readSheetAsDtos_(XxxRepository._getSheet()); },
findAsMap: function() { /* 有効フラグ FALSE 除外 + 重複ID は先着採用 + Utils.persistLog('WARN', ...) */ },
_cache: null,
resetCache: function() { XxxRepository._cache = null; },
};
MAS-057 で新設する 3 Repository(SocialInsuranceTierRepository / IncomeTaxBracketRepository / PerDiemPolicyRepository)はこの 5 要素を完全対称に配置する。
appsscript.json OAuth スコープの現状(failure_patterns #26 予防)
確認済(2026-04-24): 既存 oauthScopes に https://www.googleapis.com/auth/cloud-platform(Vertex AI 用)が含まれている。MAS-057 での追記は不要。oauthScopes への部分追記は「既存スコープの自動検出が完全オフ」となるため、本案件で appsscript.json を編集しない方針を注意事項に明記する。
MENU_DEFINITION カテゴリの現状
000_infra/002_constants.js:206 の MENU_DEFINITION に存在するカテゴリ: 🚀 BizLP / 💾 バックアップ / 📋 サイドバー: 📊 マート更新 / 📋 サイドバー: 🔧 開発・設定 / 📋 サイドバー: 📒 経理業務 (RPA / Action) / 📋 サイドバー: 🔍 消込・マッチング / 📋 サイドバー: 📝 費用登録 / 📋 サイドバー: ⚙️ メンテナンス / 📋 サイドバー: 🔧 マイグレーション / 📋 サイドバー: 🔄 開発用 (dev) / 📋 サイドバー: 🧪 テスト。
MAS-057 用の新規カテゴリ追加は MAS-056 が先行して追加予定の 🧭 意思決定対話(Web App) に相乗りし、コックピット URL コピー項目を同カテゴリに追加する方針とする(MAS-056 仕様書 PR #350 で規定済)。
修正方針
Phase 1 — 社会保険料壁エンジン + 等級マスタ(約 1.0 ヶ月・週 10h 前提)
ゴール: 400_domain/442_social_insurance_tier_engine.js が単体で動作し、月額報酬 → 標準報酬月額等級 → 健保料・厚年保険料を算出できること。本 Phase は MAS-056 実装状態に依存せず独立完成(v1.1 Major 3 反映・依存方向反転)。MAS-056 が後から実装される際に、MAS-056 側から SocialInsuranceTierEngine.calcPremiums() 等を呼び出す形とする。
100_config/101_sys_config.js拡張:confSheet.appendRow(['MST_SOCI', '', '17_mst_soci_tier', 'マスタ_社会保険標準報酬月額等級表 (F-57 壁エンジン)'])を追加。schemas['MST_SOCI']={ headers: ["有効フラグ","等級","標準報酬月額下限","標準報酬月額上限","健保料率","厚年料率","介護保険料率","子ども子育て支援金率","適用開始年月","備考"], color: "#666666", validations: { ... } }。v1.7 Minor 反映: 適用開始年月列に{ type: 'regex', pattern: '^20[2-3]\\d-(0[1-9]|1[0-2])$', helpText: 'YYYY-MM 形式で入力してください(例: 2026-03)' }のバリデーションを追加し、「2026/03」「R8-3」等のブレを防止。- DDL 実行後の初期データ投入スクリプトは
800_ops/配下に812_migration_f57_tier_seed.jsとして新設(migrationF57TierSeed()関数・マイグレーション運用ガイドライン準拠・冪等性必須)。日本年金機構 2026 年 3 月分〜の料率表(全国一律・健保 50 等級 + 厚年 32 等級)を投入する。出張日当規程テンプレは Phase 2 で別関数migrationF57PerDiemSeed()として追加する。
000_infra/002_constants.jsにINCOME_TAX_BRACKETS定数追加(v1.1 Critical 2 反映・法人税TAX_RATES.bracketsと対称な一元管理):/** * 個人所得税 累進課税ブラケット (2026 年時点・総合課税) * brackets: 課税所得の低い方から順にマッチ * rate: 税率 / deduction: 控除額(速算表) * 毎年 3 月税制改正後に本定数を直接編集して更新する。 */ INCOME_TAX_BRACKETS: { brackets: [ { upTo: 1950000, rate: 0.05, deduction: 0 }, { upTo: 3300000, rate: 0.10, deduction: 97500 }, { upTo: 6950000, rate: 0.20, deduction: 427500 }, { upTo: 9000000, rate: 0.23, deduction: 636000 }, { upTo: 18000000, rate: 0.33, deduction: 1536000 }, { upTo: 40000000, rate: 0.40, deduction: 2796000 }, { upTo: Infinity, rate: 0.45, deduction: 4796000 }, ], residentTaxRate: 0.10, // 住民税(都道府県民税 + 市町村民税 合算) applicableFrom: '2026-01-01', },200_data/202_repository.jsに Repository 追加:SocialInsuranceTierRepositoryをHurdleRateRepositoryの直後に追加。_getSheet('MST_SOCI', '17_mst_soci_tier')/findAll()/findAsMap()(キー = 等級コード・重複先着・有効フラグ FALSE 除外・Utils.persistLog('WARN', ...)で警告)/_cache/resetCache()。- 個人所得税用の Repository は新設しない(v1.1 Critical 2 反映)。呼び出し元は
Constants.INCOME_TAX_BRACKETS.bracketsを直接参照する。
400_domain/442_social_insurance_tier_engine.js新設(v1.2 賞与 API 追加 + v1.3 Pure Function 厳格化):SocialInsuranceTierEngine = { findTier, calcPremiums, calcBonusPremiums, calcBreakEvenPoint, ... }の構造で実装。- 完全な純粋関数(v1.3 Critical 反映・Pure Function 厳格化):
SpreadsheetApp/UrlFetchAppへの依存なしUtils/Constantsへの依存も排除:Utils.parseAmt/Utils.persistLog/Constants.getParamを関数内で直接呼ばず、呼び出し元(Repository または UI 層)がパース済みの値と料率(healthRate/pensionRateなど)を引数として渡す- この「完全な依存排除」により、GAS 環境 / ブラウザ環境 / Jest テスト環境で同じ
.jsファイルを一切の変更なしに使い回せる(v1.3 Critical 反映・単一ソース共有) - ログ出力が必要な場合は、戻り値に
warnings: [{ level, message }]配列を含めて呼び出し元でUtils.persistLogを呼ぶ
findTier(monthlyCompensation, tierMap, targetYm): 月額報酬額と対象年月("YYYY-MM")から、該当期間に適用される等級を返す(v1.3 Minor 反映・targetYmで適用開始年月と突合)。最大等級超過時は最大等級に丸め、戻り値に{ ..., isOverCap: true, warnings: [...] }。calcPremiums(tier, { isOver40, healthRate, pensionRate, nursingCareRate, childcareLevyRate, targetYm }): 月額報酬に対する健保料 + 厚年 + 介護(40 歳以上のみ)+ 子ども子育て支援金を算出。料率は引数で注入(Constants.getParam直接呼ばない)。targetYmで tier の「適用開始年月」との整合確認。calcBonusPremiums(bonusAmount, tierMap, options)実装済(v1.2 計画 → v1.6 で Phase 2 から Phase 1.5 に前倒し実装完了 PR #356・実装実態を反映):options = { isOver40, accumulatedBonusThisFiscalYear, singleBonusCapPension, yearlyBonusCapHealth }(実装シグネチャに準拠)- 料率は
tierMap内の等級レコードから_extractUniformRates_で抽出(厚年料率 > 0 の等級を優先採用・全等級統一前提)。v1.3 で計画していた「料率の直接引数注入」は実装でtierMap経由に統合されたが、クライアント側でもtierMapを bootstrap 配信して渡せば等価に機能する(Pure Function 性は保持)。targetYmは実装で省略(tierMap が既に適用期間でフィルタ済前提) - 標準賞与額:
Math.floor(bonusAmount / 1000) * 1000(千円未満切り捨て)を内部で適用 - 厚年 1 回上限:
Math.min(standardBonus, singleBonusCapPension)で丸めた額に厚年料率適用。デフォルトsingleBonusCapPension = 1_500_000(DEFAULT_BONUS_PENSION_CAP_SINGLE定数・03_sys_paramsのF57_BONUS_PENSION_CAP_SINGLEから注入) - 健保年累計上限:
yearlyCapHealth - accumulatedの残枠まで健保対象、超過部分は健保・介護対象外。デフォルトyearlyBonusCapHealth = 5_730_000(DEFAULT_BONUS_HEALTH_CAP_YEARLY定数・03_sys_paramsのF57_BONUS_HEALTH_CAP_YEARLYから注入) - 子ども子育て拠出金: 厚年ベース(
pensionBaseに料率適用)のため 1 回上限に従う - 戻り値(実装確定値):
{ standardBonus, healthPremium, pensionPremium, carePremium, childcareLevy, total, pensionBase, healthBase, newAccumulatedHealthBase, isPensionCapped, isHealthYearlyCapped }- v1.3 計画の
isOverPensionCap/isOverHealthCapは実装でisPensionCapped/isHealthYearlyCappedにリネーム(受動態で状態を表現) newAccumulatedHealthBaseは実装で追加: 呼び出し元は次回賞与呼び出し時にaccumulatedBonusThisFiscalYearとして渡して反復呼び出しtotalは実装で追加: 健保 + 厚年 + 介護 + 子育て の合算
- v1.3 計画の
- 単体テスト 18 件(F57-22 〜 F57-39・
901_test_runner.js)で精度担保: 通常賞与 / 介護 40 歳以上 / 千円未満切り捨て / 厚年 1 回上限突破 / 健保年累計上限突破 / 夏冬反復呼び出し / ゼロ・負値
calcBreakEvenPoint({ annualRevenue, fixedCost, annualIncome, monthlyAllocationRatio, targetYm, ... }): 年収固定 × 配分最適化の BEP を計算。厚年賞与 1 回上限突破効果を含めた合算社保最小化ポイントを返す。月額上限突破 BEP も従来通り返す。
PersonalTaxEngineの税法上必須の端数処理(v1.7 Major 反映・Gemini 指摘):- 課税所得の端数処理: 所得計算時に
Math.floor(taxableIncome / 1000) * 1000(1,000 円未満切り捨て)を適用してからブラケット判定・税率乗算を行う。 - 最終算出税額の端数処理: 所得税額の計算結果に
Math.floor(incomeTax / 100) * 100(100 円未満切り捨て)を適用。住民税も同様(100 円未満切り捨ての慣行)。 - この 2 段階の切り捨ては国税通則法・地方税法に基づく税額計算の実務慣行であり、シミュレータの手残り計算を実額(源泉徴収票・確定申告書の数値)と一致させるために必須。端数処理なしでは数百〜数千円単位の誤差が生じ、ユーザーの実データとの整合検証が取れなくなる。
- 単体テストケースとして「課税所得 3,300,999 円 → 切り捨て後 3,300,000 円 → 税額計算 → 最終税額の 100 円未満切り捨て」を必ず含める。
900_test/901_test_runner.jsにテストケース追加:- 齋藤 Baseline(月収 50 万)→ 等級判定 + 健保・厚年保険料計算の手計算値と ±1 万円以内一致。
- 境界値: 等級下限ジャスト / 等級上限ジャスト / 上限超過 / 下限未満。
Phase 2 — 社宅・日当・共済統合 + MAS-056 対話 UI 拡張(約 1.0 ヶ月)
ゴール: BRD §4.3 の 3 パラメータ(社宅家賃負担率・出張日当・共済積立額)が Phase 1 エンジンと合算され、MAS-056 の calculateOptimalCompensation() が役員報酬最適化時にこれらを考慮できるようになる。
13_tmpl_per_diem_policyDDL 追加:schemas['TMPL_PDIEM']={ headers: ["有効フラグ","規程ID","規程名","出張区分","宿泊有無","日当単価","交通費上限","適用開始年月","備考"], ... }。confSheet.appendRow(['TMPL_PDIEM', '', '13_tmpl_per_diem_policy', 'テンプレ_出張日当規程 (F-57)'])。- 初期データ投入は
800_ops/812_migration_f57_tier_seed.jsにmigrationF57PerDiemSeed()関数として追加(冪等性必須)。
PerDiemPolicyRepositoryを200_data/202_repository.jsに追加:PositionTemplateRepositoryと完全対称の 5 要素構造。400_domain/443_corporate_housing_optimizer.js新設:CorporateHousingOptimizer = { calcRentAllocation({ totalRent, taxableRentEquivalent, employeeShareRate }) }で税務上の賃貸料相当額 vs 実際家賃 vs 従業員負担割合から個人⇔法人の移転額を算出。- 賃貸料相当額の計算は 2 方式(固定資産税評価額ベース正式法 / 簡便法 50%)をパラメータ化し、
F57_HOUSING_CALC_METHODキー(デフォルトSIMPLE_50)で切り替え可能とする。 - 純粋関数のみ。
400_domain/444_per_diem_policy_engine.js新設:PerDiemPolicyEngine = { calcMonthlyAllowance({ policyMap, businessTripCount, includeAccommodation }) }で非課税日当総額を算出。PerDiemPolicyRepository.findAsMap()を外部から渡して依存性注入する。純粋関数。
MAS-056 統合の検証:
- MAS-056 実装が完了している場合のみ、
440_conversational_ui.jsのcalculateOptimalCompensation()が本 Phase 1 エンジンを参照するよう組み込む。 - MAS-056 未実装時は MAS-057 エンジンを単体で動作させ、MAS-056 実装時に統合する方針を「人間が検討すべき事項」に明記する。
- MAS-056 実装が完了している場合のみ、
Phase 3 — ドロップダウン + サンキー UI + インサイト + 5 カ年推移統合(約 1.0 ヶ月・クライアントサイド計算設計・ai_agent_tips.md §7 準拠)
ゴール: templates/financial_cockpit.html が Web アプリとして動作し、主要 3 ドロップダウン(役員報酬・社宅負担率・共済積立額)の onChange 操作で合算手残り推移がリアルタイム反映、サンキーダイアグラムで流出可視化、AI インサイトが明示的トリガーで更新される。
🔴 v1.1 Critical 1 維持(v1.8 でドロップダウン化に統一): GAS の google.script.run 通信レイテンシ(1〜3 秒)とリアルタイム UX は根本的に非互換のため、シミュレーション計算はクライアントサイド JS で実行し、GAS 側 API は初期ロード時のマスタ配信 + AI インサイト生成(重処理)のみに限定する設計を維持。v1.8 で UI を連続スライダーから離散単位ドロップダウンに変更したが、レイテンシ排除の方針は引き続き有効(ドロップダウン onChange でも同等の即応性を担保)。
クライアントサイド計算エンジン(v1.3 Critical 反映・単一ソース共有に変更):
- GAS 側と同一の
.jsファイルをクライアントでも直接読み込む方式に変更(v1.2 で想定した「TypeScript として複製」「バンドル時に定数埋め込み」は撤回・DRY 違反回避) 400_domain/442_social_insurance_tier_engine.js/443_corporate_housing_optimizer.js/444_per_diem_policy_engine.jsを 依存のない Pure JS(ES Modules または UMD 互換) で書く(Phase 1/2 で既に Pure Function 化済)- Vite のビルド設定で
../../400_domain/442_*.jsから直接 import(またはvite-plugin-file-copy等で同一ソースをコピー)してバンドル。GAS 側更新時にクライアント側ビルドも自動で最新版に追従する - マスタデータと料率はすべて
action=F57_BOOTSTRAPで配信(v1.3 Major 反映・バンドル埋め込みは廃止):17_mst_soci_tier全件(82 行・約 8KB) /13_tmpl_per_diem_policy全件 /Constants.INCOME_TAX_BRACKETS.brackets/Constants.TAX_RATES.brackets/F56_FUKUI_*料率キー /F57_*パラメータキー(F57_BONUS_PENSION_CAP_SINGLE/F57_BONUS_HEALTH_CAP_YEARLY等)。合計 20KB 以内。GAS 側で定数更新時にクライアント再ビルド不要 - ドロップダウン
onChangeは純粋にブラウザ内で再計算(GAS へのラウンドトリップなし)。応答時間 < 50ms(離散選択の即時反映で十分・スライダー時代の 60fps 要件は不要)を実現
- GAS 側と同一の
GAS 側
doGet(e)のマスタ配信 API:F57_BOOTSTRAPアクション:?action=bootstrapで上記 JSON 一式を返す。レスポンスにETagを含め、クライアントはlocalStorage+ 有効期限 1 時間でキャッシュ。F57_INSIGHTアクション:?action=insight&payload=...で役員報酬 + 現在試算値を受け取りcallClaudeApiOnVertex_で 1 インサイト生成。同期応答(Phase 3 時点で MAS-056 のポーリング基盤を流用するか、シンプル同期で 5 秒以内応答を保証するか判断)。
5 カ年推移への連動:
- 5 カ年計算はロジックが大きいため、MAS-011
WhatIfSimulator.run()はサーバーサイド維持。ドロップダウン選択が確定(onChangeから 2 秒間追加変更なし)したタイミングで 1 回だけgoogle.script.run.withSuccessHandler(...).runFiveYearForF57(params)を呼び出し、法人内部留保の運用益(F57_INVESTMENT_YIELD)と共済積立の所得控除複利を含めた 5 カ年推移を取得する。 - 折れ線グラフ + 積み上げ棒グラフで可視化。描画は Chart.js or D3.js。
- 5 カ年計算はロジックが大きいため、MAS-011
AI インサイト提示のトリガー変更(v1.1 Major 4 反映):
- debounce 500ms による連続呼び出しは廃止(Vertex AI クオータ枯渇 + コスト高騰リスク)。
- 発火条件を以下 2 択から
F57_INSIGHT_TRIGGER_MODEで切替:ONCHANGE_2SEC(デフォルト・v1.8 でドロップダウン化に伴いONMOUSEUP_2SECから改名): ドロップダウンonChangeイベント発火後、さらに 2 秒間追加の選択変更がない場合のみ AI 呼び出しEXPLICIT_BUTTON: 「💡 インサイトを更新」ボタンのクリックでのみ AI 呼び出し(コスト最重視)
- UI に「最終更新: HH:MM」を表示し、現在値と AI 応答時点の差分をユーザーが認識できるようにする。
サンキーダイアグラム + 2 段ドロップダウン入力 UI(v1.8 でスライダー全廃に統一・v1.9 で位置付けを「概観タブ」に再定義・
ai_agent_tips.md §7準拠):- v1.9 で UI 構造を 2 階層化: サンキーダイアグラムは「概観タブ」として補助的に残し、主要表示は新設 Step 6 の 3 区分テーブル(個人 / 法人 / 合計)に変更。サンキーは数値精度と改善示唆性が弱いため経営判断には Step 6 を優先利用する。
- サンキーダイアグラムライブラリは D3.js sankey-diagram / Plotly sankey / Chart.js sankey 拡張から選定(「人間が検討すべき事項」参照)。サンキーダイアグラム自体は離散値の流量可視化用途として維持(スライダーと別概念・
ai_agent_tips.md §7明記)。 F57_INCOME_INPUT_MODEモード:DROPDOWN_DISCRETE(デフォルト・v1.8 で確定・推奨): 1 段目 = 年収ドロップダウン(300 万〜1,500 万・50-100 万円単位の<select>)、2 段目 = 月額ドロップダウン(5 万円単位で標準報酬月額等級境界と整合)+ 賞与ドロップダウン(50 万円単位)。onChange毎に 1 回の純粋 JS 再計算 → SVG 再描画。±ボタン併用可。SLIDER(廃止予定・互換用のみ残置・v1.8 以降の新規実装非推奨): v1.0-v1.7 で採用していた連続スライダー UI。ai_agent_tips.md §7廃止理由(パフォーマンス / GAS クォータ / 離散単位の意思決定整合性 / 等級境界整合)により本モードは新規採用しない。既存実装が残っている場合の互換用にのみ存置(テスト網羅対象外)。
- 賞与上限突破のビジュアル表示: サンキーダイアグラムで「厚年賞与 1 回上限 150 万を超える部分」を別色(緑)で描画し「社保ゼロ流入」として明示。健保年累計上限 573 万突破時も同様。
- 計算トリガー分離:
onChange= クライアントサイド計算 /onChange + 2secor 明示ボタン = 5 カ年サーバー計算 + AI インサイト呼び出し。
個人 / 法人 / 合計 の 3 区分テーブル UI + 大型機能群(v1.9 で 3 区分テーブル新設 → v2.1 で Step 6.1〜6.15 に細分化・PR #394 実装完了):
v1.9 では「Step 6 = 個人/法人/合計の 3 区分テーブル UI」のみが設計されていたが、main 側 PR #394 で 33 コミットにわたりspec 未記載機能を 15 項目以上追加実装。経営者ユーザー指摘「サンキーは直感的だが数字としてわかりづらい・改善するための情報には利用しにくい」をベースに、Y1-Y5 単年タブ・累積セクション・実効税率併記・生命保険料・社長稼働限界メーター・純資産 3 用途分解・創業費・シナリオ保存・月単位入力・変動費比率・住宅ローン減税 等を Step 6.1〜6.15 として体系化。Gemini Deep Think (MAS-334) で発見された複数の独自機能 (社長稼働限界・最低月額制約等) も先行実装(注意事項 #19 参照)。
Step 6.1: 3 区分テーブル基本構造(v1.9 設計を踏襲・実装で詳細展開を 7 行に拡張)
- 「誰が負担するか」軸でグループ化(個人 / 法人を主軸・MAS-057 BRD のデッドヒート分析と整合)
- 4 グループ × 3 列構造: 収入 / 👤 個人負担合計 / 🏢 法人負担合計 / 🔄 法人→個人移転 / 💰 手取り(フロー)/ 🏦 純資産(ストック)
- 2 階層展開構造: デフォルトはサマリー行のみ、各グループ右端の
[▼]クリックで詳細展開- 個人負担合計: 4 行展開(所得税 / 住民税 / 健保本人 / 厚年本人)
- 法人負担合計: 4-5 行展開(法人社保 / 固定費 / 経費(変動費・cogsRate ベース) / 創業費(初年度のみ) / 法人税)— v2.1 で経費・変動費・創業費を追加して 3 行 → 4-5 行に拡張
- 数値精度: 万円単位 1 桁まで表示(例: 113.5 万)。大値は整数表示(例: 1,680 万)
- 色分け: ▲ 赤(負担)/ + 緑(収入・移転)/ % 青(税率)
- サンキーは「概観タブ」として
<details>で折りたたみ補助化(v1.9 では並列表示だったが、v2.1 で主要 UI を 3 区分テーブルに完全シフト)
Step 6.2: Y1-Y5 単年タブ(v1.9 にない・v2.1 新設)
3 区分テーブルに Y1/Y2/Y3/Y4/Y5 のラジオタブを追加し、各年単独の収入・負担合計・手取り・実効税率を表示。
- Y1:
isFirstYearフラグに従う(短縮月数 + 創業費を一時費用として加算) - Y2-Y5: 通年 12 ヶ月 + 月額報酬の年次増加額を
Y_n offsetで適用 - 純資産表示: 単年純増分(流動 + 老後 + 万一)を表示
- 5 年分の result 配列は
yearResultsuseMemo で一括生成
Step 6.3:
Y1-Y5 累積セクション(v1.9 にない・v2.1 新設)3 区分テーブルの下に独立セクションを追加し、
Y1/Y2/Y3/Y4/~Y5 タブで累積期間選択。- 累積純資産: 流動 + 老後 + 万一 + 法人期首預金残高加算(Step 6.14)
- 累積負担金額: 税 + 社保
- 平均実効税率(税理士定義): 期間内の (税/利益) の年次平均
- 平均実効負担率(社保込み売上比): 期間内の (税+社保/売上) の年次平均
- 節税金額: vs baseline(参考値・住宅ローン減税を含めない baseline と比較)
- 個人列の注記: 個人列は実質「累積手取り(+ 個人保険料払込)」の旨を注記表示(純資産概念との混同防止)
Step 6.4: 実効税率(税理士定義)と実効負担率(社保込み売上比)の併記(v1.9 にない・v2.1 新設)
経営者・税理士両方の語彙でアクセス可能にするため両指標を併記。
- 実効税率(税/利益・国際標準 ETR):
- 個人 = (所得税 + 住民税) / 課税所得
- 法人 = 法人税 / 税引前利益
- 実効負担率(税 + 社保 / 売上):
- 個人 = (個人税 + 個人社保) / 役員報酬
- 法人 = (法人税 + 法人社保) / 売上
- 合計 = 全税社保 / 売上
Step 6.5: 生命保険料 + 損金算入率(v1.9 にない・v2.1 新設)
- 個人生命保険料 年額入力: 新制度・段階式所得控除(上限 4 万円)
- 法人契約生命保険料 年額入力
- 法人保険損金算入率: 4 段階ドロップダウン(法人税基本通達 9-3-5・2019/7 改正準拠)
- 100%(掛捨て型)
- 60%(低中返戻率)
- 40%(高返戻率)
- 0%(全額資産計上)
- 資産計上分は累積純資産(法人)の「老後の備え」用途に分類(Step 6.7)
Step 6.6: 社長稼働限界(Burnout)メーター(Gemini Deep Think 発見 #4・先行実装・v1.9 にない・v2.1 新設)
ナレッジワーカー型 1 人社長の物理破綻ゾーンを可視化(MAS-334 Section MAS-239 の発見を MAS-067 着手前に MAS-057 で先行実装)。
- 入力: 代表取締役 月額単価 + 売上貢献稼働率
- 想定貢献年商 = 月額単価 × 稼働月数 × 売上貢献率
- 実効稼働率 = 実売上 / 想定貢献年商
- 100% 超で WARN 警告(ガードレールバナー)— 物理破綻ゾーン
- 単価を上げずに売上 2 倍の計画を入力した瞬間に🔴警告
Step 6.7: 純資産 3 用途分解(v1.9 にない・v2.1 新設)
純資産行を expandable 化し、▶ で 3 用途を展開。
- 💵 流動資産(いま使えるお金): 個人手取り + 法人現預金 - 法人保険資産計上分
- 🏛️ 老後の備え(退職金原資): 共済 + 法人保険資産計上分
- 🛡️ 万一の備え(保険給付想定): 個人/法人保険料の払込累計(実給付額は商品で異なる旨注記・注意事項 #20)
Step 6.8: 創業費 + 初年度フラグ + 月数按分(v1.9 にない・v2.1 新設)
- 初年度フラグ ON で N ヶ月稼働(1-12)を月数按分
- 創業費(前提条件・default 100 万): 初年度のみ一時費用として加算
- 繰延資産だが本実装は全額一括損金算入の簡易扱い(将来改修候補・注意事項 #20)
- 単年テーブル Y1 と Y2-Y5 で計算を分岐(
firstYearResult/annualResult) - Y1 月数 0 入力時は
Math.max(1, ...)で 1 にクランプ(エッジケース #26)
Step 6.9: シナリオ・前提条件プリセット保存・呼出(v1.9 にない・v2.1 新設・v2.2 で前回選択自動復元追加 (PR #400))
localStorage ベースで保存(個人デバイスに閉じる・チーム共有は v2 候補)。
ScenarioStore(Variables のみ): localStorage キーf57_cockpit_scenarios_v1AssumptionsStore(前提条件 16 項目): localStorage キーf57_cockpit_assumptions_v1- 旧スキーマ migration:
revenueAnnual→revenueMonthly(/12) 等を_migrateInputs/_migrateAssumptionsで自動変換(エッジケース #22) - シナリオ呼出時は前提条件を維持(Variables のみ上書き)— 「前提 × シナリオ」のマトリクス試算が可能に(エッジケース #23)
- 【v2.2 追加・PR #400】Variables 自動復元: 前回選択シナリオ・プリセットを起動時に自動ロード
f57_cockpit_last_selected_scenario_v1: 最後に選択したシナリオ名(ScenarioBar.tsx担当)f57_cockpit_last_selected_assumption_v1: 最後に選択した前提条件プリセット名(AssumptionsBar.tsx担当)- 起動時に該当キーを読み、対応するシナリオ・プリセットがまだ存在すれば自動的に呼び出す
- cockpit を一度閉じても 「前提 × シナリオ」マトリクス試算の継続性 を担保
Step 6.9-extension: 健全性診断機能(MAS-058 統合・v2.2 新設・PR #400)
MAS-058 「シナリオ健全性診断パネル」が cockpit に統合(詳細は MAS-058 spec v2.0 参照):
- 配置: 「累積純資産 + 平均実効負担率」セクションの直下(現状把握↑ vs 目標逆算↓ の境界)
- 6 制約 × Y1-Y5 期末 matrix: 黒字 / 営業利益率 / 留保率 / 労働分配率 / ランウェイ / 緊急予備金
- ヘルシーを保てる年間投資余力テーブル: 期末残高で 6 制約を維持できる最大の追加支出を binary search
- 適用開始年タブ: Y1 から / Y2 から (default) / Y3 から / Y4 から / Y5 から で部分適用
- 副機能: 必要年商の逆算(折りたたみ)+ キャパシティ ギャップ分析(単価 × 稼働率 vs 必要年商・100% 超で警告)
MAS-057 cockpit の配置原則: 現状把握 vs 目標逆算 の境界
v2.2 で MAS-058 panel を「累積純資産 + 平均実効負担率」セクション直下に配置することを確定。設計原則: cockpit を上から下に「現状把握 → 目標逆算」の流れとして構成し、3 区分テーブル + 累積純資産 + 平均実効負担率 までが「現状把握」レイヤー、MAS-058 健全性診断パネル以降を「目標逆算」レイヤーとする概念分離。今後追加される MAS-066(配当ミックス)/ MAS-067(マルチイヤー計画)等の cockpit 拡張機能は、この境界線に従って配置を決める運用ルール。
Step 6.10: 前提条件 / 入力 セクション分離(v1.9 にない・v2.1 新設)
ユーザーが頻繁に動かす変数と、業種・モデル選定で半固定の前提条件を視覚的に分離。
- 「⚙️ 前提条件」セクション(頻繁に変えない・16 項目): 黄系背景 + プリセットバー(
AssumptionsPanel.tsx) - 「📊 入力」セクション(頻繁に動かす Variables・7 項目): 灰系背景 + シナリオバー(
CompensationDropdowns.tsx+ScenarioBar.tsx)
Step 6.11: 月単位入力 + 変動費比率(v1.9 にない・v2.1 新設)
revenueAnnual→revenueMonthly(月商入力・内部で × 12)fixedCostAnnual→fixedCostMonthly(月固定費入力)- 二軸化: 売上原価率 (
cogsRate) + 変動費比率 (variableCostRate) cogsRateのラベル変更: 「経費比率(外注費含む・人件費除く)」に明示(役員報酬は別枠)cogsRateを 2.5% 単位ドロップダウンに細粒度化(0-70% / 29 段階)
Step 6.12 / 6.13: 月額報酬の年次増加額 + 役員報酬の最低月額(v1.9 にない・v2.1 新設)
- Step 6.12: Y2 以降に毎年加算される月額報酬の増加額(前提条件)
yearResultsuseMemo で 5 年分の result 配列を生成- 例: 月 5 万増 → Y1=50 万, Y2=55 万, ..., Y5=70 万
- Step 6.13: 役員報酬の最低月額(Gemini Deep Think 発見 #1・先行実装・前提条件・default 30 万)
- 生活費ベースの月額下限
- AI インサイトの制約として活用予定(現状: 入力フィールドのみ実装・
buildInsightPrompt_への反映は v2.2 候補・人間検討事項 #15)
Step 6.14: 法人期首預金残高 + 住宅ローン減税(v1.9 にない・v2.1 新設)
- 法人期首預金残高(前提条件・default 0): 累積純資産(法人)に加算
- 住宅ローン減税(前提条件・default 0・2022 年改正後制度):
- 所得税から先に控除
- 控除しきれない分を住民税から控除(上限: 課税所得 × 5% または 97,500 円)
- baseline で 0 にして節税金額に含める
- 簡易実装: 年額固定 × 5 年(本来は残高 × 0.7% で年々減少・13 年期間)— 注意事項 #20
Step 6.15: 想定貢献月商の参考表示(v1.9 にない・v2.1 新設)
AssumptionsPanelに read-only 表示(月額単価 × 売上貢献稼働率)CompensationDropdownsの月商入力に**「想定値」ボタン**(一発設定)- Burnout メーター(Step 6.6)の入力値と連動
Step 6.16: シート保存 + UX 統一 + プルダウン即時反映(v2.3 新設・PR #454)
背景: Step 6.9 の localStorage 二系統保存 (v2.1 / v2.2) は単一端末内では機能していたが、(a) 端末跨ぎ共有不可 (PC ↔ スマホでシナリオ移行不可) / (b) 業種別テンプレ配布の手段がない / (c) 削除済シナリオの復元不可 等の限界が顕在化。F-67 ScenarioPanel が同様の課題を解決した経緯と並行して、F-57 のプリセット・シナリオもシート保存に移行 + UX を F-67 と統一 + プルダウン即時反映 (Phase E v2 同等) を一括実装。
移行スコープ:
- 旧版:
ScenarioStore(フルCockpitInputs) /AssumptionsStore(前提条件 16 項目) をlocalStorage保存 - 新版: 2 タブにシート保存
38_f57_assumptions(前提条件プリセット・業種別テンプレ配布可能)39_f57_scenarios(フルCockpitInputsシナリオ)
- 自動移行: 初回 SPA ロード時に旧 localStorage 内容を 1 回だけシートにアップロード (
f57_cockpit_assumptions_migrated_to_sheet_v1/f57_cockpit_scenarios_migrated_to_sheet_v1フラグで再実行抑制) - 旧 localStorage: 安全のため残置 (手動削除可・将来 migration 完了確認後に廃止予定)
データモデル (F57_AS / F57_SC 共通スキーマ):
列 内容 有効フラグ TRUE / FALSE (削除は論理削除で FALSE 化) プリセットID / シナリオID F57AS_xxxx/F57SC_xxxx(4 桁連番・Constants.ID_PREFIXES.F57AS/F57SCで発番)プリセット名 / シナリオ名 ユーザ入力 (例: コンサル業・1000 万資本) 作成日時 / 更新日時 new Date()(上書時に更新日時のみ更新)payloadJSON 値オブジェクトの JSON 文字列 (前提条件 16 項目 or フル CockpitInputs)備考 任意 公開 API (
300_ui/302_spa_bridge.js・_f57Crud_ファクトリで重複排除):各タブに対し 4 関数 = 計 8 個:
関数 用途 listF57Assumptions()/listF57Scenarios()values 込みのフルレコードを返す (prefetch 用・即時反映の核) saveF57Assumption(payload)/saveF57Scenario(payload)id 未指定で新規発番、指定で同 ID 上書 loadF57Assumption(id)/loadF57Scenario(id)単一フェッチ (現状は使用箇所なし・後方互換用) deleteF57Assumption(id)/deleteF57Scenario(id)論理削除 (有効フラグ=false) 戻り値は全て
JSONSafe<T>ラップ。型定義はdocs/spec/sidebar_api.d.tsのF57RecordMeta(.values?含む) /F57RecordSavePayload/F57RecordFullを参照。UX 統一 (F-67 ScenarioPanel と同一構造):
- 同一スタイル:
myr-scenario-panel(緑色テーマ) を F-57 / F-67 で共有 - 同一構造: インライン名前入力 + 4 ボタン (🔄 再取得 / 💾 上書保存 / ➕ 新規保存 / 🗑️ 削除)
- AssumptionsBar (📋 前提条件プリセット) と ScenarioBar (📚 シナリオ) で同一 UI
即時反映 (Phase E v2 同等):
- list API が values 込みで返却するため SPA は初回 1 回の取得で全件 prefetch
- プルダウン onSelect で即座に値反映 (sheet roundtrip なし) — 体感サクサク化
- 📂 読込 → 🔄 再取得 (他タブ更新取込用) に役割変更
- F-57 / F-67 両方で同パターン適用 (UX 統一の実装裏付け)
適用ロジック (Bar 別の差分):
Bar 上書対象 維持対象 AssumptionsBar 読込時 前提条件 16 項目のみ Variables (報酬・配分系) は維持 ScenarioBar 読込時 Variables のみ 前提条件 16 項目は維持 (参考) F-67 ScenarioPanel yearInputs/initialBS/optimizationPolicy/exitPlanを全て上書き(なし・state 完全復元) 新規追加ファイル / 変更ファイル (PR #454):
- DDL:
100_config/101_sys_config.jsに38_f57_assumptions/39_f57_scenarios+flagTabs登録 +F57_AS/F57_SCスキーマ - ID 発番:
000_infra/002_constants.jsにF57AS_/F57SC_プレフィックス追加 - Repository:
200_data/202_repository.jsにF57AssumptionsRepository/F57ScenarioRepository新設 - API:
300_ui/302_spa_bridge.jsに_f57Crud_ファクトリで重複排除し list/save/load/delete を assumption/scenario 各 4 = 計 8 個追加 - 型:
docs/spec/sidebar_api.d.tsにF57RecordMeta/F57RecordSavePayload/F57RecordFull型追加 - Store:
webapp_client/src/cockpit/{ScenarioStore.ts, AssumptionsStore.ts}を sync localStorage から async sheet ベースに書換
テスト:
900_test/901_test_runner.jsにtestF57ScenarioSheetMigration_を追加 (12 ケース):ケース 内容 F57-SHEET-01 API 関数 8 個の存在 F57-SHEET-02 _f57Crud_ファクトリの存在F57-AS-01〜06 前提条件プリセット ラウンドトリップ (新規 / load / 上書 / 上書 load / 削除 / 削除後 load エラー) F57-SC-01〜04 シナリオ ラウンドトリップ (新規 / load monthlySalary / load dividendType / 削除) 「実装が spec を先行 → spec を整合追従」のパターン累計 9 例目 (F-57 v2.1 PR #395 + 均等割修正 PR #399 + F-58 v2.0 PR #401 + F-66 v1.2 PR #403 + F-67 v1.5 PR #424 + F-67 v1.6 PR #427 + F-67 v1.7 PR #449 + F-66 v1.2 + 本 v2.3 で 9 例目)。
Step 7: cockpit 拡張パネル群(v2.4 新設・PR #459)
背景: v2.3 まで MAS-057 cockpit は「単年の節税最適化ツール」として完成していたが、ユーザーから「(a) 4 アプローチ A/B/C/D の P/L を横並びで見たい (1 画面で比較したい) / (b) F-67 マルチイヤー planner の B/S 引継ぎロジックを cockpit にも統合し、6 年分の財務 3 表 (P/L · B/S · CF) を一気通貫で確認したい / (c) 各年の役員報酬を個別アプローチで切替できるようにしたい / (d) 本年 (Y0) は当期着地見込み (64_pl_ytd_plan + 73_bs_plan) で上書きできるようにしたい」という要望が出た。これに応えるため、main 側 PR #459 (commit
8f45430) で cockpit 拡張パネル群 (Step 7-A/B/C/D) を一括実装し、cockpit を「節税最適化ツール → 多年経営ダッシュボード」に進化させた。Step 7 の 4 サブパネル全体像:
サブステップ パネル / API 配置 / 役割 7-A ApproachComparisonPanel.tsxMAS-071 戦略シナリオパネル直下・4 アプローチ + AVG の 5 列均等 P/L 比較 7-B SoloFinancialStatementsPanel.tsx7-A の直下・Y0-Y5 の 6 年分 P/L · B/S · CF 連結表示 7-C getSoloCEOY0Forecast()GAS API7-B の Y0 上書きトグル用・64_pl_ytd_plan + 73_bs_plan 集約 7-D cockpit-main.tsx副作用 import 拡張451_multiyear_planner.js追加 (failure_patterns #33 対策)Step 7-A: ApproachComparisonPanel — 4 アプローチ別 P/L 比較
- ファイル:
webapp_client/src/cockpit/ApproachComparisonPanel.tsx - 配置: MAS-071 戦略シナリオパネル (
CompensationStrategyPanel) の直下 - 目的: A/B/C/D の 4 アプローチ + その平均 (AVG) の計 5 アプローチで役員報酬を採用した場合の単年 P/L を並列比較し、戦略選択の妥当性を 1 画面で吟味する
- データ供給元:
- 役員報酬月額 = MAS-071 戦略シナリオの推奨額を直接参照 (rounding 誤差回避のため戦略推奨値を SSoT とする)
isFirstYear=falseを強制 (短縮事業年度按分を排除し通年ベースで純粋比較)- 既存
computeYearlyBreakdown(modifiedInputs)を 5 回呼出 (A/B/C/D/AVG 別 modifiedInputs)
- 表示行 (12 行):
- 年商 / 変動費 / 固定費 (法人社保含む) / 役員報酬 / 営業利益 / 法人税等 (国税 + 地方税) / 住民税均等割 / 税引後利益 / 個人税 / 個人社保 / 個人手取り / 家族純資産フロー
- UI:
<table style="table-layout: fixed">+ 各列width: 16%(5 列均等 + ラベル列 1 列)・列幅崩れ防止 - MAS-071 との接続:
compensationStrategyprop で MAS-071 推奨役員報酬 4 値を受け取る (端末 onChange だけでは rounding が入るため SSoT で連結)
Step 7-B: SoloFinancialStatementsPanel — 多年 P/L · B/S · CF
- ファイル:
webapp_client/src/cockpit/SoloFinancialStatementsPanel.tsx - 配置: ApproachComparisonPanel の直下
- 目的: Y0 (本年) を左端とした 6 年分の財務 3 表 (P/L · B/S · CF) を年次連結で表示し、節税戦略の長期的影響を可視化
- 計算エンジン: F-67
simulateMultiyearClient(451_multiyear_planner.js) を流用 (B/S 引継ぎロジックを F-57 / F-67 で共有) - F67MultiyearBootstrap の合成: F57 boot を起点に MultiyearBootstrap を合成 (
perDiemPolicies/mas071Paramsは F-57 では不要なため省略合成) - 各年で役員報酬を選択可能 (6 dropdown):
- 各年 (Y0-Y5) ごとに dropdown を 1 つ用意・選択肢は A / B / C / D / AVG / 現状 の 6 つ
- Y0 のみ「現状」を default 選択 (Y0 は当期着地見込みとの併用シナリオが多いため)
- Y1-Y5 は「AVG」を default 選択 (戦略平均で安定運用するシナリオを想定)
- 本年 (Y0) 事業継続月数入力 (1-12 ヶ月・短縮事業年度対応):
- default 12・clamp [1, 12]
- 按分は Y0 のみ実施:
revenueMonthly/fixedCostMonthly/monthlySalary/dividendAnnualをy0Months / 12で scale (Y1 以降は通年でフル計上) - 短縮事業年度の P/L 月割按分 + 法人税均等割の月割 (既存 calc 流用) で精緻化
- Y0 を当期着地見込みで上書きトグル:
- default OFF (理論計算ベース)
- ON 時に
getSoloCEOY0Forecast()(Step 7-C) を 1 回呼出・結果 P/L で Y0 を直接上書き + B/S を Y1 期首 BS に初期値投入 - planner は
horizon=5(Y1-Y5) で実行・initialBS = forecast.bsを渡す → Y1 期首 BS が Y0 forecast 期末 BS で連結性維持 - トグル文言は 「64 + 73」 で表記 (旧「64 + 71」は誤り・64 は計画なので 73 が正しいペア)
- CF 表示: 営業 CF / 投資 CF / 財務 CF / FCF (FreeCashFlow) を含む簡易 4 行表示
Step 7-C: Y0 当期着地見込み API —
getSoloCEOY0Forecast()- ファイル:
300_ui/302_spa_bridge.js - 関数名:
getSoloCEOY0Forecast() - 戻り値:
{ pl: { revenue, cogs, sga, operatingIncome, ordinaryIncome, pretaxIncome, corporateTax, netIncome }, bs: { capital, retainedEarnings, cash, fixedAssets, debt, equity }, source: { plSheet, bsSheet, fallbackUsed } } - 集約ロジック:
- P/L 集約:
64_pl_ytd_planの通期列 (column B) から主要 8 項目 (売上 / 売上原価 / 販管費 / 営業利益 / 経常利益 / 税引前 / 法人税等 / 純利益) を抽出 - B/S 集約:
73_bs_planの最右列 (期末計画) から主要 6 項目 (資本金 / 利益剰余金 / 現預金 / 固定資産 / 借入金 / 純資産) を抽出 - フォールバック: 73_bs_plan が未生成のとき →
71_bs(実績) 最右列を代替使用 (source.fallbackUsed = trueで SPA 側に通知)
- P/L 集約:
- failure_patterns #29 対策: 戻り値全体を
_scrubInfinityForJSON_経由で返却 (V8 → Java シリアライズ時に Infinity / NaN が silent null 化する致命的落とし穴を予防) - SoloFS パネルとの接続: トグル ON 時に planner を
horizon=5(Y1-Y5) で実行 +initialBS = forecast.bsを渡し、Y1 期首 BS = Y0 forecast 期末 BS で連結性維持
Step 7-D: cockpit-main.tsx 副作用 import 拡張
- ファイル:
webapp_client/src/cockpit/cockpit-main.tsx - 背景: failure_patterns #33 (SPA 副作用 import 漏れによる engine 未ロード) の予防
- 副作用 import の旧 / 新:
状態 import 一覧 旧 (v2.3) 442_social_insurance_tier_engine.js/443_corporate_housing_optimizer.js/444_per_diem_policy_engine.js/445_solo_ceo_calc_engine.js/449_*.js/454_*.js新 (v2.4) 上記 + 451_multiyear_planner.jsを追加 (SoloFS 多年版でsimulateMultiyearClient再利用)- 実装ファクト: F-57 SPA 起動時に
window.MultiyearPlanner(もしくは同等の global) が確実に解決されるよう、副作用 import を追加することでsimulateMultiyearClientが SoloFS パネルから即座に呼出可能になる - failure_patterns #33 必須対策: 「engine 未ロード → SoloFS パネル白画面」を防ぐ予防策・ビルド時に確実にバンドル含有させる目的
CockpitApp.tsx 配置順序 (v2.4 最新)
v2.3 までは MAS-058 RequiredRevenuePanel の上は MAS-071 戦略シナリオパネルだけだったが、Step 7-A / 7-B が間に挟まる:
1. GuardrailBanners (税務否認リスク警告等・最上部固定) 2. CompensationStrategyPanel (MAS-071 戦略シナリオパネル) 3. ApproachComparisonPanel (Step 7-A・4 アプローチ P/L 比較) ← v2.4 新規 4. SoloFinancialStatementsPanel (Step 7-B・多年 P/L · B/S · CF) ← v2.4 新規 5. AssumptionsBar / ScenarioBar / CompensationDropdowns (既存・前提 + Variables 入力群) 6. RequiredRevenuePanel (MAS-058 シナリオ健全性診断パネル・既存)MAS-067 / MAS-071 との連携 (Step 7 由来)
- MAS-067 マルチイヤー planner:
simulateMultiyearClient(451_multiyear_planner.js) を SoloFS で流用するため、MAS-067 v1.9 の B/S 引継ぎロジック改修は MAS-057 SoloFS にも自動適用される (SSoT) - MAS-071 報酬戦略シミュレーター: ApproachComparisonPanel が MAS-071 推奨額を直接参照するため、MAS-071 の 4 アプローチ算出ロジック更新は cockpit に即反映される
Step 7 関連テスト
Step 7 はクライアントサイド SPA + GAS API 両方をまたぐため、テストは複数レイヤで実施:
テスト 種別 内容 getSoloCEOY0Forecast()単体GAS テスト 64_pl_ytd_plan / 73_bs_plan 存在ケース + 73 未生成 → 71 フォールバックケース ApproachComparisonPanel 表示 手動 SPA 確認 A/B/C/D/AVG 5 列の数値整合 ( computeYearlyBreakdown5 回呼出結果と一致)SoloFS Y0 月数按分 手動 SPA 確認 y0Months=6 設定 → revenueMonthly / fixedCostMonthly / monthlySalary / dividendAnnual が Y0 のみ 1/2 にスケール SoloFS Y0 上書きトグル 手動 SPA 確認 トグル ON → Y0 P/L が forecast 値に切替 + Y1 期首 BS が forecast 期末 BS に連結 「実装が spec を先行 → spec を整合追従」のパターン累計 13 例目 (F-57 v2.1 PR #395 + 均等割修正 PR #399 + F-58 v2.0 PR #401 + F-66 v1.2 PR #403 + F-67 v1.5 PR #424 + F-67 v1.6 PR #427 + F-67 v1.7 PR #449 + F-57 v2.3 PR #454 + F-66 v1.2 + 本 v2.4 PR #459 で 13 例目)。
MAS-058 / MAS-061 / MAS-141 との連携(v1.9 から維持)
- MAS-058 必要年商シミュレーター: MAS-058 の Healthy 年商を入力した際、3 区分テーブルの「収入」「手取り」「純資産」が連動更新
- MAS-061 Cash ETR: 「法人税」行に Cash ETR の信号機(🟢/🟡/🔴)を併記し、節税余地を明示
- MAS-141 共済シミュレーター: 「純資産」行(特に老後の備え用途・Step 6.7)に共済積立の累積額を反映
「サンキー vs 3 区分テーブル」の使い分け(v2.1 で更新)
UI 主用途 表示優先度 3 区分テーブル(Step 6・15 細項目) 数値精度 + デッドヒート分析 + Y1-Y5 + 累積 + 改善示唆との連動 デフォルト表示・主要 UI サンキーダイアグラム(Step 5・既存) 流出構造の概観・初見ユーザーへの説明 <details>で折りたたみ補助化(v2.1 で副次化)実装ファイル(PR #394 で新規追加)
webapp_client/src/cockpit/AssumptionsPanel.tsx— 前提条件 16 項目入力 UIwebapp_client/src/cockpit/AssumptionsStore.ts— 前提条件 localStorage 永続化webapp_client/src/cockpit/ScenarioBar.tsx— シナリオ保存/呼出 UIwebapp_client/src/cockpit/ScenarioStore.ts— シナリオ localStorage 永続化(migration 含む)webapp_client/src/cockpit/ThreeSectionTable.tsx— 3 区分テーブル本体(Y1-Y5 タブ + 累積セクション)
MENU_DEFINITIONへの追加:- MAS-056 が追加予定の
🧭 意思決定対話(Web App)カテゴリに{ label: '🎛️ ビジュアルコックピット URL をコピー', funcName: 'copyF57CockpitUrl', description: 'F-57 ビジュアルコックピットの公開 URL をクリップボードにコピー' }を追加。MAS-056 未着手時は本案件内で同カテゴリを新規追加する。
- MAS-056 が追加予定の
03_sys_params に追加する MAS-057 固有パラメータ
| キー | デフォルト | 用途 |
|---|---|---|
F57_HOUSING_CALC_METHOD | SIMPLE_50 | 社宅賃貸料相当額の計算方式(SIMPLE_50 / FORMAL_FIXED_ASSET) |
F57_INVESTMENT_YIELD | 0 | 法人内部留保の想定運用益年率(5 カ年推移用・0〜0.05 想定) |
F57_OPTIMIZER_SALARY_STEP | 50000 | 役員報酬スキャンのステップ幅(MAS-056 のキーと衝突しないよう F57 プレフィックスで分離) |
F57_SANKEY_LIBRARY | D3 | サンキーダイアグラム描画ライブラリ(D3 / PLOTLY / CHARTJS) |
F57_INSIGHT_AI_MODEL | GEMINI_PRO | インサイト生成に使う AI(CLAUDE_SONNET / GEMINI_FLASH / GEMINI_PRO / CUSTOM)。v2.0 で default を CLAUDE_SONNET → GEMINI_PRO に変更: Vertex AI Anthropic Claude quota が dev で escalation 申請中 (記憶: gcp-quota-escalation) のため即時動作する Gemini を default 化。Claude quota 承認後は CLAUDE_SONNET 切替可能。CUSTOM は F57_GEMINI_MODEL_OVERRIDE_PRO/FLASH で実 model id を上書きするモード |
F57_INSIGHT_TRIGGER_MODE | EXPLICIT_BUTTON | AI インサイト発火条件(ONCHANGE_2SEC = ドロップダウン onChange 後 2 秒間追加変更なしで発火 / EXPLICIT_BUTTON = 「💡 更新」ボタンのみ)。v2.0 で default を ONCHANGE_2SEC → EXPLICIT_BUTTON に変更: コスト防衛・誤クリック防止・dev での AI quota 消費抑制を優先。v1.1 Major 4 でクオータ枯渇リスク低減・v1.8 でドロップダウン化に伴い ONMOUSEUP_2SEC から ONCHANGE_2SEC に改名・v2.0 で default を更に保守側へ |
F57_BONUS_PENSION_CAP_SINGLE | 1500000 | 厚生年金 1 回賞与上限(円)。calcBonusPremiums が賞与額をこの値で丸めてから料率を適用。2026 年法令値。v1.2 追加 |
F57_BONUS_HEALTH_CAP_YEARLY | 5730000 | 健康保険 年累計賞与上限(円)。1 会計年度の標準賞与額合計がこの値を超過した部分は健保対象外。2026 年法令値。v1.2 追加 |
F57_INCOME_INPUT_MODE | DROPDOWN_DISCRETE | 年収・配分 UI モード(DROPDOWN_DISCRETE = 本線・年収 50-100 万・月額 5 万・賞与 50 万 単位の離散ドロップダウン / SLIDER = 廃止予定・互換用のみ残置・新規実装非推奨)。v1.8 で SLIDER → DROPDOWN_DISCRETE に default 変更(ai_agent_tips.md §7 準拠) |
F57_INSIGHT_ENABLED | false | v2.0 新設。AI インサイト UI 表示制御フラグ。Vertex AI quota 障害や key 不在時に UI が壊れない防衛策として、明示的に true セットされない限り InsightPanel を描画しない。dev での試験運用後に true 切替を想定 |
F57_GEMINI_MODEL_OVERRIDE_PRO | (未設定 → コード側 default gemini-2.5-pro) | v2.0 新設。Gemini Pro 系の実 model id 上書き。F57_INSIGHT_AI_MODEL = GEMINI_PRO or CUSTOM 時に参照。新モデル(gemini-3-pro-preview 等)の検証時に切替 |
F57_GEMINI_MODEL_OVERRIDE_FLASH | (未設定 → コード側 default gemini-2.5-flash) | v2.0 新設。Gemini Flash 系の実 model id 上書き。F57_INSIGHT_AI_MODEL = GEMINI_FLASH or CUSTOM 時に参照 |
影響範囲
| 対象 | 変更内容 | リスク |
|---|---|---|
400_domain/ 新規 3 ファイル | 442_social_insurance_tier_engine.js / 443_corporate_housing_optimizer.js / 444_per_diem_policy_engine.js | 純粋関数のため既存ドメインロジックへの影響なし |
200_data/202_repository.js | SocialInsuranceTierRepository / PerDiemPolicyRepository 追加(計 2 件・v1.1 Critical 2 で IncomeTaxBracketRepository は廃止) | 既存 Repository には変更なし |
000_infra/002_constants.js | Constants.INCOME_TAX_BRACKETS 定数追加(v1.1 Critical 2・個人所得税一元管理)+ MENU_DEFINITION に Web アプリ URL コピー項目追加 | 既存 TAX_RATES との対称。税制改正時の更新箇所を本ファイルに一元化 |
100_config/101_sys_config.js | confSheet.appendRow 2 行 + schemas オブジェクトに 2 エントリ(v1.1 で 20_mst_income_tax_bracket / MST_INCM を廃止) | 既存スキーマへの変更なし。DDL 実行タイミングで新シートが自動作成される |
800_ops/812_migration_f57_tier_seed.js | 新規(マイグレーション運用ガイドライン準拠・v1.3 時点で 810 を想定していたが main 実装着手時に 810/811 が他案件で先行採用され 812 に繰り上げ・v1.5 で追従) | 冪等性必須(既に投入済みならスキップ) |
03_sys_params | 9 キー追加(v1.1 で 6 + v1.2 で 3: F57_BONUS_PENSION_CAP_SINGLE / F57_BONUS_HEALTH_CAP_YEARLY / F57_INCOME_INPUT_MODE) | 既存キーには影響なし |
000_infra/002_constants.js | MENU_DEFINITION に Web アプリ URL コピー項目追加(MAS-056 の 🧭 意思決定対話(Web App) カテゴリ内) | MAS-056 が先行してカテゴリを追加する前提。MAS-056 未着手時は本案件内で新規カテゴリ追加に切り替える |
templates/financial_cockpit.html | 新規(または MAS-056 の conversational_ui.html 実装後に非破壊タブ追加) | MAS-056 HTML 構造への干渉リスクあり → 独立 <div id="cockpit-tab"> として分離 |
900_test/901_test_runner.js | MAS-057 壁エンジンテスト追加 | 既存テストへの影響なし |
docs/_config.json | §E.5 FP&A・レポーティング に E.5.36 F-57 エントリ追加 | PR 競合に注意(編集前に git pull origin main) |
docs/_internal/changelog.md | 初版作成エントリ追加 | 影響なし |
appsscript.json | 変更なし(既存 cloud-platform スコープで Vertex AI 利用可能) | failure_patterns #26 部分追記禁止 |
注意事項
本案件の実装時に注意すべき既知の落とし穴・設計制約を failure_patterns.md の番号付きで列挙する。
#18-#20(命名造語禁止): 新設ファイル名・関数名・シート名・sysKey・メニュー名は Phase 1 の調査で実在確認した形(
MST_SOCI/MST_INCM/TMPL_PDIEM/442_social_insurance_tier_engine.js等)を厳密に使う。特にcalculateOptimalCompensation()は MAS-056 実装未着手時点では架空関数扱いであり、仕様書・コード内で参照する際は必ず「MAS-056 Phase 3 実装後に本エンジンを呼び出す」と明記し、未実装の関数を直接呼び出すコードを本案件で書かない。#25(並列実装対称性): 3 つの新設 Repository は
_getSheet/findAll/findAsMap/_cache/resetCacheの 5 要素を完全対称に実装する。IncomeTaxBracketRepositoryのみfindAsMapの代わりにfindAsBracketsを返す点は意図的な差分(所得税はブラケット順序依存のため)としてコメントに明記し、他の 2 Repository との非対称性が「書き忘れではない」ことを示す。#26(oauthScopes 部分宣言禁止): 確認済(2026-04-24)—
appsscript.jsonに既にhttps://www.googleapis.com/auth/cloud-platformが含まれているため、MAS-057 ではappsscript.jsonを一切編集しない。部分的に追記すると GAS の自動スコープ検出が完全に無効化され、既存の全機能でスコープ不足エラーが発生する。#27(Admin SDK API 変動): 該当なし(本案件は Vertex AI / スプレッドシート操作のみで Admin SDK を使用しない)。理由を注意事項に明記し「該当なし」と判断した旨を残す。
#21(
getLastColumn()列範囲膨張): 該当なし。新設マスタシートは列数固定・DDL 管理のためgetLastColumn()を動的使用しない。sheet.getRange(1, 1, 1, headers.length)のように列数を明示する。#22(
String.trim()で全角スペース残留):findAsMap()のキー正規化では.trim()だけでなく.replace(/[\s ]+/g, '')で全角スペースも明示除去する(等級名・規程名の入力ゆらぎ対策)。#23(
setValue("YYYY-MM")日付自動パース): 適用年度・開始年月はUtils.parseDateToYm(val)で正規化済みの文字列として管理し、setValue()で直接 "YYYY-MM" を渡さない(Google Sheets が YYYY-MM-01 として日付型に自動変換する事故を防止)。#24(
ARRAYFORMULA + MATCH脆弱性): 該当なし。サンキー・ドロップダウン UI はtemplates/financial_cockpit.html上の JavaScript(D3.js / Plotly 等)で計算描画するため、Sheets 数式によるラベル解決を行わない。DRY 原則(MAS-056 パラメータの非複製): 2026 年福井県料率(健保 9.71% / 介護 1.62% / 子ども子育て支援金 0.23% / 厚年 9.15% / 軽減税率 15% / インボイス 70% 控除)は MAS-056 が
F56_FUKUI_*キーで管理済。MAS-057 ではこれを**F57_*にコピーせず**Constants.getParam('F56_FUKUI_HEALTH_RATE', 0.0971)等で直接参照する。税制改正時の更新箇所を MAS-056 側に一元化する。税制改正追従ポリシー: 個人所得税累進税率(
20_mst_income_tax_bracket)・法人税軽減税率(Constants.TAX_RATES.brackets)・社会保険料率(17_mst_soci_tier)は毎年 3 月の税制改正後に手動更新する。更新責任者と更新 SOP を「人間が検討すべき事項」に明記し、MAS-049(賃上げ税制)仕様書の税制改正追従ポリシーと整合させる。MAS-056 との依存方向反転(v1.1 Major 3 反映): 当初案では MAS-057 が MAS-056 Phase 3 完了を待つ設計だったが、MAS-056 実装未着手のまま待つと MAS-057 もブロックされるため、依存を逆転する。MAS-057 Phase 1/2 で計算エンジン(
442_social_insurance_tier_engine.js/443_corporate_housing_optimizer.js/444_per_diem_policy_engine.js)を独立した公開 API として完成させ、MAS-056 実装時に MAS-057 エンジンを呼び出す形とする。MAS-057 Phase 3 UI のみ MAS-056 Phase 3 + MAS-232 SPA 基盤完了後に着手。クライアントサイド計算設計の堅持(v1.1 Critical 1 / v1.3 / v1.7 / v1.8 更新): Phase 3 UI は GAS
google.script.run通信レイテンシ(1〜3 秒)を避けるため、ドロップダウンonChange時の再計算をクライアントサイド JS で実行する。v1.8 で UI を連続スライダーから離散ドロップダウンに変更したが、レイテンシ排除の方針は引き続き有効(ai_agent_tips.md §7準拠・ドロップダウン化で 60fps 要件は不要になったが、即応性確保のため GAS 通信は引き続き最小化する)。v1.3 / v1.7 で「TypeScript 複製」方針を撤回し、単一ソース共有(SSoT)に変更済(詳細は注意事項 #14 参照)。同一入出力の担保は Phase 1 のテスト(901_test_runner.js)に加えて、クライアント側では同じ.jsファイルをそのまま読み込むため Jest 統合テストで同一ファイルを呼べる構成とする。Constants vs DDL の責務分離(v1.1 Critical 2 反映): 税率・料率パラメータは「毎年 3 月税制改正で全国一律に更新されるもの」と「会社固有で動的に更新するもの」で管理場所を分ける。全国一律の固定値(個人所得税ブラケット・法人税ブラケット・住民税率)は
002_constants.jsの定数、都道府県別・会社固有の動的値(社会保険料率の等級別・出張日当規程)は DDL シートに格納する。この方針を新規案件にも踏襲する。Pure Function 厳格化と単一ソース共有(v1.3 Critical / v1.7 で GAS-Vite ブリッジ方式を具体化):
400_domain/442_*.js/443_*.js/444_*.jsの新設ドメインエンジンは、SpreadsheetApp/UrlFetchAppだけでなくUtils/Constantsへの直接依存も排除する。Utils.parseAmt/Utils.persistLog/Constants.getParamは関数内で呼ばず、呼び出し元(Repository / UI 層)が引数として値を注入する。ログ出力が必要な場合は戻り値にwarnings: [{ level, message }]配列を含め、呼び出し元でUtils.persistLogを呼ぶ。
GAS と Vite のモジュールシステム非互換への対処(v1.7 Critical 反映・Gemini 指摘): GAS V8 ランタイムはexport/importの ESM 構文をネイティブサポートしないため、.jsに ESM 構文を書くと GAS 実行時にSyntaxErrorになる。そのため新設エンジンの.jsファイルは GAS 側で直接動作するvar SocialInsuranceTierEngine = (function () { ... return { findTier, calcPremiums, ... }; })();の IIFE + グローバル変数宣言パターン とする(Phase 1 実装442_social_insurance_tier_engine.jsの方式に準拠)。Vite 側の import には以下のいずれかを採用:
(a)vite-plugin-commonjs/ CJS 変換プラグイン で GAS 側のグローバル変数宣言を CJS モジュールとして読み込む
(b)windowオブジェクトへの露出: ビルド時に.jsの末尾でif (typeof window !== 'undefined') window.SocialInsuranceTierEngine = SocialInsuranceTierEngine;をラップ(GAS 側ではwindowが未定義なので安全)
(c) UMD ラッパー生成: 既存のvar宣言コードを Rollup 等で後付け UMD 化するビルドステップを Vite 設定に組み込む
これにより GAS 環境 / ブラウザ環境 / Jest テスト環境で同じ.jsファイルを変更なしに使い回せる(TypeScript 複製は禁止)。MAS-232(Vite+React SPA 基盤)の PoC で (a)(b)(c) のどれを採用するか実測で決定する(「人間が検討すべき事項」参照)。税務否認リスクへの UI ガードレール(v1.3 Major 反映・BRD §5/§8 免責事項と整合): 本システムは数値シミュレータであり、税理士・社労士の個別助言に代わるものではない。Phase 3 UI 実装時に以下を必須とする: (a) 賞与比率 ≥ 40% 検知時の赤枠警告バナー、(b) 月額が最低等級に到達した際の「社保免脱目的と認定されるリスク高」警告、(c) 画面下部の常時表示免責文(「本シミュレータの出力は税理士・社労士の個別助言に代わるものではありません」)、(d) 事前確定届出給与の届出期限アラート(BRD §6 参照)。これらは
F57_INSIGHT_AI_MODEL等の AI 生成ではなくルールベースで常時表示とし、AI 障害時も機能する設計とする。【v2.0 追記】V8→Java シリアライズの Infinity / NaN silent null(Phase 3 実装時に実機検出): GAS Web App から
google.script.run経由で関数を呼んだ際、戻り値オブジェクトのどこかにInfinity/-Infinity/NaNが含まれていると、V8→Java ブリッジでのシリアライズが失敗し、withSuccessHandlerに null が渡る(withFailureHandlerは呼ばれない・throwもない・GAS エディタ直接実行ではJSON.stringifyも成功するため検知困難)。HAR で見ると:op.exec[0, null, "<Java HashMap.toString>"]— 第二要素が null・第三要素に Java toString が入る。対策: bootstrap でConstants.INCOME_TAX_BRACKETS.brackets[6].upTo = Infinityのような既知 Infinity をNumber.MAX_SAFE_INTEGER(9007199254740991)に scrub。Repository 経由で取得する値もNumber.isFinite()で防御的にチェック。切分テクニック(実装時の手順): ①静的 probe 関数(Date と string のみ返す)で通信経路を確認 → ②関数内でJSON.stringifyを呼んで length をconsole.log→ ③それでも null なら必ず Infinity / NaN / 関数 / 循環参照を疑う → ④最終手段は HAR エクスポートでop.exec[0, ...]の中身を確認。failure_patterns.md #29も参照。【v2.0 追記】Vertex AI Gemini 3 系は dev 未有効化(Phase 3 実装時に実機検出):
gemini-3-pro-preview/gemini-3.1-pro-previewはbizlp-gas-accounting-devの Vertex AI で HTTP 404 (Publisher Model not found)。Model Garden で個別 Enable + 48h 課金履歴経過が必要。MAS-057 Phase 3 実装時点ではgemini-2.5-proを default に運用し、UI のCUSTOMオプション +F57_GEMINI_MODEL_OVERRIDE_PRO経由で 3.x 系の有効化検証が可能な設計とした。failure_patterns.md #30も参照。【v2.0 追記】deployment ID の二重管理リスク(Phase 3
copyF57CockpitUrl実装時に判明):ScriptApp.getService().getUrl()は GAS が認識する最新の deployment URL を返すが、scripts/deploy.shで固定運用している共有 deployment ID(チーム標準 URL)と異なる ID を返す場合がある(手動デプロイ等で枝分かれ)。copyF57CockpitUrlではdeploy.shの deployment ID をハードコード(Env.isDev()で dev/prod 切替)し、URL のホスト・ドメイン部だけgetService().getUrl()から流用する形を採用。【v2.1 追記】Gemini Deep Think 発見の MAS-067 機能を MAS-057 Step 6 で先行実装: PR #394 では MAS-067 (マルチイヤー計画) の MAS-334 議論と Step 6 実装が並行して進められた結果、Gemini Deep Think (MAS-334 Section G) で発見された複数の独自機能を MAS-067 着手前に MAS-057 Step 6 で先行実装している。具体的には: (a) Step 6.6 社長稼働限界 (Burnout) メーター = MAS-334 Section MAS-239 (ナレッジワーカー型 1 人社長の物理破綻ゾーン検知)、(b) Step 6.13 役員報酬最低月額 = MAS-334 由来の AI インサイト制約 (生活費ベースの下限制約)、(c) Step 6.12 月額年次増加額 = MAS-334 マルチイヤー判定の前提となる Y_n offset。これらは MAS-067 v1 spec にも別途記載されているが、MAS-057 Step 6 の単年×Y1-Y5 タブで「マルチイヤー計画の入口」として先行体験できる構成にすることで、MAS-067 実装着手時の UI 設計判断材料を確保している。MAS-067 実装時は MAS-057 Step 6.6 / 6.13 の入力値を引き継ぐ前提で設計する。
【v2.1 追記】簡易実装の明示が必要な機能リスト(PR #394 実装時の妥協点を spec に明示記録・v2.1.1 で (f) は ✅ 解決済化): Step 6 の以下 6 機能のうち (a)-(e) は v1 スコープを優先して簡易実装としており、ユーザーへの注記表示と将来改修候補としての記録を残す。(f) は v2.1 → v2.1.1 で PR #397 により実装修正完了:
- (a) 住宅ローン減税 (Step 6.14): 年額固定 × 5 年で実装。本来は 残高 × 0.7% で年々減少・13 年期間・住宅種別 (認定長期優良住宅 / 一般住宅 等) 別の上限差。精密計算は別案件 (人間検討事項 #16) として切出推奨
- (b) 老後の備え (個人) (Step 6.7): 共済 + 法人保険資産計上分のみ計算。NISA / iDeCo / 個人年金保険は未対応 (v2 候補・人間検討事項 #17)
- (c) 万一の備え (Step 6.7): 個人/法人保険料の払込累計をそのまま給付想定として表示。実際の給付倍率は 3-10 倍が一般的であるため、UI に「実給付額は商品で異なる」旨の注記を必ず併記
- (d) 退職所得控除の 5 年/19 年ルール (Gemini Deep Think 発見 #2): 小規模企業共済と法人退職金の枠の食い合いトラップは未実装。MAS-067 v1 で本格対応予定
- (e) 創業費 (Step 6.8): 全額一括損金算入の簡易扱い。本来は 5 年定額償却 or 任意償却の繰延資産
- (f) 法人住民税 均等割 70,000円/年 (2026-04-28 ユーザー指摘で発覚 → ✅ 同日 PR #397 で解決済・v2.1.1 で追従):
Constants.TAX_RATES.localMinimumAnnual = 70000は元々定義済だったが Step 6 cockpit 実装のcalcResult内で加算されていなかった (黒字でも常に + 7 万円が税法上の正解・「ミニマム値」ではない)。齋藤 Baseline (税引前利益約 750 万・21.4% ブラケット) で実効税率を約 +0.9pt 過小評価していた。MAS-013 投資分析600_report/610_service_investment_analysis.js:227-246も「ミニマムモデル」(赤字時のみ 7 万・黒字時は加算なし) で実装されており税法上バグだった。PR #397 修正内容: (1)300_ui/302_spa_bridge.jsの bootstrap にlocalMinimumAnnualを追加配信、(2)webapp_client/src/cockpit/calc.tsで corporateTax 累進計算後にMath.round(localMinimumAnnual * monthsActive / 12)を常時加算 (Y1 短縮事業年度は monthsActive で月割按分・法人住民税均等割の月割が原則)、(3)600_report/610_service_investment_analysis.jsのcalcEffectiveTaxRate_で黒字時にも minAnnual を加算、(4)docs/spec/sidebar_api.d.tsのF57CockpitBootstrap型にlocalMinimumAnnual: number追加。法人住民税の構造: 均等割 (固定費・資本金 + 従業員数で決まる・赤字でも黒字でも常に発生) + 法人税割 (法人税 × 7%・所得連動) の 2 層構造。MAS-057 cockpit と MAS-013 投資分析の両方で前者が抜けていたが、PR #397 で両方とも税法準拠 (常に + 7 万円) に統一済。
エッジケース
実装時に必ずテーブル記載の 26 件(v1.0 で 14 件 → v1.1 で +3 件 → v1.2 で +1 件 → v2.0 で +4 件 → v2.1 で +5 件)を単体テストでカバーする。条件 / 検知方法 / 期待される挙動 / ログ出力を明示。
| # | 条件 | 検知方法 | 期待される挙動 | ログ出力 |
|---|---|---|---|---|
| 1 | 17_mst_soci_tier 未作成 or 0 行 | SocialInsuranceTierRepository.findAll().dtos.length === 0 | 計算を中止し UI に「等級マスタ未初期化」エラー表示。既定値フォールバックは禁止(誤った計算結果の流出防止) | Utils.persistLog('ERROR', 'SocialInsuranceTierEngine.findTier', '等級マスタ未初期化', '') |
| 2 | 役員報酬が厚生年金上限(標準報酬月額 65 万等級・月収目安 63.5 万超)を超過 | monthlyCompensation > 等級表の最大下限額 | 最大等級に丸めて計算し、戻り値に { ..., isOverCap: true, note: '厚年上限超過' } を含める。UI に「壁なし警告バナー」を表示 | Utils.persistLog('WARN', ..., '厚年上限超過: ' + monthlyCompensation, ...) |
| 3 | 役員報酬が等級表の最小下限を下回る(例: 月 5.8 万未満) | monthlyCompensation < 最小等級下限 | 最小等級に丸めて計算 + UI に「最低等級フロア警告」表示 | Utils.persistLog('WARN', ...) |
| 4 | 等級マスタに同一等級コードが重複登録 | findAsMap() でキー衝突 | 先着(最初の行)採用。二行目以降は黙殺し WARN ログ | Utils.persistLog('WARN', 'SocialInsuranceTierRepository.findAsMap', '重複等級: ' + code, '先着採用') |
| 5 | ドロップダウン or 直接入力でゼロ or マイナス値が入力 | Number(val) <= 0 | 最小等級フロア値にクランプ + UI に赤バナー「入力値は正の数値のみ」(ドロップダウンの選択肢は正の値のみ提供する設計だが、URL パラメータや開発者ツール経由の不正入力に対する防御的バリデーション) | Utils.persistLog('WARN', ...) |
| 6 | 売上または法人利益がゼロ(ゼロ除算) | 分母 = 0 の計算パス | 比率は "—" 表示、金額は 0 で返却。UI に「計算不可(売上ゼロ)」を表示 | なし(正常系扱い) |
| 7 | 社宅家賃の個人負担割合が 0% 未満 or 100% 超 | rate < 0 || rate > 1 | 0 または 1 にクランプ + UI に「0〜100% の範囲で入力してください」警告 | Utils.persistLog('WARN', 'CorporateHousingOptimizer.calcRentAllocation', ...) |
| 8 | callClaudeApiOnVertex_() が null を返す(ネットワーク障害・Vertex AI 障害等) | 戻り値 === null | UI に「インサイトを生成できませんでした(計算結果は正常)」を表示。ドロップダウン・サンキーは正常描画を維持 | Utils.persistLog('ERROR', 'F57.generateInsight', 'Vertex AI null response', ...) |
| 9 | AI レスポンスの JSON パース失敗 | JSON.parse() が例外 | try-catch で捕捉し固定フォールバックメッセージ(「現在の数値では明確な改善提案ができません」)を返す | Utils.persistLog('ERROR', 'F57.generateInsight', 'JSON parse failed: ' + e.message, rawResponse.slice(0, 200)) |
| 10 | AI に渡す推移データ(5 カ年分)がトークン上限超過 | JSON.stringify(data).length > 10000 | 直近 12 ヶ月分のサマリーのみに縮小して再送信 | Utils.persistLog('WARN', ..., 'token limit prune', ...) |
| 11 | 03_sys_params で F57_* キー未設定 | Constants.getParam(key, defaultVal) が defaultVal を返す | 仕様書記載のデフォルト値で継続 + 初回のみ INFO ログ | Utils.persistLog('INFO', 'F57.init', 'F57_* keys not set; using defaults', ...) |
| 12 | Constants.INCOME_TAX_BRACKETS.brackets が空配列または未定義 | !Constants.INCOME_TAX_BRACKETS || Constants.INCOME_TAX_BRACKETS.brackets.length === 0 | Constants.TAX_RATES.brackets(法人税)をフォールバックにしない。コード不整合として例外を投げる(リリース時のコードレビューで防げる想定) | Utils.persistLog('ERROR', 'F57.calcIncomeTax', 'INCOME_TAX_BRACKETS 未定義 — 002_constants.js 要確認', '') |
| 13 | MAS-056 実装未着手時に MAS-057 コックピット UI を起動 | typeof calculateOptimalCompensation === 'undefined' | MAS-057 Phase 1 エンジン単体で動作し、最適役員報酬の自動探索は「MAS-056 実装後に有効化」とグレーアウト表示 | Utils.persistLog('INFO', 'F57.init', 'F-56 未実装のため単体モードで起動', '') |
| 14 | 並行実行(複数タブでドロップダウン操作) | LockService.getDocumentLock().tryLock(1000) が失敗 | 後勝ちせず、UI に「他のタブで計算中です。しばらくお待ちください」表示 | Utils.persistLog('WARN', 'F57.recalc', 'LockService tryLock failed', '') |
| 15 | 適用年月がまたがる料率更新(年度跨ぎ計算) | Utils.parseDateToYm(val) 結果が計算対象期間と異なる | 「適用開始年月」列の最新有効レコードを使用。該当期間に料率変更があった場合は月別に分割計算 | Utils.persistLog('INFO', ..., '料率変更検知: ' + oldYm + ' → ' + newYm, ...) |
| 16 | 40 歳境界値(介護保険料のオン/オフ切替・v1.1 Minor 5 反映) | isOver40 = age >= 40 で判定。39 / 40 / 41 歳のケース | 39 歳 = 介護保険料ゼロ / 40 歳・41 歳 = 介護保険料率(0.0162)を健保料に加算。生年月日が会計期間内に 40 歳到達する場合は月割り対応(将来拡張) | Utils.persistLog('INFO', 'SocialInsuranceTierEngine.calcPremiums', '介護保険料適用: age=' + age, ...) |
| 17 | クライアントサイド計算の数値不整合(v1.1 Critical 1 反映) | クライアント JS と GAS サーバー側で同一入力に対し異なる出力 | 開発時に統合テスト(Phase 1 GAS テスト + クライアント Jest の同一入出力マトリクス)で検知。実運用時は AI インサイトに「サーバー再計算値との差分が X 円以上」検知を組み込み警告表示 | console.error + テレメトリログ送信(将来拡張) |
| 18 | 【v2.0 追記】bootstrap レスポンスの Infinity / NaN(注意事項 #16 由来) | クライアントで state === null(withSuccessHandler に null が渡る・throw なし) | サーバー側で Constants.INCOME_TAX_BRACKETS.brackets[6].upTo の Infinity を Number.MAX_SAFE_INTEGER(9007199254740991)に scrub 済。bootstrap 失敗時は state.error に診断メッセージを格納 | サーバー側 Utils.persistLog('ERROR', 'F57.bootstrap', 'JSON.stringify length: ' + len, '') |
| 19 | 【v2.0 追記】Vertex AI Gemini モデル未有効化(HTTP 404)(注意事項 #17 由来) | _callVertexGeminiForF57Insight_ で全リージョン(global / us-east5 / us-central1 / asia-northeast1)が 404 を返す | UI に「全リージョンで失敗」エラー詳細を表示。計算結果自体は正常維持(インサイトのみ失敗扱い) | 各リージョンのエラー詳細を集約して Utils.persistLog('WARN', 'F57.callVertexGemini', regionErrors, model) |
| 20 | 【v2.0 追記】UrlFetchApp 帯域幅クォータ枯渇 | fetch 例外: 「帯域幅の上限を超えています」メッセージ | UI にエラーメッセージ表示 + 数分待機案内 + リトライボタン。GAS 1 日のクォータリセット(PT 0:00)まで一時的に Vertex AI 呼出不可 | Utils.persistLog('ERROR', 'F57.callVertexGemini', 'UrlFetchApp quota exhausted', '') |
| 21 | 【v2.0 追記】Web App OAuth 未認可(executeAs:USER_DEPLOYING + access:MYSELF) | google.script.run が iframe(userCodeAppPanel?createOAuthDialog=true)を返す | GAS エディタから関数を一度実行して認可ダイアログを通過させる手順を README に明記。Web App デプロイ時に必ず通過する setup ステップとして文書化 | — |
| 22 | 【v2.1 追記】旧シナリオ(revenueAnnual で保存)のロード(Step 6.9 / 6.11 由来) | _migrateInputs / _migrateAssumptions で旧キーを検知 | 月単位フィールドに自動変換(revenueAnnual → revenueMonthly = revenueAnnual / 12)し、新フィールド(variableCostRate / directorMonthlyRate / livelihoodMinimumSalary 等)は default 値で fill | console.info('Scenario migrated from v0 schema', oldKeys) |
| 23 | 【v2.1 追記】シナリオロード時に前提条件まで上書きされる(Step 6.9 / 6.10 由来) | ScenarioStore.load() が AssumptionsStore の管理キーを Variables に含めてしまうケース | ASSUMPTION_KEYS 配列で除外し Variables のみ pick して上書き。前提条件は維持して「前提 × シナリオ」のマトリクス試算を成立させる | — |
| 24 | 【v2.1 追記】想定貢献年商 0(月額単価 0)(Step 6.6 由来) | r.directorAnnualValue === 0 で実効稼働率も 0 | 警告なし(入力ゼロ時は計算スキップ・Burnout メーター非表示) | — |
| 25 | 【v2.1 追記】法人税引前利益が負(赤字)(Step 6.4 実効税率併記由来) | corporatePreTax <= 0 で実効税率分母なし | 「—」表示・税額は 0。実効負担率は売上比のため計算継続 | — |
| 26 | 【v2.1 追記】Y1 月数 0(Step 6.8 創業月数按分由来) | firstYearMonths === 0 | Math.max(1, firstYearMonths) で 1 にクランプ。1 ヶ月稼働として扱う(創業費は満額計上) | console.info('Y1 months clamped to 1', input) |
実データ検証
実装完了後に以下の数値を GAS 実行 or MCP で確認し、手計算値と一致することを仕様書完成の必須条件とする。
齋藤 Baseline(BRD §8・Phase 1 検証データ)
入力: 月収 500,000 円 / 福井県料率(2026 年 3 月〜)/ 40 歳未満(介護保険なし)
| 項目 | 手計算期待値 | 確認方法 |
|---|---|---|
| 標準報酬月額等級(健保) | 30 等級(50 万円) | SocialInsuranceTierEngine.findTier(500000, tierMap).healthGrade === 30 |
| 標準報酬月額等級(厚年) | 20 等級(50 万円) | 同 .pensionGrade === 20 |
| 健保料(労使合算) | 500,000 × 0.0971 = 48,550 円/月 | calcPremiums 戻り値 .healthPremium === 48550 |
| 厚年保険料(労使合算) | 500,000 × 0.0915 = 45,750 円/月 | .pensionPremium === 45750 |
| 子ども子育て支援金 | 500,000 × 0.0023 = 1,150 円/月 | .childcareLevy === 1150 |
| 年間社会保険料合計(労使合算) | (48,550 + 45,750 + 1,150) × 12 = 1,145,400 円 | ±100 円以内で一致 |
| 法人側負担(労使折半後) | 572,700 円/年 | 合算の半分 ±50 円 |
| 個人側負担(労使折半後) | 572,700 円/年 | 同上 |
13 パターンスキャン(Phase 3 検証データ)
役員報酬 月 25 万 / 30 万 / 35 万 / ... / 85 万(5 万刻み 13 パターン)× 齋藤 Baseline 固定費 → 各シナリオで法人手残り / 個人手残り / 合算純資産を算出し、合算純資産が最大となる役員報酬額を特定する。
期待される定性的結論: 厚年上限(標準報酬月額 65 万・月収目安 63.5 万)付近で「厚年は頭打ち、健保と所得税は上昇し続ける」局面に入るため、純資産最大化ポイントは標準報酬月額 50 万〜65 万の等級帯に落ち着く可能性が高い(齋藤 Baseline の年商 1,680 万 / 固定費 240 万 / 原価 0 の前提下)。実装後に数値で検証する。
個人所得税ブラケットの整合確認
20_mst_income_tax_bracket の 2026 年時点値(総合課税・所得控除後の課税所得に対し):
| 課税所得ブラケット | 税率 | 控除額 |
|---|---|---|
| 〜195 万 | 5% | 0 |
| 195 万〜330 万 | 10% | 97,500 |
| 330 万〜695 万 | 20% | 427,500 |
| 695 万〜900 万 | 23% | 636,000 |
| 900 万〜1,800 万 | 33% | 1,536,000 |
| 1,800 万〜4,000 万 | 40% | 2,796,000 |
| 4,000 万〜 | 45% | 4,796,000 |
これを住民税 10% と合算したものが「個人側実効税率」となり、Constants.TAX_RATES.brackets(法人実効 21.4% / 33.6%)との交点がデッドヒート分岐点となる。
賞与配分による社保総額逆転点(v1.2 追加・v1.7 で main Phase 1.5 実装と ±1 円一致に更新・齋藤 Baseline 年収 600 万固定 × 配分 4 パターン)
年収 600 万円を固定し、月額 × 賞与の配分を 4 通り変えた場合の年間社保総額(労使合算)。下表は calcBonusPremiums / calcPremiums 実装(PR #354 Phase 1 + PR #356 Phase 1.5)と ±1 円一致する数値(v1.7 で main 実装に整合、単体テスト F57-22 〜 F57-39 で担保)。福井県 2026 年 3 月料率(健保 9.71% / 厚年 9.15% / 介護 0%(齋藤 40 歳未満想定・40 歳以上の場合は健保 base に 1.62% 加算) / 子ども子育て支援金 0.23%)を使用。
重要: 月額側の社保は月額報酬そのものではなく、17_mst_soci_tier の標準報酬月額等級に丸めた額に料率を乗じる(例: 月額 40 万 → 健保 27 等級 = 標準 41 万)。spec v1.5 までは等級丸め前の raw 月額で試算していたため実装と差が出ていた(v1.7 で修正)。
| パターン | 月額報酬(丸め後) | 賞与 | 月額側社保(年額・労使合算) | 賞与側社保(年額・合算) | 年間社保合計 | Baseline A 差分 |
|---|---|---|---|---|---|---|
| A: 全額月額 | 50 万(等級 30・標準 50 万)× 12 | 0 | 1,145,400 円 | 0 | 1,145,400 円 | ±0(Baseline) |
| B: 夏冬賞与各 60 万 | 40 万(等級 27・標準 41 万)× 12 | 60 万 × 2(= 年累計 120 万) | 939,228 円 | 229,080 円(両上限未満) | 1,168,308 円 | +22,908 円(増加) |
| C: 賞与 240 万 × 1 回 | 30 万(等級 22・標準 30 万)× 12 | 240 万 × 1 | 687,240 円 | 373,740 円(健保は全額 240 万対象 / 厚年・子ども子育ては 150 万頭打ち = 上限突破部分 90 万は厚年・子育てゼロ) | 1,060,980 円 | -84,420 円(削減) |
| D: 賞与 150 万 × 2 回 | 25 万(等級 20・標準 26 万)× 12 | 150 万 × 2(= 年累計 300 万) | 595,608 円 | 572,700 円(厚年 1 回上限ジャスト・突破なし・健保累計も上限未満) | 1,168,308 円 | +22,908 円(増加) |
パターン C の上限突破内訳(±1 円一致の計算根拠)
賞与 240 万円 × 1 回(齋藤 40 歳未満・他の賞与なし):
- 標準賞与額 =
Math.floor(2_400_000 / 1000) * 1000= 2,400,000 円(千円未満切り捨て・元々切り捨て対象なし) - 健保 base =
min(2_400_000, yearlyCapHealth=5_730_000 - accumulated=0)= 2,400,000 円(年累計上限 573 万以内のため全額対象) - 厚年 base =
min(2_400_000, singleCapPension=1_500_000)= 1,500,000 円(1 回上限ちょうどで丸め) - 子ども子育て base = 厚年と同様 1,500,000 円(上限共通)
- 健保 =
round(2_400_000 × 0.0971)= 233,040 円 - 厚年 =
round(1_500_000 × 0.0915)= 137,250 円 - 子ども子育て =
round(1_500_000 × 0.0023)= 3,450 円 - 介護 = 0(40 歳未満)
- 賞与側合計 = 233,040 + 137,250 + 3,450 = 373,740 円
- 上限突破効果(Baseline A 比): 240 万 - 150 万 = 90 万円部分について「厚年 0.0915 + 子ども子育て 0.0023 = 0.0938」の料率がゼロ化 → 900,000 × 0.0938 ≒ 84,420 円の社保削減 が主因
定性的結論(v1.7 更新)
齋藤 Baseline(年収 600 万・40 歳未満)の範囲では、**パターン C(賞与 240 万 × 1 回で厚年 1 回上限 150 万超過)**が社保年 約 8.4 万円削減で唯一の最有利。
- パターン B/D は逆に Baseline より約 2.3 万円増加: 月額を下げると標準報酬月額等級も下がるが、丸め後の標準額(B: 41 万 / D: 26 万)で計算した月額側社保が Baseline A を上回るほどではない。しかし賞与側の社保が加算されるため、賞与で上限突破が起きない配分(B: 60 万 × 2 / D: 150 万ちょうど × 2)では配分のメリットゼロ + 賞与社保分だけ増えて損になる。
- パターン D の誤認注意: v1.5 spec では「150 万ちょうどなら上限ギリギリで突破効果あり」と誤解していたが、実装では
min(1_500_000, 1_500_000) = 1_500_000で丸めが発生せず突破効果ゼロ。151 万以上にしないと厚年上限突破は発動しない。 - パターン A(Baseline)は同率で 2 位: D と同じ年間合計(1,168,308 円)だが、A は賞与ゼロなので届出リスクなし(定量的に同じなら A が実務的に安全)。
実装後に本計算値と ±1 円で一致することを単体テスト基準とする(F57-22 〜 F57-39 で担保済・901_test_runner.js)。
上限の種類を混同しないこと
| 対象 | 上限の種類 | デフォルト値 | パラメータキー | 超過時 |
|---|---|---|---|---|
| 厚生年金保険料 | 1 回賞与上限 | 1,500,000 円 | F57_BONUS_PENSION_CAP_SINGLE | 超過部分は厚年ゼロ |
| 子ども子育て拠出金 | 1 回賞与上限(厚年と共通) | 1,500,000 円 | 厚年上限を共用 | 超過部分は拠出金ゼロ |
| 健康保険料 | 年累計賞与上限 | 5,730,000 円 | F57_BONUS_HEALTH_CAP_YEARLY | 年累計超過部分は健保ゼロ |
| 介護保険料(40 歳以上) | 健保 base に連動 | — | — | 40 歳未満はそもそもゼロ |
この非対称性(厚年は 1 回単位・健保は 年累計)が「パターン C で厚年だけ頭打ちになり賞与を 1 回に集約すると有利」の本質的理由。両方とも 1 回上限と誤認してはならない。
実務上の制約警告: パターン C は事前確定届出給与の届出が必須。届出タイミング(株主総会決議日から 1 ヶ月以内、または事業年度開始日から 4 ヶ月以内の早い日)を逃すと損金算入不可となり、逆に不利になるリスクがある点を UI インサイトで常時表示する。また税務否認リスク(BRD §5 / §8 参照・年収の 40% 以上の賞与配分は「社会保険料免脱目的」と認定されるリスク)も併記する。
40 歳境界値テスト(v1.1 Minor 5 反映・Phase 1 単体テスト)
介護保険料の適用有無が分かれる境界。calcPremiums(tier, { isOver40 }) の isOver40 フラグ切替で以下を確認:
| 年齢 | isOver40 | 介護保険料(労使合算) | 合計保険料との差分 |
|---|---|---|---|
| 39 歳 | false | 0 円(適用外) | 基準値 |
| 40 歳(到達月) | true | 500,000 × 0.0162 = 8,100 円/月 | +8,100 円/月・+97,200 円/年 |
| 41 歳 | true | 同上 8,100 円/月 | 40 歳と同一 |
実装時に 901_test_runner.js に「境界 age = 39/40/41 で介護保険料が 0 / 8100 / 8100」を期待値として追加。会計期間内に 40 歳到達する場合の月割り対応は将来拡張として「人間が検討すべき事項」参照。
AI インサイト出力検証(Phase 3)
齋藤 Baseline + 月報酬 45 万入力時に callClaudeApiOnVertex_ で生成されるインサイトが以下の要件を満たすこと:
- 数値が具体的(「5 万円下げる」「手残り X 万円増」など)
- 社会保険料壁ロジックを言及(「等級が下がる」「厚年保険料が Y 円減る」)
- 3 文以内で簡潔
関連ドキュメント
- BRD:
docs/brd_solo_ceo_financial_navigator.md— 本案件の起点となる Vision / Mission / ドメインロジック / UX 戦略 - MAS-056 意思決定対話 UI:
docs/dev/dev_mas-056_conversational_scenario_ui.md— Chat UX 側の姉妹案件。calculateOptimalCompensation()の仕様元。MAS-057 UI 統合時の HTML 構造参照元 - MAS-011 What-if:
docs/dev/dev_mas-011_what_if_simulation.md— 5 カ年推移計算エンジン - MAS-013 投資分析:
docs/dev/dev_mas-013_investment_simulation.md— NPV/IRR 計算エンジン - MAS-048 採用 TCO:
docs/dev/dev_mas-048_hiring_tco_bep_simulator.md— 将来採用時の TCO 計算(1 人法人フェーズでは参考のみ) - MAS-049 賃上げ税制:
docs/dev/dev_mas-049_wage_increase_tax_credit_simulator.md— 税制改正追従ポリシーの前例 - 失敗パターン:
docs/_internal/failure_patterns.md— 特に #18-#20(命名造語)/ #25(並列実装対称性)/ #26(oauthScopes 部分追記) - PRD プロダクトポリシー:
docs/prd.md— Human-in-the-Loop 原則 - CLAUDE.md: プロジェクトルール、ブランチ運用、ファイル番号体系、コーディング規約
- D.11 財務意思決定プロセス: MAS-056 派生元。9 ステップ意思決定プロセスの Step 9「個人 B/S + 法人 B/S 統合」が本案件の中核
人間が検討すべき事項
実装着手前に決定が必要な論点を列挙。Deep Research 論点 10 件 + Claude 追記 17 件の計 27 件(v1.2 で +3 / v2.1 で +3)。
Deep Research 推奨論点(BRD 由来・10 件)
- MAS-056 と MAS-057 の UI 統合形態: 単一 Web App 内タブ切替(Chat タブ / Visual Cockpit タブ)vs 独立 Web App 2 つ(別
doGetエントリ)。推奨は単一 Web App だが、URL 共有の観点で独立化も検討余地あり。 - 標準報酬月額マスタの年次更新フロー:
17_mst_soci_tierを DDL 管理(setupAllSchemasで初期化)+812_migration_f57_tier_seed.jsでデータ投入、とした場合、毎年 3 月の料率更新をどう運用するか(手動 SQL 的更新 or 新マイグレーションスクリプト発行)。 - 社宅家賃の賃貸料相当額計算方式の選定: 正式法(固定資産税評価額ベース)vs 簡便法(賃料の 50%)。正式法は評価証明書取得コスト、簡便法は税務調査リスクのトレードオフ。
F57_HOUSING_CALC_METHODパラメータで切替可能に設計するが、デフォルトをどちらにするかは税理士判断が必要。 - 出張日当規程テンプレの粒度: 単価固定(1 日 N 円)vs 距離別・宿泊有無別テーブル(JR 片道 200km 超で M 円等)。
13_tmpl_per_diem_policyのカラム設計を単価固定でスタート、将来拡張で距離別に追加する方針で問題ないか。 - 共済の出口リスク警告表示: MAS-141 の責務だが、MAS-057 UI で積立額ドロップダウンを操作する際に「経営セーフティ共済は解約後 2 年以内再加入不可(2024/10 改正)」等の注意喚起を同じ画面で表示するか、MAS-141 画面に誘導するか。
- 累進税率テーブルの管理形態:
DDL(→ ✅ v1.1 確定:20_mst_income_tax_bracketシート)vs JSON ファイルConstants.INCOME_TAX_BRACKETS定数で管理(Gemini レビュー Critical 2 反映)。法人税Constants.TAX_RATES.bracketsと対称な Constants 一元管理とし、税制改正時の更新箇所を002_constants.jsに集約する。 - サンキーダイアグラムライブラリ選定: D3.js
sankey-diagram(カスタマイズ性高・学習コスト)/ Plotly.js sankey(簡潔・ブランディング制約)/ Chart.js sankey 拡張(軽量・機能限定)。MAS-056 Vite+React 基盤との親和性も考慮。 - 法人内部留保運用益率のデフォルト値:
F57_INVESTMENT_YIELDのデフォルト 0%(控えめ)/ 3%(インフレ連動)/ 5%(積極運用)。保守的デフォルト推奨だが、UX 上「運用しない」が前提のように見えるとリアリティ欠如のリスクあり。 - インサイト生成アルゴリズム: ルールベース(「等級が下がる」テンプレ文字列 + 数値埋め込み)/ LLM 生成(
callClaudeApiOnVertex_/callGeminiForReasoningOnVertex_経由)/ ハイブリッド(数値計算はルール・自然言語整形は LLM)。ハイブリッド推奨だが、コスト試算が必要。 - 「額面 → 手残り」パラダイムシフトのオンボーディング UX: 初回起動時にチュートリアルダイアログ表示(BRD Vision を文章で説明)/ ツールチップのみ / 何もしない。認知シフトを起こすための初期教育の強度。
Claude 追記論点(実装時リスク・17 件・v1.2 で +3 / v2.1 で +3)
MAS-056 との依存方向反転の整合確認(v1.1 Major 3 反映・✅ 方針確定): MAS-057 Phase 1/2 は MAS-056 実装状態に依存せず独立完成する方針に変更した。MAS-056 実装時に
calculateOptimalCompensation()が MAS-057 エンジン(442_social_insurance_tier_engine.js等)を呼び出す設計とするため、MAS-056 仕様書(PR #350)側にも「MAS-057 エンジンを内部で使用する」旨を追記する必要がある(PR 別途)。シート番号 17 / 20 / 13 の二度採番リスク: 2026-04-24 grep 時点では空きだが、他案件(例: MAS-055 が 19_tmpl_saas_catalog を予約済)と同様に他の未着手案件が同番号を狙っている可能性。実装着手直前に再 grep 確認する旨を Phase 3 チェックリストに含める。
812_migration_f57_tier_seed.jsの番号採番(v1.5 で確定): v1.3 時点では 810 を想定していたが、main 側実装着手時に 810/811 が他マイグレーション案件で先行採用されたため 812 に繰り上げで確定(実装コミット242e0a9)。マイグレーション運用ガイドライン(CLAUDE.md 記載)に従い着手時再確認するフローが機能した実例。今後の同様ケースでも仕様書番号は意図記録として維持し、実装時に着手直前 grep で最終番号を確定する運用とする。健保料率の都道府県別管理: 健保料率は都道府県別(協会けんぽ)だが等級境界は全国一律。
17_mst_soci_tierは「全国一律の等級境界」+「料率列は福井県値」とし、他県対応時にシート分割 or 列追加する設計方針を事前決定しておく必要がある。経営セーフティ共済の 2024/10 改正反映: 解約後 2 年以内の再加入は損金算入不可。MAS-141 で詳細ロジックを扱うが、MAS-057 UI で積立額ドロップダウンを操作する際に警告表示を出すか否か。
BRD 齋藤 Baseline の「実データ検証」セクション配置: 本仕様書では §実データ検証で期待値を記載したが、MAS-056 との重複を避けるため、実装時は
900_test/901_test_runner.jsの MAS-057 テストケース内にのみ配置し、仕様書側には期待値の出典(BRD §8)のみを残すか検討。MAS-232(Vite+React SPA 基盤)未着手時のフォールバック: Phase 3 の
templates/financial_cockpit.htmlが MAS-232 前提だが、MAS-232 が着手されない場合の代替(GASHtmlService.createHtmlOutputFromFile+Chart.js単一ファイル)で段階的に動作させるか。F57_INSIGHT_AI_MODELのデフォルト選定: Phase 3 インサイト生成を Claude Sonnet / Gemini Flash / Gemini Pro Preview のどれをデフォルトにするか。コスト vs 応答品質のトレードオフ。2026-04-24 時点で Gemini 3 Pro Preview が最新で、Deep Think 有効時の応答が MAS-057 の深い税務推論に適する可能性あり。コックピット URL の公開範囲:
appsscript.json既存の"access": "MYSELF"のまま運用する(齋藤氏のみアクセス可)か、"access": "DOMAIN"に拡張して将来のチーム利用を想定するか。1 人社長フェーズでは MYSELF のままで問題ないが、商用化時に再検討。クライアント側ロジック二重実装の SOP 確立(v1.1 Critical 1 反映 → ✅ v2.0 で解決済):
Phase 3 で純粋関数を ES Module に移植すると、GAS 側(→ 採用方式: 注意事項 #14 (b) window 露出方式を採用。400_domain/442_*.js)とクライアント側(tools/webapp-client/src/engines/*.ts)の両方で同一ロジックを保守する必要があるwebapp_client/scripts/sync-engines.mjsで400_domain/{442,443,444,445}_*.jsをwebapp_client/src/engines/にコピー + 末尾にif (typeof window !== 'undefined') window.SocialInsuranceTierEngine = SocialInsuranceTierEngine;を自動付与するビルドステップを設置(PR #379 で実装)。SSoT は400_domain/維持・webapp_client/src/engines/は.gitignore化。GAS 側更新時はnpm run sync:enginesで同期するだけ。TypeScript 複製ゼロを実現。Jest 統合テストは400_domain/を直接 import で同一性検証可能。AI インサイトトリガーモードのデフォルト選定(v1.1 Major 4 反映):
F57_INSIGHT_TRIGGER_MODEのデフォルトをONMOUSEUP_2SEC(自動・低コスト)とするかEXPLICIT_BUTTON(完全手動・ゼロコスト)とするか。初期 UX は自動推奨だが、商用化時のコスト見通しが立つまではEXPLICIT_BUTTONで運用する慎重論もあり。03_sys_paramsで切り替え可能なので実運用で判断可能。事前確定届出給与の届出タイミング制約(v1.2 追加・BRD 年収スコープ転換で新規論点): 本 BRD の賞与配分シナリオ(パターン C/D 等)は事前確定届出給与の届出が前提。届出タイミング(株主総会決議日から 1 ヶ月以内 or 事業年度開始日から 4 ヶ月以内の早い日)を逃すと損金算入不可となり、節税効果が逆転するリスクあり。顧問税理士への事前ヒアリング必須、UI 上でもインサイトと併せて常時警告文を表示する必要がある。届出内容(支給額・支給日)は実行時に「そのまま」支給しないと損金不算入となる点も含めて UX 設計する。
賞与の税務上の扱い(定期同額給与との関係)(v1.2 追加): 本 BRD で扱う役員賞与は「定期同額給与の例外」として事前確定届出給与の枠組みで損金算入される。月中の月額報酬変更(定期同額から外れる支給)は原則として損金不算入となるため、「年収を維持したまま月額を途中で増減させる」配分変更は通常不可。Phase 1/2 の計算エンジンではこの税務制約を「固定的な配分として事前に設計する」前提で実装し、月次配分の動的変更機能は実装しない方針。
22_bud_headcountへの賞与列追加の是非(v1.2 追加・Phase 2 以降の別案件切出推奨): 現行22_bud_headcountは月額報酬(月額給与・報酬)中心の設計で、賞与を明示的に管理する列がない。MAS-057 の配分シナリオを実行する場合、HC マスタにも「年間賞与額」「支給回数」「届出済フラグ」等の列追加が必要になる可能性がある。ただし本変更は DDL 影響が大きく HC マスタ全体への波及があるため、別案件(MAS-058 候補: 役員賞与 HC マスタ拡張)として切り出し、MAS-057 Phase 1/2 は既存22_bud_headcountに触れない方針とする。MAS-057 の計算エンジンは「年収・月額・賞与」を引数として受け取る純粋関数であり、データソースは後付け可能。【v2.1 追加】AI インサイトの最低月額制約反映(Step 6.13 由来): 現状の Step 6.13 は入力フィールドのみ実装で、
buildInsightPrompt_への反映は未着手。v2.2 候補として、AI インサイトの payload にlivelihoodMinimumSalaryを追加し、プロンプト末尾に「最低月額 X 円を下回る役員報酬の提案をしないこと」を明記する設計。F57_INSIGHT_MINIMUM_SALARY_DEFAULT等の03_sys_paramsキーを追加する想定(Step 6 は localStorage ベースのため現状は03_sys_params拡張なし・本対応時のみ追加)。実装着手前に「AI 提案の質低下リスク」(最低月額が高すぎると有効提案ゼロになる)を税理士レビューで確認。【v2.1 追加】住宅ローン減税の精密計算(Step 6.14 由来・別案件として将来起票候補): 現状は年額固定 × 5 年の簡易実装。本来は 残高 × 0.7% で年々減少・13 年期間・住宅種別 (認定長期優良住宅 / ZEH 水準 / 一般住宅 等) 別の上限差・子育て世帯特例 (2024 改正) 等の精密計算が必要。MAS-057 単独で対応するか、住宅ローンシミュレーター案件として独立切出するかは将来判断。注 (2026-04-30): v2.1 当初は「MAS-071 候補?」と仮押さえしていたが、MAS-071 が稼働率連動型役員報酬シミュレーター (
dev_mas-071_compensation_strategy_simulator.md) として正式確定したため、住宅ローン減税精密計算は別 ID で再アサイン (優先度高まり次第起票)。1 人社長の住宅ローン額は個人差が大きいため、簡易実装でも実用上問題ない可能性も高い。【v2.1 追加】老後の備え (個人) の NISA / iDeCo 対応(Step 6.7 由来・MAS-066 配当ミックスとの境界判断): 現状の老後の備え (Step 6.7 個人列) は「個人保険料の払込累計」のみ。NISA (新 NISA 1,800 万枠) や iDeCo (掛金所得控除 + 受取時退職所得控除) は未対応。MAS-066 配当ミックス最適化と機能境界が近接する (個人の蓄積資産配分という観点) ため、MAS-066 実装着手前にスコープ分担を確定させる必要あり。案 A: MAS-057 Step 6.7 に NISA/iDeCo 入力を追加 (1 人社長単独最適化)。案 B: MAS-066 配当 spec に統合 (配当 vs NISA/iDeCo の代替関係を明示)。案 C: 別案件として独立 (個人ライフプラン軸)。
実装プロンプト(Claude Code 用)
本案件は 3 Phase に分割し、各 Phase を独立プロンプトとして使う。着手順序は Phase 1 → Phase 2 → Phase 3。Phase 1 は MAS-056 実装状態に依存せず単独で着手可能だが、Phase 2 以降は MAS-056 Phase 3 実装完了を確認してから着手する。
Phase 1 実装プロンプト(Claude Sonnet 推奨)
## 案件
MAS-057 Phase 1 — 社会保険料壁エンジン + 等級マスタ + 個人所得税 Constants(約 1 ヶ月・MAS-056 実装状態に依存せず単独実装可・v1.1 反映)
## 事前調査(必ず Read する)
1. `000_infra/002_constants.js` — `TAX_RATES.brackets` 構造 / `getParam` シグネチャ / `SHEET_DEFAULTS` 配列型 / `ID_PREFIX_MAP` 既使用番号
2. `000_infra/003_contracts.js` — `Contracts.toDto(headers, row)` / `Contracts.toRows(headers, dtos)` シグネチャ
3. `000_infra/004_utils.js` — `Utils.getSheetByKey(key, fallbackName)` / `Utils.persistLog(level, funcName, message, detail)` / `Utils.parseDateToYm` / `Utils.parseAmt`
4. `200_data/202_repository.js` — `readSheetAsDtos_` / `AccountRepository` / `PartnerRepository` / `HurdleRateRepository` の完全構造(_getSheet / findAll / findAsMap / _cache / resetCache の 5 要素対称性)
5. `100_config/101_sys_config.js` — `setupAllSchemas` の `confSheet.appendRow` パターンと `schemas` オブジェクト追加パターン
6. `900_test/901_test_runner.js` — 既存テストケースの命名規約と実行パターン
7. `800_ops/` ディレクトリ配下のマイグレーションスクリプト構造(809_backup_tool.js が最新)
## 実装対象
1. **`100_config/101_sys_config.js` 編集**:
- `confSheet.appendRow(['MST_SOCI', '', '17_mst_soci_tier', 'マスタ_社会保険標準報酬月額等級表 (F-57 壁エンジン)'])` 追加
- `schemas` オブジェクトに以下 1 エントリ追加(`MST_HURDLE` の直後、`#666666` 色、validation は range 型)
- `MST_SOCI`: headers = ["有効フラグ","等級","標準報酬月額下限","標準報酬月額上限","健保料率","厚年料率","介護保険料率","子ども子育て支援金率","適用開始年月","備考"]
- `MST_SOCI.validations`: `{ "適用開始年月": { type: 'regex', pattern: '^20[2-3]\\d-(0[1-9]|1[0-2])$', helpText: 'YYYY-MM 形式で入力(例: 2026-03)' } }`(v1.7 追加)
2. **`000_infra/002_constants.js` 編集**(v1.1 Critical 2 反映):
- `Constants` オブジェクト内、`TAX_RATES` の直後に `INCOME_TAX_BRACKETS` を追加
- 構造: `{ brackets: [{ upTo, rate, deduction }], residentTaxRate: 0.10, applicableFrom: '2026-01-01' }`
- 2026 年時点の 7 段階累進テーブル(5% / 10% / 20% / 23% / 33% / 40% / 45%)を初期値とする
3. **`200_data/202_repository.js` 編集** — `HurdleRateRepository` の直後に 1 Repository を追加(5 要素対称実装・failure_patterns #25):
- `SocialInsuranceTierRepository`: `findAsMap()` はキー = 等級コード、重複は先着 + WARN ログ、`有効フラグ FALSE` 除外
- **個人所得税用 Repository は新設しない**(v1.1 Critical 2 反映・Constants で代替)
4. **`400_domain/442_social_insurance_tier_engine.js` 新規作成** — `SocialInsuranceTierEngine` 名前空間:
- `findTier(monthlyCompensation, tierMap)`: 線形 or 二分探索で等級を返す(上限超過時は最大等級 + `isOverCap: true` フラグ)
- `calcPremiums(tier, { isOver40, prefectureKey = 'F56_FUKUI' })`: 健保 + 厚年 + 介護(40 歳以上のみ)+ 子ども子育て支援金を算出。料率は `Constants.getParam(prefectureKey + '_HEALTH_RATE', 0.0971)` 等で取得(MAS-056 キーを DRY で参照)
- `calcBreakEvenPoint({ annualRevenue, fixedCost, ... })`: 厚生年金上限突破 BEP を計算
- **純粋関数のみ**(SpreadsheetApp / UrlFetchApp を呼ばない)
5. **`800_ops/812_migration_f57_tier_seed.js` 新規作成** — マイグレーション運用ガイドライン準拠:
- `migrationF57TierSeed()` 関数(冪等性必須: 既存データが 82 行ある場合はスキップ)
- 日本年金機構 2026 年 3 月分〜の料率表(全国一律・健保 50 等級 + 厚年 32 等級)をハードコードで投入
- `000_infra/002_constants.js` `MENU_DEFINITION` の `📋 サイドバー: 🔧 マイグレーション` カテゴリに `{ label: 'F-57 社会保険等級データを投入', funcName: 'migrationF57TierSeed', description: '17_mst_soci_tier シートに 82 行の等級データを投入 (冪等)' }` を追加
6. **`900_test/901_test_runner.js` にテスト追加**:
- 齋藤 Baseline(月 50 万円)→ 等級 + 保険料の手計算値との ±100 円以内一致
- 境界値テスト: 等級下限・上限ジャスト / 上限超過 / 下限未満
- **40 歳境界テスト**(v1.1 Minor 5 反映): `age = 39 / 40 / 41` で介護保険料が `0 / 8100 / 8100`
- エッジケース #1 #2 #3 #4 #11 #12 #16 のカバー
## Phase 1 デプロイ手順
- dev 環境で `setupAllSchemas` → `migrationF57TierSeed` → テストランナーの順で実行
- 問題なければ `npm run push:prod` → prod で同順実行
- コミットメッセージ: `feat(F-57): 社会保険料壁エンジン + 等級マスタ + 所得税ブラケットマスタ (Phase 1)`
## failure_patterns チェック
- #18-#20: 新設ファイル名・sysKey・関数名は事前調査 Read で実在確認したもののみ使用
- #25: 2 Repository の対称性(意図的な `findAsBrackets` 差分はコメントで明示)
- #26: `appsscript.json` を一切編集しない(cloud-platform 済)
Phase 2 実装プロンプト(Claude Opus 4.7 推奨)
## 案件
MAS-057 Phase 2 — 社宅・日当・共済統合 + MAS-056 対話 UI 拡張(約 1 ヶ月・MAS-056 Phase 3 完了後に着手)
## 前提確認
- MAS-056 Phase 3 完了(`calculateOptimalCompensation()` が `400_domain/440_conversational_ui.js` or `400_domain/441_compensation_optimizer.js` に実在)を Read で確認
- MAS-057 Phase 1 が完了しており `SocialInsuranceTierEngine` が動作する
## 実装対象
1. **`100_config/101_sys_config.js` 編集**: `TMPL_PDIEM` スキーマ追加 + `confSheet.appendRow(['TMPL_PDIEM', '', '13_tmpl_per_diem_policy', 'テンプレ_出張日当規程 (F-57)'])`。**`validations` フィールド必須**(v1.3 Minor 反映):
```js
'TMPL_PDIEM': {
headers: ["有効フラグ","規程ID","規程名","出張区分","宿泊有無","日当単価","交通費上限","適用開始年月","備考"],
color: "#666666",
validations: {
"日当単価": { type: 'range', min: 0, max: 50000, helpText: '0〜5 万円の範囲で入力(1 日あたり)' },
"交通費上限": { type: 'range', min: 0, max: 200000, helpText: '0〜20 万円の範囲で入力' },
"宿泊有無": { type: 'regex', pattern: '^(有|無)$', helpText: '「有」または「無」を入力' },
}
}
```
2. **`200_data/202_repository.js`**: `PerDiemPolicyRepository` を `PositionTemplateRepository` と完全対称に追加
3. **`400_domain/443_corporate_housing_optimizer.js` 新設**: `CorporateHousingOptimizer.calcRentAllocation()` を純粋関数で実装。`F57_HOUSING_CALC_METHOD` で `SIMPLE_50` / `FORMAL_FIXED_ASSET` 切替
4. **`400_domain/444_per_diem_policy_engine.js` 新設**: `PerDiemPolicyEngine.calcMonthlyAllowance()` を純粋関数で実装
5. **MAS-056 統合**: `440_conversational_ui.js` の `calculateOptimalCompensation` が `SocialInsuranceTierEngine.calcPremiums` + `CorporateHousingOptimizer.calcRentAllocation` + `PerDiemPolicyEngine.calcMonthlyAllowance` を呼び出すよう改修
Phase 3 実装プロンプト(Claude Opus 4.7 1M context 推奨)
## 案件
MAS-057 Phase 3 — ドロップダウン + サンキー UI + インサイト + 5 カ年推移(約 1 ヶ月・クライアントサイド計算設計・v1.1 Critical 1 / v1.8 ドロップダウン化反映・`ai_agent_tips.md §7` 準拠)
## 前提確認
- MAS-056 Phase 3 完了 + MAS-057 Phase 1/2 完了
- MAS-232(Vite+React SPA 基盤)完了 or MAS-056 が Vite+React で稼働中
- MAS-011 `WhatIfSimulator.run()` が 5 カ年モードで動作
## 設計原則(v1.1 反映・厳守)
- **シミュレーション計算はクライアント側**: GAS `google.script.run` 通信レイテンシ(1〜3 秒)を避けるため、ドロップダウン `onChange` 時の再計算はブラウザ内 JS で実行
- **GAS 側 API は 2 種のみ**: (1) 初期ロード時のマスタ一括配信 (2) AI インサイト生成(重処理)
- **AI インサイトは明示的トリガー**: `F57_INSIGHT_TRIGGER_MODE` に従い `onChange + 2sec` or `EXPLICIT_BUTTON` のみで発火。`onChange` 毎の自動呼び出し禁止
## 実装対象
1. **クライアントサイド計算エンジンの単一ソース共有**(v1.7 更新・TypeScript 複製禁止):
- **GAS 側 `400_domain/442_*.js` / `443_*.js` / `444_*.js` をそのままクライアントでも読み込む**(TypeScript ES Module として複製する方式は v1.3 / v1.7 で撤回済)
- GAS ファイルは `var EngineName = (function(){ ... return {...}; })();` の IIFE + グローバル変数宣言パターンで実装(既に Phase 1 `442_social_insurance_tier_engine.js` はこの形式)
- Vite 側の import ブリッジは **注意事項 #14 の (a) `vite-plugin-commonjs` / (b) `window` 露出 / (c) UMD ラッパー生成** の 3 方式から MAS-232 PoC で採用を決定
- Jest 統合テストでも同一の `.js` ファイルを直接読み込み、GAS 側 `901_test_runner.js` と同じ期待値(MAS-057: F57-01 〜 F57-39)を検証する
- `Constants.INCOME_TAX_BRACKETS` は**バンドル時に定数埋め込みではなく**、`action=F57_BOOTSTRAP` で JSON 配信(v1.3 Major 反映・バンドル埋込は再ビルド必須のため廃止)
2. **`templates/financial_cockpit.html` 新設** or MAS-056 `conversational_ui.html` にタブ追加:
- ドロップダウン 3 本(役員報酬 / 社宅負担率 / 共済積立額)を `<select>` で実装(`ai_agent_tips.md §7` 準拠・離散単位・±ボタン併用可)
- `onChange` → クライアント JS エンジン再計算 → SVG 即時再描画(< 50ms 応答)
- `onChange` から 2 秒間追加変更なし → GAS `runFiveYearForF57()` + AI インサイト API 呼び出し
- サンキーダイアグラム(`F57_SANKEY_LIBRARY` で切替・D3.js / Plotly / Chart.js・離散値の流量可視化用途として維持)
- 5 カ年折れ線 + 積み上げ棒(サーバー計算結果を表示)
3. **`400_domain/440_conversational_ui.js` 拡張**(MAS-056 実装の doGet エントリを流用):
- `action=F57_BOOTSTRAP`: 17_mst_soci_tier 全件 + 13_tmpl_per_diem_policy 全件 + `Constants.INCOME_TAX_BRACKETS` + `Constants.TAX_RATES.brackets` + `F56_FUKUI_*` + `F57_*` を JSON 返却
- `action=F57_INSIGHT`: ドロップダウン現在値 + シナリオを受け取り `callClaudeApiOnVertex_` で 1 インサイト生成。**自然言語プロンプトの組み立ては専用ビルダー関数 `buildInsightPrompt_(currentValues, diff)` に分離**(v1.7 Major 反映・Gemini 指摘)。`currentValues = { annualIncome, monthlySalary, bonusYearly, allocationRatio, cashflowTake, netWorth5y }` と `diff = { vsBaseline, vsPrevious }` を受け取り、「年収 N 万円・月額 X × 12 + 賞与 Y の配分から、賞与を Z 万円増やすと厚年上限突破で社保 W 万円減少・手取り V 万円増」形式のプロンプト文字列を返す純粋関数。テンプレート(配分変更型 / 年収変更型)を 2 種内蔵し、LLM 呼び出しを安定化。
- `action=F57_FIVE_YEAR`: `WhatIfSimulator.run({ mode: 'FIVE_YEAR', ... })` を呼び出し 5 カ年推移を返却
4. **AI インサイト発火ロジック**(v1.1 Major 4 反映):
- `F57_INSIGHT_TRIGGER_MODE === 'ONCHANGE_2SEC'`(v1.8 で `ONMOUSEUP_2SEC` から改名): ドロップダウン `onChange` から 2 秒間追加の選択変更がない場合のみ AI 呼び出し。操作再開時は既存タイマーキャンセル
- `F57_INSIGHT_TRIGGER_MODE === 'EXPLICIT_BUTTON'`: 「💡 インサイトを更新」ボタンクリックのみで AI 呼び出し
- UI に「最終更新: HH:MM」を表示し現在値との差分を可視化
5. **MENU_DEFINITION 更新**: MAS-056 の `🧭 意思決定対話(Web App)` カテゴリに `🎛️ ビジュアルコックピット URL をコピー` を追加
6. **テスト**:
- 齋藤 Baseline 13 パターンスキャン検証(§実データ検証・クライアント側 Jest で実行)
- GAS 側 Phase 1 テスト vs クライアント側 Jest で同一入出力を担保(CI で両方実行)
- **40 歳境界** の介護保険料オン/オフ(v1.1 Minor 5 反映)
推奨実行モデル
Phase 別に推奨モデルを使い分け、トークン消費と応答品質を最適化する。
| Phase | 推奨モデル | 根拠 |
|---|---|---|
| Phase 1(社会保険料壁エンジン + 2 Repository + DDL + マイグレーション + テスト) | Claude Sonnet 4.6 | 中程度の設計判断(Repository 対称実装・DDL スキーマ追加・マイグレーション冪等性)。コアコード参照で大部分が確定、純粋関数設計のため判断分岐が少ない |
| Phase 2(社宅 / 日当 / 共済統合 + MAS-056 非破壊統合) | Claude Opus 4.7 (1M context) | 複数ファイル横断の税制・社保ロジック統合 + MAS-056 既存コードの理解 + MAS-141 共済ロジックとの境界設計が必要。会計ロジック判断を複数含む |
| Phase 3(ドロップダウン + サンキー UI + AI インサイト + MAS-011/MAS-013 連動) | Claude Opus 4.7 (1M context) | Vite+React SPA 基盤 + MAS-011/MAS-013 エンジン + AI 統合 + サンキーライブラリ選定の複合設計。UI/UX 判断 + コスト試算 + エッジケース対応の網羅性が必要 |
| 仕様書レビュー(本仕様書の添削 / 4_review_specs_by_gemini.js) | Gemini 3 Pro Preview + Deep Think | 第三者アーキテクト視点の論理矛盾検出・BRD との整合確認。Deep Think で深い税務推論が可能 |
変更履歴
| 日時 | バージョン | 変更内容 |
|---|---|---|
| 2026-05-02 | v2.5 (F-57 大規模 UI 再構成 — 2026-05-01〜05-02 連続セッション・dev @230 反映) | **2 日間連続の 30+ commits によって F-57 cockpit を「節税最適化ツール → 多年経営ダッシュボード」から 「Solo-CEO 経営の総合 CFO ダッシュボード」に再構成完了。コード側はすでに dev @230 まで反映済 (commits b93f4bc 〜 6ad690b の 30 件)。統合: (1) F-67 多年系パネル統合 (commit 6ad690b): 旧 F-67 ワークスペース → main cockpit (CockpitApp.tsx) に統合・GuardrailPanel / SuggestPanel (hideAi) / AiSuggestPanel (Phase D) の 3 パネル統合・RetirementPanel は削除 (下記参照) / (2) AI 提案 sticky 最上部 + 5 年計画ナビ ミニボタン (commit 32beca1, 5e382e4)・AiSuggestPanel に AI 提案を分離 sticky 化 / (3) 多年 P/L · B/S · CF 表 (SoloFinancialStatementsPanel): P/L 比較パネルと項目構造統一 (commit 625593d) + B/S compaction (純資産 + 現預金 default 表示・残りは開閉式 commit 74c5305・共済積立金は資産扱い・期首 B/S 貸借不一致修正 commit e47a817) + ランウェイ・指標行 (ランウェイ / ランウェイ役員報酬込 / 月次バーン役員報酬込 / 営業利益率 / 労働分配率 / 自己資本比率) + 投資余力セクション末尾統合 / (4) 健全性 6 指標を P/L · ランウェイ指標行に inline 化 (commits 9309db8 / 738fa0e / 0cb3fe3 / ad91b80 / eb33645): 数字下段に 1 字 pill (黒/留/走/緊/営/労 + ✅/❌)・該当行ラベルは太字強調 (solo-fs-health-row) / (5) P/L 比較パネル (ApproachComparisonPanel) に「現状」列追加 (commit fbaaf89): 列構成 = CURRENT / A / B / C / D / AVG / (6) MAS-071 戦略シミュレーター再構成: 前提条件を P/L / B/S / C/F の 3 枠分割 (commit 60fd334) + 制約条件枠新設 (lMin / bufferMonths / targetProfit・commit 6020bb4) + 詳細設定 (折りたたみ) に旧 AssumptionsPanel から移管 (commit 5e43d1c) + 現在月額役員報酬 (currentMonthlySalary) 入力追加 (commit f0a505b) / (7) 入力セクションを 個人/法人 タブ + アプローチ切替に再構成 (commit eb33645): アプローチ切替タブ [現状] [A 生活防衛] [B 内部留保] [C 税務最適] [D 融資対策] [平均] → クリックで MAS-071 推奨年額 → 月額 (5 万円単位) 反映 + 賞与 = 0。削除コンポーネント・機能 9 件と廃止 / 再開判断 (sub 側 draft・要ユーザー承認): (1-1) RetirementPanel (退職プラン・F-67 多年系) → (b) 開発し直す・将来再開 (Solo-CEO 段階では優先度低だが MAS-141 共済 / MAS-072 企業価値 / 出口戦略との連動が将来必要・エンジン側 F67ExitPlan 残存で復元コスト低・MAS-067 v3 候補) / (1-2) RequiredRevenuePanel (MAS-058 健全性診断・941 行削除) → 要相談・現状で「機能としては多年表に内包される形で残存」と仕様明記 (6 制約 → SoloFS inline pill / 投資余力 → SoloFS 末尾セクション) + 将来単独 view 復活余地あり (例: cockpit と別 URL ?view=required-revenue) / (1-3) AssumptionsPanel (前提条件パネル・orphan 削除) → (a) 完全削除 + MAS-071 統合明記 / (1-4) ThreeSectionTable + CumulativeTable + build3SectionData / buildCumulativeData (-262 行) → (a) 完全削除 (多年表で同等情報・redundant) / (1-5a) InsightPanel → (a) 完全削除 (AiSuggestPanel に統一) / (1-5b) SankeyDiagram (流出可視化) → (b) 将来再開・MAS-XXX 切り出し候補・要相談 (経営判断で価値あり) / (1-5c) FiveYearChart (5 年推移) → (b) 将来再開・要相談 (多年表 vs グラフ UX 選好で再開余地) / (1-6) SectionGPanel (5 軸ステージダッシュボード) → (a) 完全削除 (多年表 inline 化で redundant) / (1-7) minimumMonthlySalary フィールド (CockpitInputs / DEFAULT_INPUTS / AssumptionsStore / ScenarioStore / CompensationStrategyPanel) → (a) 完全削除 (lMin と意味重複・dead state) / (1-8) MAS-071 詳細設定からの重複 3 項目 (代表月額単価 / 売上貢献稼働率 / 変動費比率) → (a) 仕様書修正のみ (UI 上で重複していたため統合) / (1-9) MAS-071 詳細設定からの初年度フラグ + 初年度稼働月数 → (b) 将来再開・section 末尾メモ (短縮事業年度シナリオは将来必要・M&A 直前期等)。バグ修正 (確定・コード反映済): (i) 共済掛金の CF 二重計上修正 (commit f0a505b・operatingCF / investingCF から kyosaiAnnual 加減算除去) / (ii) 期首 B/S 貸借不一致修正 (commit e47a817・retainedEarnings = corpCash - founding の整合) / (iii) Y0 月次バーンを y0Months で按分 (commit 9bfb048・短縮事業年度対応)。既知のバグ: 健全性行の数値整列ズレ (低優先度 cosmetic・BUG_tracking.md MAS-304 として登録) — SoloFinancialStatementsPanel 多年表の 税引後利益 / ランウェイ役員報酬込 / 営業利益率 / 労働分配率 の 4 行で「万円」「ヶ月」「%」の右端 x 座標が他行と右にズレる・対策 1-4 試行も依然ズレる・推測根本原因は padding-bottom: 22px !important の td 幅計算影響。配置順序 v2.5 (最新): AiSuggestPanel (sticky 最上部) → MAS-071 戦略シナリオ (前提 3 枠 + 制約条件枠 + 詳細設定 + 個人/法人タブ) → ApproachComparisonPanel (CURRENT 列追加) → SoloFinancialStatementsPanel (多年 P/L · B/S · CF + 健全性 inline pill + 投資余力末尾セクション) → GuardrailPanel + SuggestPanel + 5 年計画ミニナビ。配置原則の継承: cockpit を上から下に「経営判断の起点 (AI 提案) → 戦略シナリオ → 比較 → 多年財務 (健全性 inline) → ガードレール」の流れに整理。「実装が spec を先行 → spec を整合追従」のパターン累計 14 例目。docs-only PR で prod 自動デプロイへの影響なし。最終更新日 2026-05-02。 |
| 2026-05-01 | v2.4 (Step 7 新設・cockpit 拡張パネル群 — PR #459 実装完了反映) | MAS-057 cockpit を「節税最適化ツール → 多年経営ダッシュボード」に進化させる Step 7 を main 側 PR #459 (commit 8f45430) で実装完了 ・spec を v2.4 として整合追従。Step 7 構成: (1) 7-A ApproachComparisonPanel: 4 アプローチ A/B/C/D + AVG の 5 列均等 P/L 並列比較 (既存 computeYearlyBreakdown を 5 回呼出・列幅均等 table-layout: fixed) / (2) 7-B SoloFinancialStatementsPanel: Y0 を左端とした 6 年分財務 3 表 (P/L·B/S·CF・F-67 simulateMultiyearClient 流用で B/S 引継ぎ共有) + 各年アプローチ選択 (A/B/C/D/AVG/現状の 6 dropdown) + Y0 月数入力 (1-12・短縮事業年度対応・按分は Y0 のみ scale) + Y0 当期着地見込み上書きトグル / (3) 7-C getSoloCEOY0Forecast() API 新設 (300_ui/302_spa_bridge.js): 64_pl_ytd_plan 通期列 B から P/L 集約 + 73_bs_plan 最右列から期末 B/S 集約 (73 未生成時は 71_bs にフォールバック)・failure_patterns #29 対策で _scrubInfinityForJSON_ 経由 / (4) 7-D cockpit-main.tsx 副作用 import 拡張: 旧 442/443/444/445/449/454 → 新規 451_multiyear_planner.js 追加 (SoloFS 多年版再利用・failure_patterns #33 対策)。配置順序 (v2.4): GuardrailBanners → MAS-071 戦略シナリオ → Step 7-A 4 アプローチ比較 → Step 7-B 多年 PL/BS/CF → 既存 AssumptionsBar/ScenarioBar/CompensationDropdowns → MAS-058 RequiredRevenuePanel。「実装が spec を先行 → spec を整合追従」のパターン累計 13 例目。docs-only PR で prod 自動デプロイへの影響なし。 |
| 2026-04-30 | v2.3 (Step 6.16 シート保存 + UX 統一 + プルダウン即時反映 — PR #454 実装完了反映) | MAS-057 のプリセット・シナリオを localStorage からシート保存に移行 + UX を F-67 と統一 + プルダウン即時反映を実装 (PR #454・commit 3487562) ・spec を v2.3 として整合追従。移行内容: (1) 38_f57_assumptions / 39_f57_scenarios の 2 タブ追加 + F57AssumptionsRepository / F57ScenarioRepository 新設・F57_AS / F57_SC スキーマ DDL 登録 / (2) Constants.ID_PREFIXES.F57AS / F57SC で 4 桁連番発番 / (3) _f57Crud_ ファクトリで API 8 本 (list/save/load/delete × 2 タブ) を重複排除 / (4) 自動移行: 初回 SPA ロード時に旧 localStorage 内容を 1 回だけシートにアップロード (f57_cockpit_*_migrated_to_sheet_v1 フラグで再実行抑制) / (5) F-67 と同一 UX (myr-scenario-panel 緑色テーマ + インライン名前入力 + 4 ボタン 🔄 再取得 / 💾 上書保存 / ➕ 新規保存 / 🗑️ 削除) / (6) list API を values 込みに変更 → プルダウン即時反映 (sheet roundtrip なし) / (7) F-57 / F-67 両方で 📂 読込 → 🔄 再取得 に役割変更 / (8) AssumptionsBar 読込時は前提条件 16 項目のみ上書き (Variables 維持) / ScenarioBar 読込時は Variables のみ上書き (前提条件維持) の差分適用ロジック / (9) F57-SHEET / AS / SC テスト 12 件全 PASS (testF57ScenarioSheetMigration_ 新設)。型定義: docs/spec/sidebar_api.d.ts に F57RecordMeta (.values? 含む) / F57RecordSavePayload / F57RecordFull。spec 更新内容: (1) Step 6.16 「シート保存 + UX 統一 + プルダウン即時反映」セクション新設 (移行スコープ + データモデル + API 8 個 + UX 統一 + 即時反映 + 適用ロジック + 新規ファイル + テスト 12 件詳細) / (2) 変更履歴 v2.3 entry 追加。当初は localStorage 保存だったが、端末跨ぎ共有とサクサク UX を狙ってシート移行 + prefetch 化した経緯を spec 内に明示。「実装が spec を先行 → spec を整合追従」のパターン累計 9 例目。docs-only PR で prod 自動デプロイへの影響なし。 |
| 2026-04-28 | v2.2 (MAS-058 シナリオ健全性診断パネル統合 — PR #400 実装完了反映) | MAS-058 Step 5 が main 側 PR #400 (commit ff61a29) で実装完了。MAS-057 cockpit にシナリオ健全性診断パネルが「累積純資産 + 平均実効負担率」セクション直下に統合された。Step 6.9 拡張: (1) Variables 自動復元 — 前回選択シナリオ/プリセットを起動時に自動ロード (f57_cockpit_last_selected_scenario_v1 + f57_cockpit_last_selected_assumption_v1 localStorage キーを ScenarioBar.tsx / AssumptionsBar.tsx に追加・「前提 × シナリオ」マトリクス試算の継続性を担保)。(2) Step 6.9-extension 新設: MAS-058 統合の概要記載 — 6 制約 × Y1-Y5 matrix・投資余力テーブル・適用開始年タブ・副機能(逆算 + キャパシティ ギャップ分析)。詳細は MAS-058 spec v2.0 参照。(3) 配置原則の明文化: cockpit を上から下に「現状把握 → 目標逆算」の流れとして構成する設計原則を Step 6.9-extension に記載。今後の MAS-066 / MAS-067 等の cockpit 拡張機能はこの境界線に従って配置を決める運用ルール。docs-only PR で prod 自動デプロイへの影響なし。「実装が spec を先行 → spec を整合追従」のパターン 2 例目 (MAS-057 v2.1 PR #395 + MAS-058 v2.0 PR #400 spec 追従と同じパターン)。 |
| 2026-04-28 | v2.1.1 (法人住民税均等割の常時加算 — PR #397 実装完了反映) | 2026-04-28 ユーザー指摘で発覚した MAS-057 cockpit + MAS-013 投資分析の均等割計上漏れを PR #397 で実装修正完了 (commit 71be933)。本 spec の注意事項 #20 (f) を「✅ 同日 PR #397 で解決済」マークに更新。修正実装の内訳: (1) 300_ui/302_spa_bridge.js の bootstrap に localMinimumAnnual を追加配信 / (2) webapp_client/src/cockpit/calc.ts で corporateTax 累進計算後に Math.round(localMinimumAnnual * monthsActive / 12) を常時加算 (Y1 短縮事業年度は monthsActive で月割按分) / (3) 600_report/610_service_investment_analysis.js の calcEffectiveTaxRate_ で黒字時にも minAnnual を加算 / (4) docs/spec/sidebar_api.d.ts の F57CockpitBootstrap 型に localMinimumAnnual: number 追加。影響: 齋藤 Baseline (税引前 750 万・21.4% ブラケット) で実効税率 21.4% → 22.3% (+0.9pt)・法人税 160 万 → 167 万 / 累積 5 年で +35 万円の精緻化 / 赤字シナリオでも 7 万円の均等割が表示されるように修正 / MAS-013 NPV/IRR は均等割込みでやや厳しめに精緻化。「失敗 → 教訓 → プロセス改善」の閉ループ運用 実例: ユーザー指摘 (2026-04-28 00:00 頃) → sub 側調査 + spec 注意事項追記 PR #396 (00:25 マージ) → main 側へ修正依頼 pbcopy → main 側実装 PR #397 (00:41 マージ) → sub 側 spec 解決済追従 PR (本 v2.1.1) を 当日 1 時間以内 で完走。docs-only PR で prod 自動デプロイへの影響なし。 |
| 2026-04-28 | v2.1 (Step 6 大型拡張実装完了反映・milestone) | MAS-057 Step 6 を main 側 PR #394 で実装完了 (commit 94d9c71・33 コミット・spec 未記載機能を 15 項目以上追加)。spec v1.9 (PR #380) では「Step 6 = 個人/法人/合計の 3 区分テーブル UI」のみが設計されていたが、実装では Step 6.1〜6.15 に細分化して大型機能群に進化。Step 6 セクション全面書換: (1) 6.1 3 区分テーブル基本構造: 法人負担合計の詳細展開を 3 → 4-5 行 (経費・変動費・創業費追加) に拡張・サンキーは <details> で折りたたみ補助化。(2) 6.2 Y1-Y5 単年タブ (新設): 各年単独の収入・負担合計・手取り・実効税率を表示・Y1 は isFirstYear + 月数按分・Y2-Y5 は通年 + 月額年次増加額 offset。(3) 6.3 f57_cockpit_scenarios_v1 / f57_cockpit_assumptions_v1)・旧スキーマ migration (revenueAnnual → revenueMonthly) ・「前提 × シナリオ」マトリクス試算可能。(10) 6.10 前提条件 / 入力 セクション分離 (新設): 黄系背景 (前提 16 項目・AssumptionsPanel.tsx) vs 灰系背景 (Variables 7 項目・CompensationDropdowns.tsx + ScenarioBar.tsx)。(11) 6.11 月単位入力 + 変動費比率 (新設): 月商/月固定費入力・経費比率 (cogsRate) + 変動費比率 (variableCostRate) 二軸化・cogsRate を 2.5% 単位 29 段階に細粒度化。(12)(13) 6.12 月額年次増加額 + 6.13 役員報酬最低月額 (新設・Gemini Deep Think MAS-334 発見の先行実装): default 30 万・AI インサイト制約として活用は v2.2 候補 (人間検討事項 #15)。(14) 6.14 法人期首預金残高 + 住宅ローン減税 (新設・2022 年改正後制度・所得税控除しきれない分を住民税からも控除・上限課税所得 × 5% or 97,500 円)。(15) 6.15 想定貢献月商参考表示 (新設): AssumptionsPanel read-only + CompensationDropdowns の「想定値」ボタン。注意事項 #19 #20 新規追加: #19 = Gemini Deep Think (MAS-334) 発見の MAS-067 機能を MAS-057 Step 6 で先行実装した経緯 (Burnout メーター #4 + 最低月額 #1 + 年次増加額)・MAS-067 実装時に Step 6.6/6.13 入力値を引き継ぐ前提・#20 = 簡易実装の明示が必要な機能 5 件 (住宅ローン減税年額固定 × 5 年・老後備え個人 NISA/iDeCo 未対応・万一給付倍率は払込総額・退職所得控除 5 年/19 年ルール未実装・創業費全額一括損金)。エッジケース #22-26 新規追加: #22 旧シナリオ migration / #23 シナリオロード時の前提条件保護 / #24 想定貢献年商ゼロ時の Burnout 計算スキップ / #25 法人赤字時の実効税率「—」表示 / #26 Y1 月数 0 のクランプ。人間検討事項 #15-17 新規追加: #15 AI インサイト最低月額制約反映 (v2.2 候補) / #16 住宅ローン減税精密計算 (MAS-071 候補?) / #17 老後備え NISA/iDeCo 対応 (MAS-066 境界判断)。03_sys_params キー追加なし: Step 6 は localStorage ベースのため新規キー不要。AI インサイト最低月額制約反映時に F57_INSIGHT_MINIMUM_SALARY_DEFAULT 等を追加する想定 (v2.2 候補)。新規追加ファイル: webapp_client/src/cockpit/{AssumptionsPanel,AssumptionsStore,ScenarioBar,ScenarioStore,ThreeSectionTable}.tsx 5 ファイル (PR #394)。Phase 3 注意事項 #15 (税務否認リスク UI ガードレール) は引き続き有効・Step 6 でも遵守。docs-only PR で prod 自動デプロイへの影響なし。「失敗 → 教訓 → プロセス改善」の閉ループ運用 が「実装が spec を先行 → spec を整合追従」のパターンでも機能することを実証 (v1.9 設計 → v2.1 実装フィードバック反映)。 |
| 2026-04-25 04:00 | v1.7 | §実データ検証「賞与配分による社保総額逆転点」テーブルを main Phase 1.5 実装(calcBonusPremiums・PR #356)と ±1 円一致する実計算値に更新 + Gemini レビュー CONDITIONAL GO 指摘 4 件を全反映。(I) 検証値 4 パターン差し替え(主眼・ユーザー指示)v1.6 で「手計算値と実装に微差がある・詳細は F57-22〜F57-39 テスト参照」と deflect していたが、spec を ground truth として読む読者への誤誘導を避けるため、数値自体を実装整合値に書き換え(ユーザー指示)。ズレの原因は 2 点: (A) 月額側: v1.5 までの spec は月額報酬を raw で料率乗算していたが、実運用では 17_mst_soci_tier の標準報酬月額等級で丸めてから料率適用(例: 月額 40 万 → 健保 27 等級・標準 41 万)。(B) 賞与側: (1) 健保 vs 厚年の上限ロジック誤認 — 健保は「年累計 573 万」・厚年と子ども子育ては「1 回 150 万」の非対称な上限を持つが、v1.5 spec はパターン C で両方とも 1 回 150 万と誤解(実際は健保は全額 240 万対象・厚年のみ 150 万丸め)、(2) 介護保険料 1.62% の誤混入 — 齋藤 40 歳未満 Baseline なのに v1.5 spec のパターン C/D で賞与側試算に介護料率を加算していた(実際はゼロ)。更新後の実計算値: A=1,145,400 / B=1,168,308(+22,908)/ C=1,060,980(-84,420)/ D=1,168,308(+22,908)。定性的結論も更新: v1.5 の「C 最有利 14.5 万・D 11.4 万削減・B はほぼ同額」は誤りで、実際は C のみが唯一の削減(約 8.4 万円)・B/D は Baseline より約 2.3 万円増加(D は 150 万ちょうどで突破せず月額側増の負担のみ)。パターン C の上限突破内訳を計算式レベル(min(2_400_000, 1_500_000) = 1_500_000・料率乗算・端数処理)で明文化。新規サブセクション「上限の種類を混同しないこと」を追加し、厚年 = 1 回上限 / 健保 = 年累計上限 / 介護 = 40 歳以上のみ の非対称性を表で整理。v1.6 の「実装との整合性メモ」は本 v1.7 更新により役目終了のため削除。(II) Gemini レビュー指摘 4 件を全反映(併せて本 v1.7 で対応): 🔴 Critical (単一ソース共有方針の自己矛盾とGAS ESM非互換): v1.3 で「TypeScript 複製禁止」としたが Phase 3 実装プロンプト(line 558 付近)と注意事項 #12 に古い「ES Module として複製」記述が残存 + GAS V8 は export 構文非サポートの技術的問題が未明示。注意事項 #14 を拡張し、GAS-Vite ブリッジ方式 3 択((a) vite-plugin-commonjs / (b) window 露出ラッパー / (c) Rollup UMD 生成)を明記。var EngineName = (function(){ ... return {...}; })(); の IIFE + グローバル変数宣言パターン(Phase 1 442_*.js の既存実装方式)を SSoT として確定。Phase 3 実装プロンプトの矛盾記述も修正済。🟡 Major (所得税端数処理欠落): PersonalTaxEngine の税法上必須の 2 段階端数処理を Phase 1 修正方針に追記: 課税所得 Math.floor(taxableIncome / 1000) * 1000(1000 円未満切捨)+ 最終税額 Math.floor(incomeTax / 100) * 100(100 円未満切捨)。単体テスト「3,300,999 円 → 3,300,000 円」ケース必須。🟡 Major (AI インサイト用プロンプト構築ロジック不在): Phase 3 action=F57_INSIGHT 処理に専用ビルダー buildInsightPrompt_(currentValues, diff) を新設、{ annualIncome, monthlySalary, bonusYearly, allocationRatio, cashflowTake, netWorth5y } + { vsBaseline, vsPrevious } を受け取り配分変更型/年収変更型 2 種テンプレート内蔵の純粋関数として定義。🟢 Minor (DDLバリデーション): Phase 1 MST_SOCI スキーマの「適用開始年月」列に { type: 'regex', pattern: '^20[2-3]\\d-(0[1-9]|1[0-2])$' } 追加。変更規模: MAS-057 spec 602 → 約 655 行、検証値テーブル 4 行 + 定性結論 + 新規サブセクション 2 つ + Gemini 指摘 4 件反映。本件は数値精度整合 + API 仕様明確化で、既存実装(Phase 1 / Phase 1.5)への変更なし(Phase 3 プロンプトとドメインエンジンの Pure 化指針を精緻化)。 |
| 2026-04-25 02:30 | v1.6 | main 側 MAS-057 Phase 1.5 実装(PR #356・commit 5d552b4)を受けて calcBonusPremiums 実装実態を反映。v1.2 で Phase 2 並列追加計画としていた calcBonusPremiums が、BRD v1.2 の年収最適化転換を受けてPhase 2 から Phase 1.5 に前倒し実装完了。(1) Phase 1 修正方針の calcBonusPremiums 記述を実装シグネチャに合わせて更新: options = { isOver40, accumulatedBonusThisFiscalYear, singleBonusCapPension, yearlyBonusCapHealth } の 4 キーのみ(v1.3 で想定した料率直接注入は tierMap 経由の _extractUniformRates_ 抽出に統合、targetYm は実装で省略)。戻り値の命名を isOverPensionCap → isPensionCapped / isOverHealthCap → isHealthYearlyCapped(受動態で状態表現)に修正、newAccumulatedHealthBase / total / pensionBase / healthBase / carePremium を追加(実装実態に合わせる)。(2) Pure Function 性は保持(クライアント側でも tierMap を bootstrap 配信して渡せば等価に機能)。(3) §実データ検証のパターン A/B/C/D 期待値(114.5 / 114.5 / 100.0 / 103.1 万)に 実装との整合性メモを追記: 手計算概算値は「戦略方針の定性確認」に留め、数値精度は 901_test_runner.js の F57-22 〜 F57-39(18 件)を SSoT とする旨を明記。実装テストでの具体値例(240 万賞与 → 厚年 137,250 / 健保 233,040 / 合計 373,740 円)も記録。(4) TODO_future.md MAS-057 行のステータス「Phase 1 完了」→「Phase 1.5 完了」に昇格、概要欄に Phase 1.5 実装内容(18 件テスト・上限突破ロジック)を追記。変更規模: MAS-057 spec 590 → 約 602 行、Phase 計画上の「Phase 2 で calcBonusPremiums」記述を「Phase 1.5 で先行実装済」に付け替え。本件は実装整合のみで設計変更なし。 |
| 2026-04-25 01:00 | v1.5 | main 側 Phase 1 実装(commit 242e0a9)との整合追従。実装着手時に migration 番号が当初想定の 810 から 812 に繰り上げ(810/811 が他マイグレーション案件で先行採用)されたため、仕様書内の 6 箇所のファイル名参照を 810_migration_f57_tier_seed.js → 812_migration_f57_tier_seed.js に一括更新。影響範囲テーブル(§影響範囲)と人間検討事項 #3 の採番根拠記述も現状(812 で確定)に合わせて更新。本件以外の設計変更なし。Phase 1 実装の仕様整合確認: 実装された SocialInsuranceTierEngine は findTier / calcPremiums / calcBreakEvenPoint の 3 API + 別名前空間 PersonalTaxEngine を持ち、仕様書 v1.3 と一致。v1.2 で追加予定とした calcBonusPremiums(賞与側 API)は Phase 1 スコープ外で、Phase 2 以降で並列追加する計画通り(API 拡張は非破壊)。仕様書と実装の API 面での齟齬なし。運用示唆: マイグレーション番号は「仕様書着手時 grep → 実装直前 grep」の 2 段確認が機能した実例として、今後の類似案件のベストプラクティスに追加。変更規模: MAS-057 spec 589 → 590 行(軽微)・6 ファイル名置換 + 3 段落の記述更新のみ。 |
| 2026-04-24 23:30 | v1.4 | BRD 趣旨を「純資産一本最大化」から「フロー × ストックのバランス最適化」に再整理。ユーザー指摘「単年のフロー、累積ストックのバランスを最適化したい」を受け、v1.2-v1.3 で「合算純資産最大化」一本に寄っていた Mission を「単年手取り(フロー)× 累積純資産(ストック)のトレードオフ可視化 + ユーザー選択」に再定義。(a) BRD §1 Mission: 「年収の単純最大化 → 合算純資産最大化」を「年収の単純最大化 → 単年フロー × 累積ストックのバランス最適化」に変更、(b) BRD §2 Core Value: 「額面 → 合算純資産」を「額面 → フロー × ストックのバランス」に変更、単年手取りと5 カ年累積純資産を同時に評価指標として明示、(c) BRD §5.1 出力: 「手残り / 純資産 / 税社保流出」の項目羅列から「フロー(単年手取り)× ストック(合算純資産)の 2 軸評価 + パレート最適解 XY プロット」の構造化出力に拡張、(d) BRD §5.2 5 カ年推移: 純資産のみだったのを「フロー時系列(年次手取り折れ線)+ ストック時系列(累積純資産積み上げ棒)+ 統合ビュー(2 軸グラフ)」に拡張、(e) MAS-057 §概要・§目的: 「純資産最大化」表記を「フロー × ストックのバランス最適化」に改訂。設計への影響: Phase 3 UI にはシナリオを XY 散布図(手取り X 軸 × 純資産 Y 軸)でプロットする新コンポーネントが追加される。ライフステージ別の優先度(生活費重視 / 長期資産形成重視)をユーザーが選べる UX となり、システムは単一最大化アルゴリズムではなく「候補点を提示し選ばせる」パレート・フロンティア型に転換。計算エンジン API は不変(calcPremiums / calcBonusPremiums の戻り値に含まれる情報で両指標を構成可能・追加実装不要)。変更規模: BRD 169 → 約 180 行、MAS-057 spec 588 → 約 600 行(短い差分・趣旨明確化が主)。 |
| 2026-04-24 22:30 | v1.3 | Gemini 3 Pro Preview + Deep Think による v1.2 レビュー(BRD + MAS-057 spec 両方 CONDITIONAL GO)指摘 6 件を全反映。🔴 Critical (MAS-057): ドメインロジックの二重管理(DRY 違反)解消: v1.2 で想定した「GAS → TypeScript 複製 + Vite バンドル」方針を撤回し、GAS 側の 442_*.js / 443_*.js / 444_*.js を依存のない Pure JS(ES Modules / UMD)として書き、Vite から ../../400_domain/ を直接 import する単一ソース共有(SSoT)に変更。これに伴い注意事項 #14 新設(Pure Function 厳格化: Utils / Constants 直接依存も排除し、料率・定数はすべて引数注入)。SocialInsuranceTierEngine の calcPremiums / calcBonusPremiums シグネチャに healthRate / pensionRate / nursingCareRate / childcareLevyRate / targetYm を引数追加。ログ出力は warnings 配列で返し呼び出し元が Utils.persistLog する方式に統一。🟡 Major (BRD): 極端な賞与配分の行為計算否認リスク警告: BRD §5 シナリオ B の「月額 30 万・賞与 240 万」パターンに「税務否認リスク高」警告を追加、§8 末尾に免責事項セクション新設(税理士・社労士の個別助言に代わるものではない旨、賞与比率 40% 以上の極端配分は年金機構調査で否認リスク、届出ずれで全額損金不算入の警告)。🟡 Major (MAS-057): Constants.INCOME_TAX_BRACKETS の引き渡し矛盾解消: Phase 3 プロンプトの「バンドル時に定数埋め込み」を削除、action=F57_BOOTSTRAP で JSON 配信されたものをクライアントで動的に使用する方針に統一(GAS 側定数更新時にクライアント再ビルド不要)。🟢 Minor (BRD): 届出期限アラート UI 方針: §6 UX 戦略に「決算月・株主総会月から届出期限算出」「30 日以上 = 緑 / 7-29 日 = 黄 / 6 日以内 = 赤」の色分け表示方針を追記。🟢 Minor (MAS-057): targetYm 引数追加: findTier / calcPremiums / calcBonusPremiums / calcMonthlyAllowance に targetYm("YYYY-MM" 形式)を追加、マスタの「適用開始年月」と突合して該当期間の料率を動的選択する設計に変更。🟢 Minor (MAS-057): TMPL_PDIEM バリデーション追加: schemas['TMPL_PDIEM'] の定義に 日当単価 / 交通費上限 の range 型 validation と 宿泊有無 の regex 型 validation を追加(0-5 万円 / 0-20 万円 / `(有 |
| 2026-04-27 | v2.0 (Phase 3 実装完了反映・milestone) | MAS-057 Phase 3 (Solo-CEO Visual Financial Cockpit) を Vite+React SPA として実装完了 (main 側 PR #379 / commit c27b0a5)。実装中に v1.8 仕様書から逸脱した箇所を v2.0 として spec 整合させる。(a) Phase 3 完了ステータス反映: 概要テーブル「前提依存」を「✅ 全 Phase 実装完了」に書換 + 「実装ステータス」行を新設し Phase 1/1.5/2/3 全完了を明示。(b) 03_sys_params 表更新: 新規 3 キー追加 (F57_INSIGHT_ENABLED default false / F57_GEMINI_MODEL_OVERRIDE_PRO default 未設定 → コード default gemini-2.5-pro / F57_GEMINI_MODEL_OVERRIDE_FLASH default 未設定 → コード default gemini-2.5-flash) + default 変更 2 件 (F57_INSIGHT_AI_MODEL: CLAUDE_SONNET → GEMINI_PRO / F57_INSIGHT_TRIGGER_MODE: ONCHANGE_2SEC → EXPLICIT_BUTTON)。前者は Vertex AI Anthropic Claude quota が dev で escalation 申請中のため即時動作する Gemini を default 化、後者はコスト防衛・誤クリック防止。(c) Phase 3 実装プロンプト現実反映: AI モデル選択 UI (モデルセレクタ GEMINI_PRO / GEMINI_FLASH / CLAUDE_SONNET / CUSTOM + Deep Think トグル) を InsightPanel に追加。Deep Think は thinking_budget=-1 明示時のみ + max_output_tokens 1024→4096 拡張。_callVertexGeminiForF57Insight_ は global / us-east5 / us-central1 / asia-northeast1 を順次試行する多リージョン fallback を実装。(d) 注意事項 #16-#18 新規追加: #16 V8→Java シリアライズの Infinity / NaN silent null (withFailureHandler 不発・GAS エディタ実行時は気づかない致命的落とし穴・bootstrap で Number.MAX_SAFE_INTEGER scrub の対策) / #17 Vertex AI Gemini 3 系は dev 未有効化 (HTTP 404・Model Garden で個別 Enable 必要) / #18 deployment ID の二重管理リスク (getService().getUrl() の最新 URL vs deploy.sh 固定共有 ID の不一致)。(e) エッジケース #18-#21 新規追加 (注意事項 #16-#17 由来): #18 bootstrap Infinity / NaN / #19 Vertex AI モデル未有効化 / #20 UrlFetchApp 帯域幅クォータ枯渇 / #21 Web App OAuth 未認可。(f) 人間検討事項 #10 解決済マーク: 「クライアント側ロジック二重実装の SOP 確立」を ✅ 解決 (webapp_client/scripts/sync-engines.mjs で window 露出方式 (b) 採用・SSoT は 400_domain/ 維持・webapp_client/src/engines/ は .gitignore 化・TypeScript 複製ゼロ実現)。failure_patterns.md #29 (Infinity/NaN silent null) + #30 (Vertex AI preview モデル個別有効化必須) も併せて新設。実装規模: 主要 4 ドロップダウン (役員報酬月額・賞与年額・社宅・共済) + サンキー (D3) + 5 カ年チャート (Chart.js Bar+Line 混合・MAS-011 WhatIfSimulator サーバー連携) + AI インサイト (Vertex Gemini モデルセレクタ + Deep Think + null 安全フォールバック)。新規ファイル: 800_ops/814_migration_f57_phase3_sys_params.js (F57_* 10 キー seed) / 300_ui/302_spa_bridge.js 拡張 (cockpit view + bootstrap + runFiveYearForF57 + generateF57Insight + buildInsightPrompt_ + copyF57CockpitUrl) / webapp_client/financial_cockpit.html + cockpit-main.tsx + CockpitApp.tsx + cockpit/{calc,CompensationDropdowns,SankeyDiagram,FiveYearChart,InsightPanel,GuardrailBanners,ErrorBoundary}.tsx。F57-INS-01〜10 (buildInsightPrompt_ 純粋性テスト 10 件) を 901_test_runner.js に追加。docs-only PR で prod 自動デプロイへの影響なし。次の改善ステップ候補 (v2.1+): 感度分析テーブル / アクションカード / 4 パターン比較表 (BRD §5 シナリオ A-D 並列) を順次追加。 |
| 2026-04-27 | v1.9 (Phase 3 Step 6 新設・3 区分テーブル UI) | 個人 / 法人 / 合計 の 3 区分テーブル UI を Phase 3 Step 6 として新設。経営者ユーザー指摘「サンキーは直感的だが数字としてわかりづらい・改善するための情報には利用しにくい」を受け、サンキーダイアグラムの補完として主要表示となる 3 区分テーブルを設計。設計原則: (1) 「誰が負担するか」軸でグループ化(個人 / 法人を主軸・MAS-057 BRD のデッドヒート分析と整合)、(2) 2 階層展開構造(デフォルト 5 行サマリー / 展開時 12 行詳細)、(3) 数値精度 1 万円単位 1 桁表示(サンキーで読み取れない 1 万円差を明示)、(4) Step 4 AI インサイトと連動した改善示唆。4 グループ × 3 列構造: 収入 / 👤 個人負担合計(所得税 + 住民税 + 健保本人 + 厚年本人)/ 🏢 法人負担合計(法人社保 + 固定費 + 法人税)/ 🔄 法人→個人移転(役員報酬振替)/ 💰 手取り(フロー)/ 🏦 純資産(ストック・MAS-056 Phase 3 統合後)。ラベル文言の統一規約を確定。サンキー vs 3 区分テーブルの使い分け: サンキーは「概観タブ」として補助的に残し、主要 UI は 3 区分テーブル。Step 5 の位置付けも「概観タブ」に再定義。既存 Step 6 (MENU_DEFINITION への追加) は Step 7 にリネーム。MAS-058 / MAS-061 / MAS-141 との連携も明記(MAS-058 Healthy 年商連動 / MAS-061 Cash ETR 信号機の法人税行併記 / MAS-141 共済積立累積反映)。docs-only 改訂で prod 自動デプロイへの影響なし。今後の方針: 「一つ一つ改善していく」スタイルで、次は感度分析テーブル / アクションカード等を順次追加検討(v2.0 候補)。 |
| 2026-04-27 | v1.8 (スライダー全廃 → ドロップダウン一本化) | ai_agent_tips.md §7(2026-04-25 確定の UX 方針「スライダー禁止・離散単位ドロップダウン優先」)の積み残し追従。MAS-057 Phase 2 完了(PR #360)後に書換タイミングをスキップしていた本仕様書を、MAS-057 / MAS-058 / MAS-059 / BRD 全体で UX 方針を統一する PR に併せて反映。書換 30 箇所: 概要・目的(17, 19, 26, 27 行)・現在のコード表(36, 57 行)・Phase 3 セクション全体(187, 189, 191, 198, 205, 211, 215-219 行)・パラメータ表(235, 238 行)・注意事項(268, 272 行)・エッジケース(287, 290, 296 行)・人間検討事項(435, 448 行)・実装プロンプト(551, 559, 561, 572, 580, 584 行)・推奨実行モデル(603 行)。F57_INCOME_INPUT_MODE の default を SLIDER → DROPDOWN_DISCRETE に変更(SLIDER モードは廃止予定・互換用のみ残置・新規実装非推奨と明記)。F57_INSIGHT_TRIGGER_MODE を ONMOUSEUP_2SEC → ONCHANGE_2SEC にリネーム(ドロップダウン化に伴うイベント名整合)。クライアントサイド計算設計(v1.1 Critical 1)は維持(GAS 通信レイテンシ排除の方針はドロップダウンでも有効・60fps 要件は不要になり < 50ms 応答に緩和)。サンキーダイアグラムは維持(離散値の流量可視化用途・スライダーと別概念・ai_agent_tips.md §7 明記)。推奨ドロップダウン粒度: 年収 50-100 万 / 月額 5 万(標準報酬月額等級境界整合) / 賞与 50 万 / 社宅負担率 10% / 共済月 1 万。±ボタン併用可。v1.0-v1.7 changelog 履歴行は当時の記述(スライダー言及)をそのまま保持(履歴用引用のため)。docs-only 改訂で prod 自動デプロイへの影響なし。 |
| 2026-04-24 21:00 | v1.2 | BRD 本旨を「年収(月額報酬 + 賞与)の最適化」に転換(main ワークスペース MAS-057 Phase 1 実装中の気付きから依頼・sub スペース改訂)。(a) BRD §1-§8 全面改訂: Mission「年収の単純最大化 → 合算純資産最大化」に変更、§3.1 社会保険料の壁に賞与上限ロジック(厚年 1 回 150 万・健保年累計 573 万)追記、§4 報酬設定を「年収を親 / 月額・賞与配分を子」の階層構造に再編、§5 シナリオ A-D を「年収固定配分最適化(A/B/C)」+「年収最適化(D)」の 2 系統に拡張、§6 UX を 2 段スライダー(年収 + 配分)または 10 万単位離散選択のフォールバック併記、§8 齋藤 Baseline を年収 600 万 4 パターン(A: 全額月額 / B: 夏冬 60 万 × 2 / C: 賞与 240 万 × 1 / D: 賞与 150 万 × 2)に更新、§9 用語定義セクション新設(年収/月額報酬/賞与/標準賞与額/賞与累計上限)。(b) MAS-057 spec の該当箇所改訂: 概要・目的を年収スコープに書き換え、Phase 1 修正方針に calcBonusPremiums(bonusAmount, tierMap, options) を並列追加(options = { isOver40, accumulatedBonusThisFiscalYear, singleBonusCapPension = 1_500_000, yearlyBonusCapHealth = 5_730_000, prefectureKey }・千円未満切り捨ての標準賞与額ロジック・戻り値に isOverPensionCap / isOverHealthCap フラグ)、既存 findTier / calcPremiums / calcBreakEvenPoint / PersonalTaxEngine API は変更なし(main 実装との整合維持)。03_sys_params に F57_BONUS_PENSION_CAP_SINGLE / F57_BONUS_HEALTH_CAP_YEARLY / F57_INCOME_INPUT_MODE の 3 キーを追加(計 9 キー)。実データ検証に齋藤 Baseline 年収 600 万 × 配分 4 パターンの社保総額逆転点(A: 114.5 万 / B: 114.5 万 / C: 100.0 万(-14.5 万)/ D: 103.1 万(-11.4 万))を手計算期待値として追加。Phase 3 UI に F57_INCOME_INPUT_MODE による 2 モード切替(SLIDER / DISCRETE_10M)とサンキーダイアグラムの「厚年賞与上限突破部分 = 社保ゼロ流入」色分け表示を明記。人間が検討すべき事項に #12(事前確定届出給与の届出タイミング制約・税理士ヒアリング必須)/ #13(賞与と定期同額給与の税務関係・月中変更不可)/ #14(22_bud_headcount 賞与列追加は別案件 MAS-058 候補として切出推奨)を追加。移行方針: 既存 calcPremiums API シグネチャは変更せず calcBonusPremiums を並列追加する形で後方互換を維持、main 側 Phase 1 実装との衝突リスク無し。変更規模: BRD 120 → 約 190 行、MAS-057 spec 535 → 約 590 行。削除最小・追記中心。 |
| 2026-04-24 19:00 | v1.1 | Gemini 3 Pro Preview + Deep Think レビュー(CONDITIONAL GO)指摘 6 件を全反映。🔴 Critical 1 (GAS 通信レイテンシとスライダー UX のミスマッチ): Phase 3 の「debounce 100ms で google.script.run → サーバー再計算」設計を廃止し、シミュレーション計算をクライアントサイド JS で実行する設計にピボット。GAS 側 API は「マスタ一括配信(?action=bootstrap)」と「AI インサイト生成(?action=insight)」に限定。Phase 1/2 純粋関数を ES Module として tools/webapp-client/src/engines/ に TypeScript 複製し、GAS 側と同一入出力を CI で担保する。🔴 Critical 2 (税率管理の非対称性): 20_mst_income_tax_bracket シート + IncomeTaxBracketRepository の新設を取りやめ、Constants.INCOME_TAX_BRACKETS を 002_constants.js に追加する形に変更。法人税 TAX_RATES.brackets と対称な Constants 一元管理とし、税制改正時の更新箇所を単一ファイルに集約。新規シート 3 → 2、新規 Repository 3 → 2 に縮小。🟡 Major 3 (MAS-056 依存方向反転): MAS-057 Phase 1/2 を MAS-056 実装状態に依存せず独立完成する方針に変更。MAS-056 実装時に MAS-057 エンジンを呼び出す形とする。Phase 1 ゴール文言 + 注意事項 #11 + 人間検討事項 1 を更新。🟡 Major 4 (AI インサイトのクオータ枯渇リスク): F57_INSIGHT_DEBOUNCE_MS: 500 パラメータを廃止し、F57_INSIGHT_TRIGGER_MODE(ONMOUSEUP_2SEC / EXPLICIT_BUTTON)に変更。スライダー操作終了から 2 秒待機 or 明示的ボタンクリックのみで AI 呼び出し。🟢 Minor 5 (40 歳境界テスト追加): エッジケース #16 + §実データ検証 §40 歳境界 + Phase 1 実装プロンプトのテスト要件に age = 39/40/41 で介護保険料が 0 / 8100 / 8100 となる境界テストを追加。🟢 Minor 6 (シート名短縮): 17_mst_social_insurance_tier → 17_mst_soci_tier に短縮(既存 mst_acct / mst_part のパターンに整合)。併せて注意事項 #12 #13 を新設(クライアント側計算設計の堅持 + Constants vs DDL の責務分離方針)、エッジケース #17(クライアント/サーバー計算の数値不整合検知)と人間検討事項 #10 #11 を追加。合格判定: Gemini の CONDITIONAL GO 条件 3 点(Phase 3 スライダー UX 設計変更 + 所得税 Constants 統合 + AI トリガー頻度制御)を全て満たしたため、main 実装着手可能状態に昇格。 |
| 2026-04-24 18:30 | v1.0 | 初版作成。BRD docs/brd_solo_ceo_financial_navigator.md 派生。MAS-056(意思決定対話 UI)の Chat UX を補完する「スライダー + サンキー型ビジュアルコックピット」をアンブレラ仕様として定義。社会保険料壁エンジン(442_social_insurance_tier_engine.js)・社宅按分(443_corporate_housing_optimizer.js)・出張日当(444_per_diem_policy_engine.js)の 3 ドメイン層 + 3 マスタシート(17_mst_soci_tier / 20_mst_income_tax_bracket / 13_tmpl_per_diem_policy)+ 3 Repository を新設。3 Phase 分割実装(Phase 1 単独可・Phase 2/3 は MAS-056 Phase 3 完了後)。齋藤 Baseline(月 50 万・福井県 2026 年料率)の実データ検証を §実データ検証に明記。Gemini 3 Pro Preview + Deep Think + Claude Sonnet 添削の 2 段階生成パイプラインで作成。 |
仕様書作成プロンプト
本仕様書は BRD docs/brd_solo_ceo_financial_navigator.md を入力に、以下 2 段階パイプラインで生成された:
- Gemini 3 Pro Preview + Deep Think(
scripts/1_generate_prompts_gemini.js): BRD + コアコード 4 ファイル(002/003/004/202)+ TODO_future.md を入力に、アーキテクト視点のメタプロンプトを生成 - Claude Sonnet 4.6 添削(
scripts/1_generate_prompts_gemini.js内reviewByClaude): 実行者視点で Phase 1 調査ステップの具体化・架空関数排除・タイムアウト回避原則を反映
添削後のプロンプトは tasks/prompts/task_F-57.md(297 行)として保存され、本仕様書は同プロンプトの Phase 1-3 を実行して作成された。原版プロンプトは tasks/prompts/task_F-57.gemini.md(67 行・Gemini 生出力)。
task_F-57.md(297 行)を展開して表示
本仕様書の作成指示プロンプト全文は tasks/prompts/task_F-57.md を参照。パイプラインの再現性確保のため、仕様書末尾への転載は省略し、Git 履歴上の元ファイルを参照する方針とする(仕様書サイズ肥大化防止)。
関連コマンド:
# 再生成する場合
TASK_IDS=MAS-057 node scripts/1_generate_prompts_gemini.js
# Gemini レビュー実行
SPEC_FILES=docs/dev/dev_mas-057_solo_ceo_cockpit.md node scripts/4_review_specs_by_gemini.js