MAS-141: 節税・共済効果シミュレーター(小規模企業共済 + 経営セーフティ共済)
概要
| 項目 | 内容 |
|---|---|
| 案件 ID | MAS-141 |
| 案件名 | 節税・共済効果シミュレーター(小規模企業共済 + 経営セーフティ共済・D.8 派生) |
| カテゴリ | シミュレーション・節税 |
| 優先度 | P1.5 ★★★(FP&A 価値・MAS-057 cockpit との直接連携・1 人法人の最重要節税手段の定量化) |
| 所要時間 | 約 1.0 ヶ月(週 10h 前提・ドメインエンジン 1 週 + UI 統合 2 週 + テスト・レビュー 1 週) |
| 実装ステータス | 📝 仕様書段階・実装未着手 (2026-05-14 v0.2 改訂時点) |
| 対象ファイル(新規) | 400_domain/450_kyosai_simulator.js(純粋関数・KyosaiSimulator 名前空間・約 250-300 行)/ webapp_client/src/cockpit/KyosaiPanel.tsx(新規・F-57 cockpit に統合・折りたたみ可・約 200 行) |
| 対象ファイル(変更) | webapp_client/src/CockpitApp.tsx(KyosaiPanel 組込)/ webapp_client/src/cockpit/calc.ts(KyosaiSimulator 連携・型定義)/ 300_ui/302_spa_bridge.js(bootstrap に共済パラメータ追加・runKyosaiSimulation API 追加)/ webapp_client/scripts/sync-engines.mjs(450_kyosai_simulator.js を sync 対象に追加) |
| 新規シート | なし(既存 03_sys_params にキー追加のみ) |
新規 03_sys_params キー | KYOSAI_SMALL_MIN_MONTHLY / KYOSAI_SMALL_MAX_MONTHLY / KYOSAI_SAFETY_MIN_MONTHLY / KYOSAI_SAFETY_MAX_MONTHLY / KYOSAI_SAFETY_MAX_CUMULATIVE / KYOSAI_SCAN_STEP / KYOSAI_SAFETY_REJOIN_BLOCK_YEARS の計 7 キー |
| 前提案件 | MAS-057 Phase 1(✅ 完了・PR #354/#356・PersonalTaxEngine 利用)/ MAS-057 Step 6(✅ 完了・PR #394・3 区分テーブル UI 基盤)/ MAS-057 Phase 3(✅ 完了・PR #379・F-57 cockpit SPA 基盤)/ Constants.INCOME_TAX_BRACKETS(既存・MAS-057 Phase 1 で新設) |
| 後続連携 | MAS-061 Cash ETR(getKyosaiOptimization API 経由で合法節税優先順位サジェストに統合)/ MAS-067 5 軸 A5/A6(Accumulation 軸の準備度判定精度向上・任意連携)/ MAS-066 配当ミックス(独立シミュレーターとして並列扱い・v3+ で同時最適化を再評価) |
| 吸収・再定義対象 | なし(MAS-041 繰越欠損金 / MAS-049 賃上げ税制と並列の独立節税領域) |
目的
1 人法人の最重要節税手段である小規模企業共済 + 経営セーフティ共済の 2 制度について、想定当期利益・役員報酬・掛金から法人税 + 個人所得税 + 住民税の軽減額を統合計算し、最適掛金設定をシミュレーションで支援する。
- F-57 cockpit Step 6.5(生命保険料 + 損金算入率)と並列で配置し、節税アクションを一覧化
- F-67 5 軸モデル A5(小規模企業共済)/ A6(経営セーフティ共済)の準備度判定の数値根拠となる
- MAS-061 Cash ETR の合法節税優先順位サジェストに統合可能な公開 API を提供
- 掛金 0 〜 上限のスキャンで「限界節税額」一覧を提示し、ユーザーが手元資金最大化と現預金拘束のトレードオフを即座に判断できる
MAS-041(繰越欠損金)/ MAS-049(賃上げ税制)は法人税額控除、本案件は役員個人の所得控除 + 法人損金算入を統合した複合節税シミュレーションで、より包括的な「税引後キャッシュ最大化」を扱う。
現在のコード
本案件は MAS-057 Phase 1 で確立した PersonalTaxEngine を順呼び出して、共済掛金を所得控除(個人)/ 損金算入(法人)に算入した状態の税額差分を算出するアグリゲータレイヤー。新規ロジックは共済 2 種の制度パラメータ管理 + スキャン + 出口リスク警告のみ。
MAS-057 Phase 1(✅ 完了)の利用関数
| 関数 | 定義ファイル | シグネチャ | MAS-141 での用途 |
|---|---|---|---|
PersonalTaxEngine.calcIncomeTax(taxableIncome) | 400_domain/442_social_insurance_tier_engine.js:280 | (taxableIncome:number) → number | 個人所得税の累進計算(1000 円未満切捨後の 100 円未満切捨は呼出側責任) |
PersonalTaxEngine.calcResidentTax(taxableIncome) | 同:306 | (taxableIncome:number) → number | 住民税 10%(均等割除く) |
PersonalTaxEngine.calcTotalPersonalTax(taxableIncome) | 同:319 | (taxableIncome:number) → {incomeTax,residentTax,total,effectiveRate} | 個人税合計(節税前後の差分計算用) |
Constants.INCOME_TAX_BRACKETS.brackets | 000_infra/002_constants.js:38 | Array<{upTo,rate,deduction}> | 個人所得税ブラケット(5-45%・7 段階) |
Constants.INCOME_TAX_BRACKETS.residentTaxRate | 同:48 | number (0.10) | 住民税標準税率 |
Constants.TAX_RATES.brackets | 同:22 | Array<{upTo,national,local}> | 法人税中小法人軽減税率(〜800 万:21.4% / 800 万超:33.6%) |
Constants.TAX_RATES.localMinimumAnnual | 同:26 | number (70000) | 法人住民税均等割(年額・本案件では参照のみ) |
Utils.getSheetByKey(key, fallbackName) | 000_infra/004_utils.js:302 | (key, fallback) → Sheet|null | 03_sys_params 取得(将来の動的パラメータ化用) |
法定実効税率(既存・本案件で参照)
法人税合算実効税率は約 33.6%(軽減区分は約 21.4%)。本案件は実際の課税所得ベースで Constants.TAX_RATES.brackets を順呼び出して個別計算する(平均実効税率近似ではなく累進ベース正確算出)。
MAS-061 Cash ETR(仕様書完了・本案件と相互参照)
MAS-061 の「合法節税優先順位サジェスト」が本案件の simulateScan 結果を呼び出して優先順位リストに統合。MAS-141 が共済 2 種の効果を spec の責任範囲、MAS-061 が複数節税策の統合スコアリング という役割分担。
F-57 cockpit SPA 基盤(PR #379・PR #394)
webapp_client/scripts/sync-engines.mjs が 400_domain/{442,443,444,445}*.js を webapp_client/src/engines/ にコピー + window 露出する仕組み。本案件で 450_kyosai_simulator.js を sync 対象に追加するだけで MAS-141 ドメインエンジンも同じ SSoT 共有方式が適用される(TypeScript 複製ゼロ)。
webapp_client/src/CockpitApp.tsx の Step 6.5(生命保険料 + 損金算入率)の隣接位置に KyosaiPanel.tsx を配置することで、節税アクション群を集約表示できる(折りたたみ可・default 折りたたみ)。
修正方針
本案件は 5 Step で実装する。Step 1-4 は 400_domain/450_kyosai_simulator.js のドメインエンジン構築、Step 5 は F-57 cockpit KyosaiPanel.tsx の UI 統合。各 Step は独立して push 可能(Phase 分割可)。
Step 1 — 共済 2 種の制度パラメータ集中管理
| 制度 | 掛金範囲 | 上限 | 損金/控除区分 | 解約時税務 |
|---|---|---|---|---|
| 小規模企業共済 | 月 1,000 〜 70,000 円(1,000 円刻み) | 年 84 万 | 個人所得控除(全額・所得税 + 住民税) | 退職所得 or 一時所得(受取時課税) |
| 経営セーフティ共済 | 月 5,000 〜 200,000 円(5,000 円刻み) | 年 240 万 / 積立 800 万 | 法人損金算入(全額・法人税) | 解約手当金が益金算入(出口リスク・退職金との相殺戦略可) |
2024-10 改正の重要ポイント: 経営セーフティ共済を解約後 2 年以内に再加入した場合は損金算入不可(KYOSAI_SAFETY_REJOIN_BLOCK_YEARS = 2)。本案件の UI で警告表示必須。
// 03_sys_params 経由で読込(年次更新時に変更可能・Constants デフォルトはフォールバック)
var KYOSAI_PARAMS = (function () {
return {
smallMinMonthly: Constants.getParam('KYOSAI_SMALL_MIN_MONTHLY', 1000),
smallMaxMonthly: Constants.getParam('KYOSAI_SMALL_MAX_MONTHLY', 70000),
safetyMinMonthly: Constants.getParam('KYOSAI_SAFETY_MIN_MONTHLY', 5000),
safetyMaxMonthly: Constants.getParam('KYOSAI_SAFETY_MAX_MONTHLY', 200000),
safetyMaxCumulative: Constants.getParam('KYOSAI_SAFETY_MAX_CUMULATIVE', 8000000),
scanStep: Constants.getParam('KYOSAI_SCAN_STEP', 5000),
safetyRejoinBlockYears: Constants.getParam('KYOSAI_SAFETY_REJOIN_BLOCK_YEARS', 2),
};
})();
Step 2 — calcKyosaiEffect(input) 純粋関数(指定掛金での税額差分計算)
// 400_domain/450_kyosai_simulator.js (純粋関数 + IIFE 名前空間)
var KyosaiSimulator = (function () {
/**
* 指定掛金における共済加入の節税効果を 1 点計算する。
*
* @param {Object} input
* @param {number} input.corporateProfitBeforeTax 共済掛金算入前の法人税課税所得(円)
* @param {number} input.personalTaxableIncome 役員個人の課税所得(給与所得控除・社保控除・基礎控除後)
* @param {number} input.smallMonthly 小規模企業共済の月額掛金(円)
* @param {number} input.safetyMonthly 経営セーフティ共済の月額掛金(円)
* @param {number} [input.safetyCumulative] 経営セーフティ共済 既積立額(円・default 0)
* @returns {{
* corporateTaxBefore:number, corporateTaxAfter:number, corporateTaxSaving:number,
* personalTaxBefore:number, personalTaxAfter:number, personalTaxSaving:number,
* totalSaving:number, totalContribution:number, netCashOutflow:number,
* effectiveSavingRate:number, warnings:Array<string>
* }}
*/
function calcKyosaiEffect(input) {
var warnings = [];
var smallMonthly = _clampSmall_(input.smallMonthly, warnings);
var safetyMonthly = _clampSafety_(input.safetyMonthly, input.safetyCumulative || 0, warnings);
var smallAnnual = smallMonthly * 12;
var safetyAnnual = safetyMonthly * 12;
var corporateTaxBefore = _calcCorporateTax_(input.corporateProfitBeforeTax);
var corporateTaxAfter = _calcCorporateTax_(Math.max(0, input.corporateProfitBeforeTax - safetyAnnual));
var corporateTaxSaving = corporateTaxBefore - corporateTaxAfter;
var personalTaxBefore = PersonalTaxEngine.calcIncomeTax(input.personalTaxableIncome)
+ PersonalTaxEngine.calcResidentTax(input.personalTaxableIncome);
var personalTaxAfter = PersonalTaxEngine.calcIncomeTax(Math.max(0, input.personalTaxableIncome - smallAnnual))
+ PersonalTaxEngine.calcResidentTax(Math.max(0, input.personalTaxableIncome - smallAnnual));
var personalTaxSaving = personalTaxBefore - personalTaxAfter;
var totalContribution = smallAnnual + safetyAnnual;
var totalSaving = corporateTaxSaving + personalTaxSaving;
var netCashOutflow = totalContribution - totalSaving;
return {
corporateTaxBefore: corporateTaxBefore, corporateTaxAfter: corporateTaxAfter,
corporateTaxSaving: corporateTaxSaving,
personalTaxBefore: personalTaxBefore, personalTaxAfter: personalTaxAfter,
personalTaxSaving: personalTaxSaving,
totalSaving: totalSaving, totalContribution: totalContribution,
netCashOutflow: netCashOutflow,
effectiveSavingRate: totalContribution > 0 ? totalSaving / totalContribution : 0,
warnings: warnings,
};
}
Step 3 — simulateScan(input, options) 純粋関数(掛金 0 〜 上限スキャン)
掛金月額を default 5,000 円刻み(KYOSAI_SCAN_STEP)で 0 〜 上限までスキャンし、各シナリオの節税額・累積掛金・実効節税率を一覧化する。
function simulateScan(input, options) {
var p = KYOSAI_PARAMS;
var opts = options || {};
var step = opts.scanStep || p.scanStep;
// 小規模 0 〜 70000 円 / 5000 = 15 シナリオ + 0
// セーフティ 0 〜 200000 円 / 5000 = 41 シナリオ + 0
// 直積 = 16 × 41 = 656 シナリオ(最悪ケース)
var smallSteps = _generateSteps_(0, p.smallMaxMonthly, step);
var safetySteps = _generateSteps_(0, p.safetyMaxMonthly, step);
var scenarios = [];
for (var i = 0; i < smallSteps.length; i++) {
for (var j = 0; j < safetySteps.length; j++) {
var result = calcKyosaiEffect({
corporateProfitBeforeTax: input.corporateProfitBeforeTax,
personalTaxableIncome: input.personalTaxableIncome,
smallMonthly: smallSteps[i],
safetyMonthly: safetySteps[j],
safetyCumulative: input.safetyCumulative || 0,
});
scenarios.push({
smallMonthly: smallSteps[i],
safetyMonthly: safetySteps[j],
totalContribution: result.totalContribution,
totalSaving: result.totalSaving,
netCashOutflow: result.netCashOutflow,
effectiveSavingRate: result.effectiveSavingRate,
warnings: result.warnings,
});
}
}
var optimal = _findOptimal_(scenarios);
return { scenarios: scenarios, optimal: optimal };
}
Step 4 — 経営セーフティ共済の「出口パズル」マッピング
累積 800 万到達後の解約年・益金算入年 + 退職金との相殺戦略を可視化する補助関数:
function mapExitStrategy(input) {
var p = KYOSAI_PARAMS;
var monthlyContrib = Number(input.safetyMonthly) || 0;
var cumulative = Number(input.safetyCumulative) || 0;
var monthsUntilCap = monthlyContrib > 0
? Math.ceil((p.safetyMaxCumulative - cumulative) / monthlyContrib)
: Infinity;
var yearsUntilCap = monthsUntilCap === Infinity ? null : Math.ceil(monthsUntilCap / 12);
return {
yearsUntilCap: yearsUntilCap,
recommendedExitYear: yearsUntilCap,
rejoinBlockedUntil: p.safetyRejoinBlockYears,
requiresRetirementOffset: true,
};
}
MAS-067 v1.2 Section G-3(退職金準備度)との整合: 退職金支給年 = 解約年に合わせる戦略は MAS-067 で別途扱う。本案件はマッピングのみを担当。
Step 5 — F-57 cockpit KyosaiPanel.tsx の UI 設計
UI 統合方針の最終決定(Phase 1 Step 1-5 検討結果): 案 A (F-57 cockpit 統合) を採用。理由: 既存 SPA 基盤流用・単年判断時に役員報酬 + 配当 + 共済を同時最適化可能・実装コスト最小。
| UI 要素 | 内容 |
|---|---|
| パネルヘッダー | 「💰 共済シミュレーター(小規模 + セーフティ)」折りたたみ可・default 折りたたみ |
| 標準月額入力 | 小規模月額(0-70,000 円・5,000 円刻みドロップダウン)+ セーフティ月額(0-200,000 円・5,000 円刻み)+ 既積立額(円・テキスト入力) |
| 結果サマリ | 法人税節税額 / 個人税節税額 / 合計節税額 / 累積掛金 / 実効節税率(%) / 警告メッセージ |
| スキャンテーブル | 横軸 = 小規模月額(5,000 円刻み)/ 縦軸 = セーフティ月額(5,000 円刻み)/ 各セル = 合計節税額(円)・最適点は太字・ヒートマップ的色分け |
| 出口パズルパネル | 800 万到達予測年 + 解約推奨年 + 退職金との相殺チェックリスト |
| Disclaimer | 「本シミュレーターの出力は税理士・社労士の個別助言に代わるものではない」を末尾固定表示 |
webapp_client/src/cockpit/calc.ts に runKyosai(input, scenarios) 型定義を追加し、KyosaiPanel.tsx から window.KyosaiSimulator を呼び出す(PR #379 の SSoT 共有方式踏襲)。
MAS-061 Cash ETR 連携用 公開 API(Phase 1 Step 1-6 検討結果)
/**
* MAS-061 Cash ETR 統合用の最適化結果取得 API。
* v1.2 改訂時に MAS-061 ダッシュボードから呼び出される。
* @returns {{ optimal:{smallMonthly,safetyMonthly}, scenarios:Array, cashEtrImpact:Object }}
*/
function getKyosaiOptimization(input) {
var scan = simulateScan(input);
return {
optimal: scan.optimal,
scenarios: scan.scenarios,
cashEtrImpact: {
totalSaving: scan.optimal.totalSaving,
effectiveSavingRate: scan.optimal.effectiveSavingRate,
cashLockup: scan.optimal.totalContribution - scan.optimal.totalSaving,
},
};
}
return {
calcKyosaiEffect: calcKyosaiEffect,
simulateScan: simulateScan,
mapExitStrategy: mapExitStrategy,
getKyosaiOptimization: getKyosaiOptimization,
};
})();
影響範囲
| 種別 | ファイル | 影響内容 |
|---|---|---|
| 新規 | 400_domain/450_kyosai_simulator.js | KyosaiSimulator 名前空間・約 250-300 行(純粋関数のみ・IIFE パターン) |
| 新規 | webapp_client/src/cockpit/KyosaiPanel.tsx | F-57 cockpit 統合 UI・約 200 行・折りたたみ可・default 折りたたみ |
| 変更 | webapp_client/src/CockpitApp.tsx | KyosaiPanel 組込(Step 6.5 隣接位置)・差分 約 15 行追加 |
| 変更 | webapp_client/src/cockpit/calc.ts | KyosaiInput / KyosaiResult / KyosaiScenario 型定義・差分 約 30 行追加 |
| 変更 | 300_ui/302_spa_bridge.js | bootstrap に kyosaiParams 追加 + runKyosaiSimulation 公開 API・差分 約 30 行追加 |
| 変更 | webapp_client/scripts/sync-engines.mjs | 450_kyosai_simulator.js を sync 対象に追加・差分 約 5 行追加 |
| 変更 | 000_infra/002_constants.js | (v1.2 で 03_sys_params 移行・v1.0 では Constants 直定数で開始)・差分 約 10 行追加 |
| 変更なし | 200_data/202_repository.js | Repository 層は本案件でタッチしない(純粋計算のみ・シート書込なし) |
| 変更なし | 003_contracts.js | DTO 追加なし(純粋関数の input/output のみ) |
| 変更なし | 400_domain/410_subledger_engine.js | 連携なし(仕訳生成は本案件のスコープ外) |
| 変更なし | appsscript.json | oauthScopes 変更不要(SpreadsheetApp / Constants / Utils のみ参照・failure_patterns #26) |
| 変更なし | 400_domain/400_rpa_common.js 〜 407_rpa_orchestrator.js | RPA 系には影響なし |
実装ボリューム: 新規 2 ファイル(約 500 行)+ 変更 5 ファイル(約 90 行追加)= 合計約 590 行規模。
注意事項
- failure_patterns #18-#20 命名造語禁止:
KyosaiSimulator/calcKyosaiEffect/simulateScan/mapExitStrategy/getKyosaiOptimizationの命名は既存ドメインエンジン(SocialInsuranceTierEngine/RequiredRevenueSolver/DividendMixOptimizer)の動詞 + 目的語パターンに準拠。命名造語・実在しない関数名の引用・推測補完は禁止。 - failure_patterns #25 並列実装対称性: 既存 442-449 ドメインエンジンと同じ IIFE + グローバル変数宣言パターン(
var KyosaiSimulator = (function () { ... })();)に揃える。returnで公開関数を露出する形式も対称的に踏襲。 - failure_patterns #26 oauthScopes 部分追記禁止: 該当なし(本案件は SpreadsheetApp / Constants / Utils のみ参照・
appsscript.json変更不要)。oauthScopes に手を入れる必要が出た場合は、必ず既存のスコープ全てを再記載すること。 - failure_patterns #29 V8→Java Infinity null: 該当なし(本案件の戻り値に Infinity / NaN を含む計算なし・税額・節税額は有限)。ただし
mapExitStrategyのyearsUntilCapがInfinityになるケース(safetyMonthly = 0)は明示的にnullに変換して返す(google.script.run経由のシリアライゼーション失敗回避)。 - failure_patterns #31 採番衝突回避: 本仕様書 v0.1 は
400_domain/451_tax_saving_simulator.jsを採用していたが、451は MAS-067multiyear_planner.jsで確定使用済のため、本 v0.2 で400_domain/450_kyosai_simulator.jsに変更(450 が空き番号・実装着手前にls 400_domain/4*.jsで再確認すること)。 - 2024/10 改正反映(経営セーフティ共済): 解約後 2 年以内再加入は損金算入不可(
KYOSAI_SAFETY_REJOIN_BLOCK_YEARS = 2)。短期解約スキーム封じ・出口パズル UI で警告表示必須。mapExitStrategy.rejoinBlockedUntilで API 化。 - 税率パラメータの年次更新ポリシー:
Constants.INCOME_TAX_BRACKETS/Constants.TAX_RATES.bracketsは毎年 3 月税制改正後に直接編集する。本案件は両者を順呼び出すのみで税率変更は引き継がれる。共済の制度パラメータも将来改正に備えて03_sys_params経由(v1.2 移行)にしておく。 - Disclaimer 必須: 「本シミュレーターの出力は税理士・社労士の個別助言に代わるものではない」を
KyosaiPanel.tsx末尾固定表示。MAS-057 の Disclaimer・MAS-067 のガードレールと整合させる。 - 税務否認リスクへの UI ガードレール(F-57 注意事項 #15 / MAS-067 ガードレール 10 件と整合): 過大掛金(経営セーフティ共済 800 万到達後の継続加入)の警告を表示。同族会社の行為計算否認(配偶者役員追加掛金などの組合せ)リスクは UI でグレーアウト表示。
- 法人 vs 個人税率最適化の境界: 利益が小さいケース(法人税 0 / 個人課税所得 0)では節税効果ゼロ → UI で「効果なし」明示。0 を「節税できた」と誤認識させない。
- 同族会社の行為計算否認: 役員報酬激減 + 配偶者役員追加掛金などの組合せでの否認リスク(MAS-066 配当ミックスと整合)。本案件単独では検知できないため、人間検討事項に記載。
- 小規模企業共済の前納掛金特例: 12 ヶ月以内の前納分は支払日基準で控除可能(簡素化のため v1 は月額 × 12 で計算・前納は人間検討事項)。
- 個人所得税の 1000 円未満切捨・100 円未満切捨:
PersonalTaxEngine.calcIncomeTaxの戻り値は既にMath.floor適用済み。本案件側で追加の切捨を行わない(二重切捨防止)。 - MCP
add_rows禁止: 本案件は計算のみで Sheet 書込なし。将来の Action 化(共済支払の仕訳生成)でもadd_rowsではなくupdate_cellsで末尾行に書込(CLAUDE.md 規約)。
エッジケース
計算式・スキャンロジックの異常系を以下にテーブル化。KyosaiPanel.tsx の表示と KyosaiSimulator.calcKyosaiEffect / simulateScan の内部処理の双方で検知・保守的フォールバックする。
| # | 条件 | 検知方法 | 期待される挙動 | ログ出力 |
|---|---|---|---|---|
| 1 | 当期利益 0 / マイナス(赤字法人) | input.corporateProfitBeforeTax <= 0 | 法人税効果 0 表示・小規模共済の個人効果のみ計算・「赤字のため法人税節税効果なし」警告 | Utils.persistLog('INFO', 'KyosaiSimulator', '法人税効果ゼロ', '赤字法人') |
| 2 | 役員報酬 0(個人課税所得 0) | input.personalTaxableIncome <= 0 | 個人効果 0 表示・「効果なし」警告・セーフティ共済の法人効果のみ計算 | Utils.persistLog('INFO', ..., '個人税効果ゼロ', '課税所得 0') |
| 3 | 掛金月額 0(両方) | smallMonthly === 0 && safetyMonthly === 0 | 全シナリオ 0 円・スキャンテーブル空表示・「掛金未設定」案内 | — |
| 4 | 掛金が制度上限超過 | smallMonthly > 70000 || safetyMonthly > 200000 | 上限にクランプ + 警告メッセージ(warnings 配列に追加)・UI で赤字注記 | Utils.persistLog('WARN', ..., '上限超過クランプ', JSON.stringify({smallMonthly, safetyMonthly})) |
| 5 | 経営セーフティ共済 累積 800 万到達 | cumulativeSafety >= 8000000 | 「累積上限到達・追加掛金不可」表示 + mapExitStrategy で解約年タイミング推奨 | Utils.persistLog('INFO', ..., '累積上限到達', 'safetyCumulative=' + cumulativeSafety) |
| 6 | 2 年以内再加入禁止期間に該当 | lastWithdrawalYear + 2 > currentYear (input オプションで渡された場合) | 「再加入不可期間」エラー表示・損金算入を 0 として計算 | Utils.persistLog('WARN', ..., '再加入禁止期間', '解約後年数=' + diff) |
| 7 | 個人所得税ブラケット境界跨ぎ | taxableIncome が境界(195 万 / 330 万 / 695 万 / 900 万 / 1800 万 / 4000 万)を跨ぐ | 階段状の節税効果テーブル表示・累進構造を可視化(スキャンでは自然に表現される) | — |
| 8 | 法人税中小法人軽減税率境界(年所得 800 万) | corporateProfitBeforeTax > 8000000 の前後で境界 | 限界節税率が 21.4% → 33.6% に切替・スキャンで境界点を明示表示 | — |
| 9 | スキャン刻み幅 0 以下入力 | options.scanStep <= 0 | KYOSAI_SCAN_STEP(default 5000)にフォールバック・「無効な刻み幅・default 適用」警告 | Utils.persistLog('WARN', ..., 'scanStep 無効', String(opts.scanStep)) |
| 10 | bootstrap で共済パラメータ未配信 | boot.kyosaiParams === undefined | Constants 既定値で動作 + UI に「03_sys_params 未投入・Constants デフォルト使用中」注記 | console.warn('kyosaiParams not bootstrapped, using Constants defaults') |
| 11 | 計算結果の最適点が複数(同点最適) | maxSavingScenarios.length > 1 | 累積掛金が小さい方を優先表示(流動性確保)・タイブレーカーは smallMonthly 昇順 | — |
| 12 | 個人住民税の均等割(年 5,000 円固定額) | 累進外の固定額 | 共済加入で課税所得 0 でも 5,000 円は残る旨を KyosaiPanel.tsx に注記 | — |
| 13 | input.safetyCumulative が負値 | cumulativeSafety < 0 | 0 にクランプ + 警告 | Utils.persistLog('WARN', ..., 'safetyCumulative 負値', String(cumulativeSafety)) |
| 14 | NaN / undefined 入力 | Number.isFinite(input.X) === false | 各フィールド 0 にフォールバック・警告 | Utils.persistLog('WARN', ..., 'NaN 入力', JSON.stringify(input)) |
| 15 | スキャン直積爆発(>1000 シナリオ) | smallSteps.length * safetySteps.length > 1000 | 自動的に刻み幅を倍化(最大 10,000 円刻み)・「スキャン規模制限」案内 | Utils.persistLog('WARN', ..., 'スキャン規模制限発動', ...) |
実データ検証
実装前に以下を MCP / Sheet 直接参照で確認:
03_sys_paramsの既存キー命名規則: 既存キーがMAS057_*/F67_*/F66_*のような Prefix を持つかを確認し、本案件のキー命名(KYOSAI_*)が一貫しているか検証する。結論: 既存仕様 (v0.1) ではS69_*Prefix を採用していた。v0.2 (本版) では「制度名 Prefix」(KYOSAI_*) を採用し将来の MAS-061/067 連携での可読性を優先(v0.2 改訂ポイント・人間検討事項 #1)。Constants.INCOME_TAX_BRACKETSの最新性: 2026 年税制改正反映済みか確認(applicableFrom: '2026-01-01'が002_constants.js:49にある)。Constants.TAX_RATES.bracketsの中小法人軽減税率: 〜800 万: 21.4% / 800 万超: 33.6% が002_constants.js:22-25で最新か確認。- 既存
442_social_insurance_tier_engine.jsのPersonalTaxEngine公開状況:calcIncomeTax/calcResidentTax/calcTotalPersonalTaxの 3 関数がreturnブロックで露出されているかを確認(442_social_insurance_tier_engine.js:332-336)。 webapp_client/scripts/sync-engines.mjsの sync 対象リスト: 442/443/444/445 が現状の sync 対象であることを確認し、450 を追加する箇所を特定する。webapp_client/src/CockpitApp.tsxの Step 6.5 位置: 生命保険料 + 損金算入率セクションの配置位置を確認し、KyosaiPanelを隣接挿入する位置(行番号)を特定。- F-57 SPA の
bootstrap構造:300_ui/302_spa_bridge.jsで他のドメインエンジン(DividendMixOptimizer 等)のパラメータがどのように配信されているかを確認し、kyosaiParamsを同じパターンで追加する。
関連ドキュメント
| ドキュメント | 関連箇所 |
|---|---|
docs/brd_solo_ceo_financial_navigator.md §7 | 主要パラメータ・共済の節税効果定義 |
docs/dev/dev_mas-057_solo_ceo_cockpit.md | F-57 cockpit SPA 基盤・Step 6.5 生命保険料セクションと並列配置 |
docs/dev/dev_mas-067_multiyear_planning_workspace.md | 5 軸 A5/A6 連携・450 番採番衝突回避の根拠 |
docs/dev/dev_mas-061_cash_etr_tracking.md | Cash ETR 統合・getKyosaiOptimization 公開 API |
docs/dev/dev_mas-066_dividend_mix_optimizer.md | 配当ミックスとの役割分担(独立シミュレーター) |
docs/dev/dev_mas-049_wage_increase_tax_credit_simulator.md | 賃上げ税制(並列の節税案件・補完関係) |
docs/_internal/failure_patterns.md | #18-#20(命名造語)・#25(並列実装対称性)・#26(oauthScopes)・#29(V8 Infinity)・#31(採番衝突) |
docs/_internal/dev_spec_prompt_template.md v1.10 | セクション構成・実装プロンプトフォーマット |
docs/prd.md Human-in-the-Loop | 税理士レビュー前提・Disclaimer の根拠 |
CLAUDE.md | コーディング規約・テスト手順・GAS 固有制約 |
| 中小企業基盤整備機構 公式制度説明(2026 年時点) | 制度パラメータの一次ソース(URL は人間検討事項 #11 で参照) |
人間が検討すべき事項
03_sys_paramsキー Prefix の最終決定: 本 v0.2 でKYOSAI_*を採用したが、既存案件はMAS057_*/F67_*/F66_*の MAS ID Prefix が主流。MAS141_*への揃え替えを検討する余地あり(v1 ではKYOSAI_*で進行)。- UI 統合方針の最終確定(案 A F-57 統合 / 案 B 独立 cockpit / 案 C F-67 統合): 本 spec は案 A 採用。実装着手時に MAS-057 cockpit のサイズ膨張(コンポーネント数 8 → 9)を許容できるか再検証。
- スキャン刻み幅のデフォルト値: 5,000 円 / 10,000 円 / 自動最適化(動的調整)の三択。v1 は 5,000 円 default だが、UI 表示でスキャンテーブルが大きすぎる場合は 10,000 円に変更する余地あり。
- 経営セーフティ共済の出口パズルマッピング UI: Y1-Y5 の解約年フラグ表示の粒度(年単位 / 半期単位)。退職金支給予定年と連動表示する場合は MAS-067 Section G-3 完了待ち。
- 退職金との連携(5 年/19 年ルール): 退職所得控除の計算と本案件の解約手当金益金算入の相殺戦略は MAS-067 Phase C 完了待ち。v1 では
requiresRetirementOffset: trueのフラグ提供までを担当。 - MAS-066 配当ミックス + MAS-141 共済の同時最適化: v3+ で再評価。v1 は独立シミュレーター扱いで、両者の総合最適は人間判断に委ねる。
- 税理士向け Disclaimer 文言の確定: 「税理士・社労士の個別助言に代わるものではない」の表現。MAS-057 / MAS-067 と統一する。
- 共済以外の節税手段の v2+ 拡張余地: 中退共(中小企業退職金共済)/ iDeCo / NISA / 役員保険(生命保険) / 倒産防止共済(本案件で対応済)以外の節税手段を v2+ で同パネルに追加するかを検討。
- 月額入力 vs 年額入力の UI 選択: default は月額(F-57 と整合)。年額入力モードのトグルを追加するかは UX 評価次第。
- 加入済み共済情報の入力フィールド(現在の累積掛金・加入年・解約予定年)の UI 設計: v1 は累積掛金のみテキスト入力。加入年・解約予定年は v2+ で
mapExitStrategy精緻化と同時に追加。 - F-67 v1.5 Phase A5/A6 との数値整合: 現状 F-67 は簡易判定(営業利益閾値)で、本案件で精緻化される。F-67 改訂タイミング(v1.5 計画)で本案件の API 統合を検討。
- 同族会社の行為計算否認のチェックロジック: 配偶者役員追加掛金などの組合せでの否認リスクを UI でどう警告するか。MAS-066 と統合した「役員報酬構成 + 共済掛金構成」の総合チェックエンジン化は v2+。
- 小規模企業共済の前納掛金特例: 12 ヶ月以内の前納分を支払日基準で控除可能とする UI を追加するかは v1 では非対応。前納割引(月額 1,000 円あたり 0.9 円 = 0.09%)の計算は v2+。
実装プロンプト(Claude Code 用)
あなたはGAS会計システム(bizlp-gas-accounting)のシニア開発者です。
案件 MAS-141「節税・共済効果シミュレーター(小規模企業共済 + 経営セーフティ共済)」を実装してください。
## 実行前タスク(8 件)
1. `docs/dev/dev_mas-141_kyosai_tax_saving_simulator.md` を Read し、本仕様書全体を把握する
2. `400_domain/442_social_insurance_tier_engine.js` の `PersonalTaxEngine` を Read (L271-L337) し、`calcIncomeTax(taxableIncome)` / `calcResidentTax(taxableIncome)` の正確なシグネチャを確認する
3. `000_infra/002_constants.js` の `INCOME_TAX_BRACKETS` (L38-L50) と `TAX_RATES` (L21-L30) を Read し、参照する累進ブラケット構造を確認する
4. `400_domain/449_dividend_mix_optimizer.js` (`DividendMixOptimizer`) を Read (冒頭 100 行) し、既存 IIFE + 純粋関数のドメインエンジンパターンを把握する
5. `ls 400_domain/4*.js` で **450 が空き番号**であることを再確認する (failure_patterns #31)
6. `webapp_client/scripts/sync-engines.mjs` を Read し、現状の sync 対象 (442/443/444/445) と追加箇所を特定する
7. `webapp_client/src/CockpitApp.tsx` を Read し、Step 6.5 (生命保険料 + 損金算入率) セクションの位置を確認する
8. `300_ui/302_spa_bridge.js` の bootstrap 構造を Read し、他のドメインエンジンパラメータの配信パターンを確認する
## 修正対象ファイル
- `400_domain/450_kyosai_simulator.js` (新規作成)
- `webapp_client/src/cockpit/KyosaiPanel.tsx` (新規作成)
- `webapp_client/src/CockpitApp.tsx` (KyosaiPanel 組込)
- `webapp_client/src/cockpit/calc.ts` (型定義追加)
- `300_ui/302_spa_bridge.js` (bootstrap + 公開 API 追加)
- `webapp_client/scripts/sync-engines.mjs` (sync 対象に 450 追加)
- `000_infra/002_constants.js` (定数追加・v1 は Constants 直定数)
## 実装内容(6 件・Step 1-5 + 統合)
1. `400_domain/450_kyosai_simulator.js` 新規作成: `KyosaiSimulator` IIFE 名前空間。公開関数 `calcKyosaiEffect(input)` / `simulateScan(input, options)` / `mapExitStrategy(input)` / `getKyosaiOptimization(input)` の 4 つ。内部ヘルパは `_clampSmall_` / `_clampSafety_` / `_calcCorporateTax_` / `_generateSteps_` / `_findOptimal_` / `_loadParams_` 等。
2. `KYOSAI_PARAMS` 定数: `03_sys_params` から `KYOSAI_SMALL_MIN_MONTHLY` / `KYOSAI_SMALL_MAX_MONTHLY` / `KYOSAI_SAFETY_MIN_MONTHLY` / `KYOSAI_SAFETY_MAX_MONTHLY` / `KYOSAI_SAFETY_MAX_CUMULATIVE` / `KYOSAI_SCAN_STEP` / `KYOSAI_SAFETY_REJOIN_BLOCK_YEARS` を取得。`Constants.getParam` 経由(既存パターン)。v1 では `002_constants.js` に default を集中定義。
3. `webapp_client/src/cockpit/KyosaiPanel.tsx` 新規作成: 折りたたみ可・default 折りたたみ・標準月額入力 (ドロップダウン) + 結果サマリ + スキャンテーブル + 出口パズルパネル + Disclaimer の 5 ブロック構成。`window.KyosaiSimulator` を呼び出す方式(PR #379 の SSoT 共有方式踏襲)。
4. `webapp_client/src/CockpitApp.tsx` 変更: Step 6.5 (生命保険料) の隣接位置に `<KyosaiPanel />` を挿入。インポート文の追加と `useScenarioStore` からの `kyosaiInput` 取得を追加。
5. `webapp_client/src/cockpit/calc.ts` 変更: `KyosaiInput` / `KyosaiResult` / `KyosaiScenario` 型定義を追加。`runKyosai(input)` 関数を `window.KyosaiSimulator.simulateScan` のラッパとして実装。
6. `300_ui/302_spa_bridge.js` 変更: `_buildBootstrap_` に `kyosaiParams: _loadKyosaiParams_()` を追加。公開関数 `runKyosaiSimulation(inputJson)` を `KyosaiSimulator.getKyosaiOptimization` のラッパとして追加。
7. `webapp_client/scripts/sync-engines.mjs` 変更: sync 対象配列に `'450_kyosai_simulator.js'` を追加。
## 制約
- **既存の `442_social_insurance_tier_engine.js` / `449_dividend_mix_optimizer.js` には触らない**(PersonalTaxEngine の再利用のみ)
- `webapp_client/src/cockpit/` 配下の既存コンポーネント (AssumptionsPanel / CompensationDropdowns / ThreeSectionTable 等) には変更を加えない (KyosaiPanel は新規追加のみ)
- `appsscript.json` の `oauthScopes` には触らない (failure_patterns #26)
- `MCP add_rows` 禁止 (CLAUDE.md 規約・本案件は計算のみなので Sheet 書込なし)
- `PropertiesService.getScriptProperties()` の直呼びは禁止 (必ず `Constants.getParam` 経由)
- 列番号ハードコード禁止 (本案件は Sheet 読込なしのため該当しないが、v2+ で 03_sys_params 読込追加時に注意)
## エッジケース
仕様書「## エッジケース」セクションの 15 件すべてを実装。特に:
- 当期利益 0 / マイナス: 法人税効果 0 + 個人効果のみ計算
- 役員報酬 0: 個人効果 0 + 「効果なし」警告
- 累積 800 万到達: 「追加掛金不可」表示 + `mapExitStrategy` で解約年タイミング推奨
- 制度上限超過: 上限にクランプ + 警告
- スキャン刻み幅 0 以下: default 5000 にフォールバック + 警告
- スキャン直積爆発: 自動倍化 (最大 10000 円刻み)
- 個人住民税均等割 (年 5000 円固定額): KyosaiPanel に注記表示
## 実データ検証
1. `Constants.INCOME_TAX_BRACKETS.applicableFrom` が `2026-01-01` であることを確認
2. `Constants.TAX_RATES.brackets[0].upTo === 8000000` (中小法人軽減税率の境界) を確認
3. `PersonalTaxEngine.calcIncomeTax(0)` が 0 を返すこと(負値・ゼロ入力のフォールバック確認)
4. `PersonalTaxEngine.calcIncomeTax(6950000)` が約 974,500 円を返すこと (20% ブラケット境界の検算)
5. `webapp_client/scripts/sync-engines.mjs` の sync 対象に 450 を追加後、`npm run build` で `webapp_client/src/engines/450_kyosai_simulator.js` がコピーされることを確認
## 動作確認(npm run push:dev 後・5 件)
1. `npm run push:dev` がエラーなく完了
2. GAS エディタで `KyosaiSimulator.calcKyosaiEffect({corporateProfitBeforeTax: 7500000, personalTaxableIncome: 4100000, smallMonthly: 70000, safetyMonthly: 200000})` を実行し、`totalSaving` が約 95 万円であることを確認
3. `npm run deploy:dev` 後、F-57 cockpit `/exec` URL を開いて KyosaiPanel が折りたたみ状態で表示されることを確認
4. KyosaiPanel を展開し、月額を入力するとスキャンテーブルが動的更新されることを確認
5. 出口パズルパネルで「800 万到達予測年」が累積掛金 + 月額から正しく計算されることを確認
## 単体テスト(GAS 上の 901_test_runner.js に追加)
- `test_KyosaiSimulator_calcKyosaiEffect_baseline_()` - 齋藤 Baseline 拡張版(法人 P/L 利益 750 万 / 役員報酬 600 万 / 小規模 7 万 + セーフティ 20 万 = 期待節税額 約 95 万円/年)
- `test_KyosaiSimulator_calcKyosaiEffect_large_corp_()` - 黒字大型法人(利益 5,000 万・法人税 33.6% ブラケット)
- `test_KyosaiSimulator_calcKyosaiEffect_loss_()` - 赤字法人(利益 0・個人効果のみ)
- `test_KyosaiSimulator_simulateScan_optimal_()` - スキャン最適点が累積掛金最小(流動性確保)であることを確認
- `test_KyosaiSimulator_mapExitStrategy_()` - 800 万到達年・rejoinBlockedUntil = 2 の確認
- `test_KyosaiSimulator_clamp_()` - 上限超過・負値入力のクランプ動作確認
## failure_patterns チェック(3 件)
1. **#18-#20 命名造語禁止**: `KyosaiSimulator` 内の全関数名が `dev_mas-141_kyosai_tax_saving_simulator.md` の Step 2-4 で定義された関数名と完全一致していること
2. **#25 並列実装対称性**: `var KyosaiSimulator = (function () { ... })();` パターンが既存 442/449 と同形式であること(IIFE + return 露出)
3. **#31 採番衝突**: 実装着手前に `ls 400_domain/4*.js` で 450 が空きであることを再確認
### 拡張思考の使用状況
| フェーズ | 拡張思考(あり/なし) | 備考 |
|---|---|---|
| ドメインエンジン Step 1-3 実装 | あり | 累進税率の境界値処理・クランプロジックの正確性 |
| ドメインエンジン Step 4 mapExitStrategy | あり | Infinity → null 変換の境界 (failure_patterns #29) |
| KyosaiPanel.tsx UI 実装 | なし | F-57 既存基盤の素直な拡張 |
| sync-engines.mjs 変更 | なし | 1 行追加のみ |
| 単体テスト追加 | なし | 期待値テーブル既定義・パターン化済 |
推奨実行モデル
| 工程 | 推奨モデル | 根拠 |
|---|---|---|
ドメインエンジン実装(calcKyosaiEffect / simulateScan / mapExitStrategy) | Claude Sonnet 4.6 | 純粋関数・数式直訳・エッジケース処理。累進税率の境界処理のみ要拡張思考。 |
UI 統合(KyosaiPanel.tsx + cockpit 連携) | Claude Sonnet 4.6 | F-57 既存基盤の素直な拡張・パターン適用が中心。 |
| 単体テスト | Claude Haiku 4.5 | 期待値テーブル既定義・パターン化済(仕様書「実データ検証」3 ケース)。 |
| 仕様書レビュー(本仕様書の妥当性検証) | Gemini 3 Pro Preview + Deep Think | 第三者視点・税務ロジックの妥当性・2024/10 改正反映の正確性検証。 |
| MAS-061 Cash ETR 統合(v1.2 改訂時) | Claude Opus 4.7 (1M context) | 複数ファイル横断・統合スコアリングロジック設計・複合節税策の優先順位判断。 |
変更履歴
| 日時 | バージョン | 変更内容 |
|---|---|---|
| 2026-04-30 | v0.1 | 初版作成(TaxSavingSimulator 名前空間・400_domain/451_tax_saving_simulator.js 採番)。docs/dev/dev_mas-141_tax_saving_simulator.md に保存。 |
| 2026-05-14 | v0.2 | 採番衝突修正 + 名前空間統一: 451 は MAS-067 multiyear_planner.js で確定使用済のため 450 に変更。名前空間を KyosaiSimulator に統一(既存 442-449 ドメインエンジンの「目的特化型・短縮型」命名規則と整合)。ファイル名も dev_mas-141_kyosai_tax_saving_simulator.md に変更(旧 tax_saving → kyosai_tax_saving・制度名を明示)。failure_patterns #31 採番衝突回避ルール追記。エッジケース 12 件 → 15 件に拡張(NaN 入力・スキャン直積爆発・safetyCumulative 負値の 3 件追加)。MAS-061 Cash ETR 連携用公開 API getKyosaiOptimization を Step 5 直下に明示。task_MAS-141.md (Phase 1-3 自律実行プロンプト) を入力として Claude Opus 4.7 で起草。 |
仕様書作成プロンプト
本仕様書は tasks/prompts/task_MAS-141.md の <instruction> タグ内プロンプトを Claude Opus 4.7 に投入して自律生成した。再現性・監査性確保のため投入プロンプト全文を以下に記録する。
展開して表示(task_MAS-141.md 全文・約 290 行)
<instruction>
【タイムアウト回避・実行原則(v1.7・必ず遵守すること)】
1. **拡張思考の使い分け**:
- Phase 1(設計フェーズ): 拡張思考をフル活用する。ファイルパス・関数名・シート名・行番号・エッジケース一覧・Step 分割粒度を **ここで完全に確定** させる。Read によるコード裏取りを妥協しない(failure_patterns #18-#20 の直接対策)。
- Phase 2(清書フェーズ): 各 Step 内では拡張思考を **最小限** に抑える。Phase 1 で確定済みの内容をそのまま書き出すことに徹する。出力途中で「本当にこれで良かったか」と再考しない。
2. **テキストでの状況報告の禁止**:
- 「〜を作成します」「一気に進めます」等の **text のみ返して tool_use を発行せずに終了する turn** を作らない。
- 説明は 1 文以内。直ちに tool を呼ぶ。
3. **4-5 分割の Write/Edit 実行**:
- 仕様書 1 本を 1 回の Write で書き切らず、以下の Step に分けて実行する:
- Step 2-1: 骨格 Write(~20 行)
- Step 2-2: 概要〜注意事項 Edit/Bash(~300 行)
- Step 2-3a: エッジケース〜人間が検討すべき事項 Edit/Bash(~200 行)
- Step 2-3b: 実装プロンプト〜変更履歴 Edit/Bash(~250 行)
- Step 2-4: `<details>` にプロンプト全文記録 Edit/Bash(最重量・必ず独立 Step)
- 1 回の Write/Edit は約 300 行以内を目安にする。
4. **各 Step で何を書くかを具体指示**:
- 設計判断を Phase 2 実行時に持ち込まないよう、Phase 1 で関数名・シート名・行番号・定数名を完全確定させる。
======================================================================
あなたは GAS 会計システム(bizlp-gas-accounting)のシニア開発者兼仕様書ライターです。
案件 **MAS-141「節税・共済効果シミュレーター(小規模企業共済 + 経営セーフティ共済)」** の開発仕様書を作成してください。
---
## Phase 1: 実行前タスク(7 ステップ・テキスト報告禁止・即座にツール実行)
### Step 1-1: 案件定義の読み込み
`docs/_internal/todo_master_tables.md` を Read し、MAS-141 の行から「案件名」「概要」「期待される効果」「人間が検討すべき事項」を取得する。
特に以下を正確に把握すること:
- **対象 2 制度の制度詳細**:
- **小規模企業共済**: 月額 1,000-70,000 円・**年 84 万円**・全額**所得控除** (個人側)・運営=中小企業基盤整備機構
- **経営セーフティ共済 (中小企業倒産防止共済)**: 月額 5,000-200,000 円・**年 240 万円**・全額**損金算入** (法人側)・**積立上限 800 万円**・運営=同
- **2024/10 改正 (重要)**: 経営セーフティ共済の解約後**2 年以内再加入は損金算入不可**(短期解約スキーム封じ・F-67 v1.2 注意事項にも反映済)
- **節税効果の構造**:
- 個人側 (小規模): 掛金が個人の所得控除 → 個人累進税率分の所得税 + 住民税が減
- 法人側 (セーフティ): 掛金が法人の損金 → 法人税実効税率 (21.4-33.6%) 分が減 + 解約時に**全額益金**として戻る (税の繰延効果)
- **「限界節税額」スキャン要件**: 掛金 0 〜 上限のスキャンで月額別の節税額・累積掛金・実効節税率を一覧表示
### Step 1-2: F-57 ドメインエンジン継承可否の調査
`400_domain/442_social_insurance_tier_engine.js` を Read し、`PersonalTaxEngine` 名前空間 (別名前空間として定義済) の `calcIncomeTax(taxableIncome)` / `calcResidentTax(taxableIncome)` のシグネチャと使用例を確認する。
`000_infra/002_constants.js` の以下を確認:
- `Constants.INCOME_TAX_BRACKETS` (個人所得税累進・MAS-057 Phase 1 で新設)
- `Constants.TAX_RATES.brackets` (法人税中小法人軽減税率・行 22-25)
- `Constants.TAX_RATES.localMinimumAnnual` (法人住民税均等割 70,000 円/年・行 26)
新規ドメインエンジン `400_domain/450_kyosai_simulator.js` の名前空間命名は **`KyosaiSimulator`** で確定 (`SocialInsuranceTierEngine` / `RequiredRevenueSolver` / `DividendMixOptimizer` の並列構造を踏襲・命名造語禁止 failure_patterns #18-20)。
### Step 1-3: 採番衝突チェック (Phase 1-A-pre / failure_patterns #31)
`grep -nE '^\| MAS-' docs/_internal/todo_master_tables.md` で **MAS-141 が既使用** であることを確認 (本案件本人)。
`ls 400_domain/4*.js` で 442/443/444/445/446/447/448/449/451 の使用状況を grep し、**450 が空き番号**であることを確認した上で `400_domain/450_kyosai_simulator.js` を新設する。**ID 衝突発見時は次空き番号 (453, 454...) で起案** (failure_patterns #31 適用)。
### Step 1-4: 共済 2 制度の閾値・制度詳細の精査
実装に必要な制度パラメータを以下にハードコードし、`03_sys_params` に外出しする (年次税制改正追従):
| パラメータ | 値 | キー候補 |
|---|---|---|
| 小規模企業共済 月額下限 | 1,000 円 | `KYOSAI_SMALL_MIN_MONTHLY` |
| 小規模企業共済 月額上限 | 70,000 円 | `KYOSAI_SMALL_MAX_MONTHLY` |
| 経営セーフティ共済 月額下限 | 5,000 円 | `KYOSAI_SAFETY_MIN_MONTHLY` |
| 経営セーフティ共済 月額上限 | 200,000 円 | `KYOSAI_SAFETY_MAX_MONTHLY` |
| 経営セーフティ共済 累積上限 | 8,000,000 円 | `KYOSAI_SAFETY_MAX_CUMULATIVE` |
| スキャン刻み幅 | 5,000 円 (default) | `KYOSAI_SCAN_STEP` |
| 経営セーフティ共済 解約後再加入禁止期間 | 2 年 (2024/10 改正) | `KYOSAI_SAFETY_REJOIN_BLOCK_YEARS` |
**注意**: 値は中小企業基盤整備機構の公式制度説明 (2026 年時点) ベース。年次改正で変動する可能性があるため、コア定数 (`002_constants.js`) ではなく `03_sys_params` で永続化する。
### Step 1-5: UI 統合方針の決定 (F-57 cockpit / F-67 マルチイヤー / 独立 cockpit)
3 つの統合パターンを比較検討し、**spec の Step 5 で 1 つに確定** する:
| 案 | 内容 | メリット | デメリット |
|---|---|---|---|
| **A: F-57 cockpit に統合** | 既存 cockpit に「💰 共済シミュレーター」セクション追加 | 既存 SPA 基盤流用・単年判断時に役員報酬 + 配当 + 共済を同時最適化可能 | cockpit が肥大化・コンポーネント数 8 → 9 に |
| **B: 独立 cockpit (`?view=kyosai_spa`)** | 新規 cockpit ファイル群 (multiyear_cockpit.html パターン) | F-57 への影響なし・MAS-141 単独デプロイ可 | SPA 構築コスト高 (3-4 件目の cockpit) |
| **C: F-67 マルチイヤーに統合** | A5/A6 (5 軸モデルの 💰 Accumulation 軸) の準備度判定を本格的なシミュレーションに格上げ | F-67 既存基盤流用・年次粒度で掛金スキャン可能 | F-67 Phase B/C 完了待ち |
**推奨**: 案 A (F-57 cockpit 統合) を default 採用。**実装着手は MAS-057 Step 6 完了済 + F-67 Phase B-4 完了済**を前提とし、F-57 SPA 基盤を流用する形で実装規模を抑える。
### Step 1-6: MAS-061 Cash ETR との連携設計
`docs/dev/dev_mas-061_cash_etr_tracking.md` (もし存在すれば Read・なければ TODO 行から要件確認) で「合法節税の優先順位サジェスト」リストを確認し、本案件 (MAS-141) の `KyosaiSimulator.simulateScan()` 結果を Cash ETR ダッシュボードへ統合する API 設計を決定:
- `getKyosaiOptimization(input)` 公開 API を `KyosaiSimulator` に追加
- 戻り値: `{ optimal: { smallMonthly, safetyMonthly }, scenarios: [...], cashEtrImpact }`
- MAS-061 Cash ETR の v1.2 改訂時に統合 (本 spec では「外部公開 API として提供」までを記述)
### Step 1-7: 配当ミックス (MAS-066) との関係整理
MAS-066 配当ミックス最適化と MAS-141 共済シミュレーターは**役割分担**:
- MAS-066: A 役員報酬 + B 賞与 + C 配当 の 3 軸 (給与系 + 配当系・**個人税最適化の中核**)
- MAS-141: 小規模共済 + セーフティ共済 (節税専用ストック・**個人所得控除 + 法人損金の中核**)
両者を**同時最適化**するのは v3+ で再評価。v1 は独立シミュレーターとして扱う。
---
## Phase 2: 仕様書の分割作成 (5 Step・テキスト報告禁止)
### Step 2-1: 骨格 Write (~20 行)
ファイル名: `docs/dev/dev_mas-141_kyosai_tax_saving_simulator.md`
dev_spec_prompt_template.md v1.10 の 14 セクション見出しを骨格として Write:
```markdown
# MAS-141: 節税・共済効果シミュレーター (小規模企業共済 + 経営セーフティ共済)
## 概要
## 目的
## 現在のコード
## 修正方針
## 影響範囲
## 注意事項
## エッジケース
## 実データ検証
## 関連ドキュメント
## 人間が検討すべき事項
## 実装プロンプト(Claude Code 用)
## 推奨実行モデル
## 変更履歴
## 仕様書作成プロンプト
Step 2-2: 概要〜注意事項 (~300 行・Edit で章ごとに追記)
概要セクション
| 項目 | 内容 |
|---|---|
| 案件 ID | MAS-141 |
| カテゴリ | シミュレーション |
| 優先度 | P1.5 ★★★ (FP&A 価値・F-57 連携) |
| 所要時間 | 約 1.0 ヶ月 (週 10h 前提) |
| 対象ファイル (新規) | 400_domain/450_kyosai_simulator.js (純粋関数・約 250-300 行) / webapp_client/src/cockpit/KyosaiPanel.tsx (新規・F-57 cockpit に統合) |
| 対象ファイル (変更) | webapp_client/src/CockpitApp.tsx (KyosaiPanel 組込) / webapp_client/src/cockpit/calc.ts (KyosaiSimulator 連携) / 300_ui/302_spa_bridge.js (bootstrap に共済パラメータ追加) / webapp_client/scripts/sync-engines.mjs (450 を sync 対象追加) |
新規 03_sys_params キー | KYOSAI_SMALL_MIN_MONTHLY / KYOSAI_SMALL_MAX_MONTHLY / KYOSAI_SAFETY_MIN_MONTHLY / KYOSAI_SAFETY_MAX_MONTHLY / KYOSAI_SAFETY_MAX_CUMULATIVE / KYOSAI_SCAN_STEP / KYOSAI_SAFETY_REJOIN_BLOCK_YEARS (計 7 キー) |
| 前提案件 | MAS-057 Phase 1 (PersonalTaxEngine 完了済 ✅) / MAS-057 Step 6 (3 区分テーブル UI 完了済 ✅) |
| 後続連携 | MAS-061 Cash ETR (getKyosaiOptimization API 経由) / MAS-067 5 軸 A5/A6 (Accumulation 軸の準備度判定精度向上・任意連携) |
目的セクション
1 人法人の最重要節税手段である小規模企業共済 + 経営セーフティ共済の 2 制度について、想定当期利益・役員報酬・掛金から法人税 + 個人所得税 + 住民税の軽減額を統合計算し、最適掛金設定をシミュレーションで支援する。
- F-57 cockpit Step 6.5 (生命保険料 + 損金算入率) と並列で配置し、節税アクションを一覧化
- F-67 5 軸モデル A5 (小規模企業共済) / A6 (経営セーフティ共済) の準備度判定の数値根拠となる
- MAS-061 Cash ETR の合法節税優先順位サジェストに統合可能な公開 API を提供
現在のコードセクション
| 関数 | 定義ファイル | シグネチャ | MAS-141 での用途 |
|---|---|---|---|
PersonalTaxEngine.calcIncomeTax(taxableIncome) | 400_domain/442_social_insurance_tier_engine.js:280 | (taxableIncome) → number | 個人所得税の累進計算 (1000 円未満切捨 + 100 円未満切捨) |
PersonalTaxEngine.calcResidentTax(taxableIncome) | 同:306 | (taxableIncome) → number | 住民税 10% |
Constants.INCOME_TAX_BRACKETS.brackets | 000_infra/002_constants.js | [{ upTo, rate, deduction }] | 個人所得税ブラケット |
Constants.TAX_RATES.brackets | 同:22 | [{ upTo, national, local }] | 法人税中小法人軽減税率 |
Utils.getSheetByKey(key, fallbackName) | 000_infra/004_utils.js:302 | (key, fallback) → Sheet|null | 03_sys_params 取得 (将来用) |
修正方針セクション (Step 1-5・各サブセクション)
- Step 1:
Constantsへの定数追加 (config 化)・v1.2 で03_sys_params移行 - Step 2:
KyosaiSimulator.calcKyosaiEffect(input)純粋関数 (個人 + 法人の節税効果を 1 点計算) - Step 3:
KyosaiSimulator.simulateScan(input)純粋関数 (掛金 0 〜 上限スキャン・5,000 円刻み・最大 (84+240)/5 = 64 シナリオ) - Step 4: 経営セーフティ共済の 「出口パズル」マッピング (累積 800 万到達後の解約年・益金算入年 + 退職金との相殺戦略・MAS-067 v1.2 Section G-3 と整合)
- Step 5: F-57 cockpit
KyosaiPanel.tsxの UI 設計 (折りたたみ可・標準月額入力 + スキャンテーブル表示)
影響範囲セクション (テーブル形式・新規 / 変更 / 変更なし の 3 分類で整理)
注意事項セクション (failure_patterns 番号付きで 12-14 件)
主要項目:
- #18-#20 命名造語禁止:
KyosaiSimulator/calcKyosaiEffect/simulateScanの命名根拠 (動詞 + 目的語・実在エンジンの命名規則踏襲) - #25 並列実装対称性: 既存 442-449 ドメインエンジンと同じ IIFE + グローバル変数宣言パターン
- #26 oauthScopes 部分追記禁止: 該当なし (本案件は SpreadsheetApp / Constants のみ・appsscript.json 変更不要)
- #29 V8→Java Infinity null: 該当なし (本案件の戻り値に Infinity を含む計算なし・税額は有限)
- 2024/10 改正反映 (経営セーフティ共済): 解約後 2 年以内再加入は損金算入不可・短期解約スキーム封じ・出口パズル UI で警告表示
- 税率パラメータの年次更新ポリシー:
Constants.INCOME_TAX_BRACKETS/TAX_RATES.bracketsの 3 月税制改正追従と本案件の整合性 - Disclaimer 必須: 「本シミュレータの出力は税理士・社労士の個別助言に代わるものではない」
- 税務否認リスクへの UI ガードレール (F-57 注意事項 #15 / F-67 ガードレール 10 件と整合): 過大掛金 (経営セーフティ共済 800 万到達後の継続加入) の警告
- 法人 vs 個人税率最適化の境界: 利益が小さいケース (法人税 0 / 個人課税所得 0) では節税効果ゼロ → UI で「効果なし」明示
- 同族会社の行為計算否認: 役員報酬激減 + 配偶者役員追加掛金などの組合せでの否認リスク (MAS-066 と整合)
Step 2-3a: エッジケース〜人間検討事項 (~200 行)
エッジケース (10-12 件・テーブル化)
| # | 条件 | 検知方法 | 期待される挙動 | ログ出力 |
|---|---|---|---|---|
| 1 | 当期利益 0 / マイナス (赤字) | corporateProfitBeforeTax <= 0 | 法人税効果 0 表示・小規模共済の個人効果のみ計算 | Utils.persistLog('INFO', ...) |
| 2 | 役員報酬 0 (個人課税所得 0) | personalTaxableIncome === 0 | 個人効果 0 表示・「効果なし」警告 | 同上 |
| 3 | 掛金月額 0 (両方) | smallMonthly === 0 && safetyMonthly === 0 | 全シナリオ 0 円・スキャンテーブル空表示 | — |
| 4 | 掛金が制度上限超過 | smallMonthly > 70000 || safetyMonthly > 200000 | 上限にクランプ + 警告表示 | WARN |
| 5 | 経営セーフティ共済 累積 800 万到達 | cumulativeSafety >= 8000000 | 「累積上限到達・追加掛金不可」表示 + 解約年タイミング推奨 | INFO |
| 6 | 2 年以内再加入禁止期間に該当 | lastWithdrawalYear + 2 > currentYear | 「再加入不可期間」エラー表示 | WARN |
| 7 | 個人所得税ブラケット境界跨ぎ | taxableIncome が ブラケット境界 (195万 / 330万 / 695万 / 900万 / 1800万 / 4000万) を跨ぐ | 階段状の節税効果テーブル表示・累進構造を可視化 | — |
| 8 | 法人税中小法人軽減税率境界 (年所得 800 万) | corporateProfitBeforeTax > 8000000 | 限界節税率が 21.4% → 33.6% に切替 | — |
| 9 | スキャン刻み幅 0 入力 | scanStep <= 0 | 5,000 円 default フォールバック | WARN |
| 10 | bootstrap で共済パラメータ未配信 | boot.kyosaiParams === undefined | 既定値 (Constants) で動作 + UI 注記 | WARN |
| 11 | 計算結果の最適点が複数 | maxSavingScenarios.length > 1 | 累積掛金が小さい方を優先表示 (流動性確保) | — |
| 12 | 個人住民税の均等割 (5,000 円) | 累進外の固定額 | 共済加入で課税所得 0 でも 5,000 円は残る旨を注記 | — |
実データ検証 (3-4 ケース)
- 齋藤 Baseline 拡張版: 法人 P/L 利益 750 万 / 役員報酬 600 万 / 個人課税所得 410 万 / 小規模 7 万 + セーフティ 20 万 = 月 27 万掛金 → 期待節税額 (個人 25.4 万 + 法人 69.4 万 = 約 95 万円/年)
- 黒字大型法人: 利益 5,000 万 (法人税 33.6% ブラケット) / 役員報酬 2,000 万 / 月最大 27 万掛金 → 期待節税額 (個人 80 万超 + 法人 108 万 = 約 188 万円/年)
- 赤字法人: 利益 0 / 役員報酬 600 万 → 個人効果のみ 25.4 万 (法人効果 0)
人間検討事項 (10-12 件)
- UI 統合方針 (案 A F-57 統合 / 案 B 独立 / 案 C F-67 統合) の最終確定
- スキャン刻み幅 (5,000 / 10,000 / 自動最適化) のデフォルト値
- 経営セーフティ共済の出口パズルマッピング UI (Y1-Y5 の解約年フラグ表示)
- 退職金との連携 (5 年/19 年ルール・MAS-067 Phase C 完了待ち)
- MAS-066 配当ミックス + MAS-141 共済の同時最適化 (v3+ で再評価)
- 税理士向け Disclaimer 文言の確定
- 共済以外の節税手段 (中退共・iDeCo・NISA) の v2+ 拡張余地
- 月額入力 vs 年額入力の UI 選択 (default は月額・F-57 と整合)
- 加入済み共済情報の入力フィールド (現在の累積掛金・加入年) の UI 設計
- F-67 v1.5 Phase A5/A6 との数値整合 (現状 F-67 は簡易判定で、本案件で精緻化される) の合流タイミング
Step 2-3b: 実装プロンプト〜変更履歴 (~250 行)
関連ドキュメント (10-15 件)
- BRD
docs/brd_solo_ceo_financial_navigator.md§7 (主要パラメータ・共済) - MAS-057 spec (
PersonalTaxEngine利用) - MAS-067 spec (5 軸 A5/A6 連携)
- MAS-061 spec (Cash ETR 連携・存在確認)
- MAS-066 spec (配当ミックスとの関係整理)
- failure_patterns.md
- dev_spec_prompt_template.md v1.10
- PRD プロダクトポリシー
- CLAUDE.md
- 中小企業基盤整備機構 公式制度説明 (URL は spec 本文には含めない・人間検討事項で参照)
実装プロンプト (Claude Opus 4.7 推奨)
事前調査 8 件 + 実装対象 6 件 + 動作確認 5 件 + failure_patterns チェック 3 件 を含む完全な実装プロンプトを記述。
推奨実行モデル
| Phase | 推奨モデル | 根拠 |
|---|---|---|
| ドメインエンジン実装 (calcKyosaiEffect / simulateScan) | Claude Sonnet 4.6 | 純粋関数・数式直訳・エッジケース処理 |
| UI 統合 (KyosaiPanel.tsx + cockpit 連携) | Claude Sonnet 4.6 | F-57 既存基盤の拡張・パターン適用 |
| 単体テスト | Claude Haiku 4.5 | 期待値テーブル既定義・パターン化 |
| 仕様書レビュー | Gemini 3 Pro Preview + Deep Think | 第三者視点・税務ロジックの妥当性検証 |
変更履歴 (v0.1 初版)
| 日時 | バージョン | 変更内容 |
|---|---|---|
| 2026-04-30 | v0.1 (仕様書完了・本 PR で起草) | 初版作成。task_MAS-141.md (本ファイル) + task_MAS-141.gemini.md (Gemini Deep Think 比較資料) を統合 input として Claude Opus 4.7 (1M context) で本体起草。... |
Step 2-4: <details> にプロンプト全文記録 (~50 行)
末尾の <details> ブロックに本 task_MAS-141.md の全文を <summary>仕様書作成プロンプト全文</summary> で記録。
Phase 3: _config.json への追記と構文チェック
docs/_config.json の nav 配列の §E.5 FP&A・レポーティング セクション末尾に以下を追加:
{ "file": "dev/dev_mas-141_kyosai_tax_saving_simulator.md", "title": "E.5.46 MAS-141 節税・共済効果シミュレーター" }
(番号は最新の §E.5 末尾を確認して連番を採用・MAS-067 が E.5.45 の場合は E.5.46 を採用)
JSON 構文チェック:
node -e "JSON.parse(require('fs').readFileSync('docs/_config.json', 'utf-8')); console.log('OK')"
【対象案件】
ID: MAS-141 / 案件名: 節税・共済効果シミュレーター(D.8 派生) / 概要: D.8 §2.f-6 抽出案件。400_domain/ に KyosaiSimulator namespace 新規ファイル追加。小規模企業共済(掛金上限月 7 万円・年 84 万円・全額所得控除)と経営セーフティ共済(月 20 万円・年 240 万円・全額損金算入・積立上限 800 万円)を対象に、想定当期利益・役員報酬・掛金から法人税・所得税の軽減額を計算。掛金 0 〜上限のスキャンで「限界節税額」を一覧提示。
</details>