概要

項目内容
案件IDMAS-035
カテゴリR&D
PhaseP3
優先度
所要時間4-6時間
対象ファイル000_infra/003_contracts.js(DTO 追記)
000_infra/002_constants.jsID_PREFIX_MAP / SHEET_DEFAULTS 追記)
200_data/202_repository.jsIntellectualPropertyRepository / IpCostRepository 新設)
100_config/101_sys_config.jsDDL スキーマ 2 件追記 + システムキー登録)
400_domain/408_rpa_ip_forecast.js(新規ファイル:費用予測 RPA
400_domain/409_rpa_ip_alert.js(新規ファイル:期限アラート)
前提案件なし(既存のマスタ/Repository 基盤のみに依存)

目的

特許・商標・意匠・著作権等の出願状況・登録日・更新期限・維持費用を一元管理するデジタル台帳を構築する。年金等の維持費用は過去実績から向こう 3 年分の月次予算を自動生成して 41_trn_budget に合流させ、更新期限が近付いた権利は週次バッチでメール通知し、権利失効を未然に防ぐ。

現在のコード

F-35 は完全な新規機能であり、既存の知財管理コードは存在しない。 実装は以下の既存基盤を利用する(新規作成ではなく踏襲のみ):

  • 000_infra/003_contracts.js@typedef 記法と Contracts.toDto / Contracts.toRows ファクトリ
  • 200_data/202_repository.js の内部ヘルパー readSheetAsDtos_ / writeDtosToSheet_ / appendDtosToSheet_ / findLastRow_ と、OrderRepository / InvoiceRepository / JournalRepository の 4 メソッド構成(_getSheet / findAll / save / append
  • 100_config/101_sys_config.jssetupAllSchemas()schemas オブジェクト記法・confSheet.appendRow(['<KEY>', '', '<sheet_name>', '<label>']) によるシステムキー登録パターン
  • 000_infra/002_constants.jsID_PREFIX_MAP / SHEET_DEFAULTS 配列
  • 000_infra/004_utils.jsUtils.logInfo(funcName, message) / Utils.auditLog(operation, targetSheet, targetId, targetCol, funcName, beforeValue, afterValue, note) / Utils.getSheetByKey(key, fallbackName)

修正方針

全体を 3 Step に分割する。Step 1 はデータ基盤(DTO・定数・Repository・DDL)、Step 2 は維持費用の自動予測、Step 3 は期限アラートメール。

Step 1: データ基盤の新設

1-A: DTO 追加(000_infra/003_contracts.js の末尾)

既存 PartnerDTO と同じ @typedef 記法・フィールドコメント形式で以下 2 DTO を追記する。 プロパティ名は DDL スキーマのヘッダーと完全一致させる。

  • IntellectualPropertyDTO17_mst_intellectual_property(マスタ)
    • 有効フラグ / 知財ID(IP) / 知財種別 (特許 / 商標 / 意匠 / 著作権 等) / 出願番号 / 登録番号 / 件名 / 出願日 / 登録日 / 次回更新日 / ステータス (出願中 / 登録済 / 期限切れ / 放棄) / 権利者 / 担当弁理士・事務所 / PJ名 / 組織名 / 備考
  • IpCostDTO37_wrk_ip_cost(費用実績)
    • 有効フラグ / IP費用ID(IPC) / 知財ID(IP) / 発生日(P/L計上日) / 費用種別 (出願料 / 登録料 / 年金 / 更新料 / 弁理士手数料 等) / 取引先名 / 税抜金額 / 消費税額 / 税込金額 / 決済手段 / 証憑URL / 摘要

1-B: 000_infra/002_constants.jsID_PREFIX_MAP 末尾に 2 件追記

既存 { pattern: '31_wrk_order', prefix: 'ORD_', digit: 4, isDate: true } と同じ要素型で以下を追加する。マスタ系は isDate: false、ワーキング(トランザクション)系は isDate: true を既存エントリから踏襲する。

{ pattern: '17_mst_intellectual', prefix: 'IP_',  digit: 4, isDate: false },
{ pattern: '37_wrk_ip_cost',      prefix: 'IPC_', digit: 4, isDate: true  },

1-C: 000_infra/002_constants.jsSHEET_DEFAULTS 末尾に 2 件追記

既存 { pattern: '32_wrk_expense', prefix: 'EXP_', defaults: {...}, _dynamic: {...} } と同じ要素型で以下を追加する。17_mst_intellectual_property には { '知財種別': '特許', 'ステータス': '出願中' }37_wrk_ip_cost には { '費用種別': '年金', '税抜金額': 0, '消費税額': 0, '税込金額': 0, '税区分': '課税', _dynamic: { '発生日(P/L計上日)': 'now' } } を設定する。

1-D: 200_data/202_repository.js 末尾に 2 Repository 新設

OrderRepository のパターンを完全踏襲して IntellectualPropertyRepository / IpCostRepository を追加する(_getSheet / findAll / save / append の 4 メソッド構成)。内部ヘルパー readSheetAsDtos_ / writeDtosToSheet_ / appendDtosToSheet_ は再利用し、新規ヘルパーは作成しない。appendlastRowCol 引数は ID 列(0 始まりで列 B = 1)を指定する(OrderRepository.append と同じ)。

var IntellectualPropertyRepository = {
  _getSheet: function() { return Utils.getSheetByKey('MST_IPRT', '17_mst_intellectual_property'); },
  findAll:   function() { return readSheetAsDtos_(IntellectualPropertyRepository._getSheet()); },
  save:      function(dtos) { /* OrderRepository.save と同形 */ },
  append:    function(dtos) { /* OrderRepository.append と同形。lastRowCol=1 */ },
};

var IpCostRepository = {
  _getSheet: function() { return Utils.getSheetByKey('WRK_IPCS', '37_wrk_ip_cost'); },
  // 以下同形
};

BudgetRepository の有無: Phase 1 調査時点で 200_data/202_repository.jsBudgetRepository は未定義(41_trn_budgetJournalRepository と同じく DTO 経由で扱われておらず、600_report/601_datamart_ingest.js 等から直接シート読み取りされている)。本案件の Step 2 で 41_trn_budget に追記するにあたり、以下いずれかを選択する:

  • 案 A(採用): 200_data/202_repository.js 末尾に BudgetRepository を新設する(TRN_BUDG / 41_trn_budget を対象とし、JournalRepository と同形)。appendlastRowCol は ID 列(予算ID = 列 B = 0 始まりで 1)。
  • 案 B(不採用): 400_domain/408_rpa_ip_forecast.js 内で Utils.getSheetByKey('TRN_BUDG', '41_trn_budget') を直接呼び、appendDtosToSheet_ ではなく個別に書き込む。

案 A を採用する。Repository 経由に統一することで他 RPA からも再利用可能となり、Step 2 の書き込みロジックが単純化する。

1-E: 100_config/101_sys_config.jssetupAllSchemas() へ DDL 追記

const schemas = { ... } ブロック(L826 付近)に MST_IPRT / WRK_IPCS のエントリを追加し、confSheet.appendRow(...) ブロック(L783 付近、WRK_ORDR 登録行の近く)に 2 件のシステムキー登録を追加する。DTO のプロパティ名とヘッダーは完全一致させる。ステータス 列にはプルダウン(出願中 / 登録済 / 期限切れ / 放棄)、知財種別 列にはプルダウン(特許 / 商標 / 意匠 / 著作権 / その他)、費用種別 列にはプルダウン(出願料 / 登録料 / 年金 / 更新料 / 弁理士手数料 / その他)を既存 MST_PART のバリデーション記法に従って設定する。色は MST_IPRT"#666666"(マスタ系既定色)、WRK_IPCS"#b45f06"(ワーキング系既定色)。

システムキー登録例:

if (!existKeys.includes('MST_IPRT')) confSheet.appendRow(['MST_IPRT', '', '17_mst_intellectual_property', 'マスタ_知的財産台帳']);
if (!existKeys.includes('WRK_IPCS')) confSheet.appendRow(['WRK_IPCS', '', '37_wrk_ip_cost', 'サブ元帳_知財維持費用実績']);
if (!existKeys.includes('TRN_BUDG')) { /* 既存行のため追記不要 */ }

Step 2: 費用予測 RPA の新設(400_domain/408_rpa_ip_forecast.js

ファイル配置: CLAUDE.md のファイル番号体系で 400_domain/ レイヤーに 408_ / 409_ は未使用を ls 400_domain/ で確認済(既存最大番号は 407_rpa_orchestrator.js410_subledger_engine.js)。RPA 系列の空き番号として 408_ を割り当てる。

公開関数: generateIpForecastBudget()

処理フロー:

  1. IntellectualPropertyRepository.findAll() で全知財を取得し、有効フラグ = TRUE かつステータス = 登録済 のレコードを対象に絞る。
  2. IpCostRepository.findAll() で有効フラグ = TRUE かつ費用種別 = 年金 の実績を取得し、知財ID(IP) 別に直近の 税込金額 を保持する(同一 IP に複数実績がある場合は最新の 発生日(P/L計上日) を採用)。
  3. 実績が 0 件の知財は Utils.logInfo('generateIpForecastBudget', 'IP_XXXX: 年金実績なしのためスキップ') で警告ログを出力し、その知財の予算生成をスキップする(外挿は精度が低いため)。
  4. 実績が存在する知財については、直近年金額を向こう 3 年間(36 ヶ月)に月次均等配分ではなく「毎年 次回更新日 の月に 1 回」計上する形式で BudgetDTO を構築する。次回更新日 が未入力の場合はスキップし、Utils.logInfo で警告ログを出力する。
  5. 生成した BudgetDTO 配列を BudgetRepository.append(dtos)41_trn_budget に追記する。
  6. 完了時に SpreadsheetApp.getUi().alert で件数サマリを表示する(例: "IP予測予算を生成しました: 対象知財 5 件 / 追記行 15 件")。

BudgetDTO 生成仕様:

フィールド
有効フラグtrue
予算IDRepository 側で採番せず空欄で渡し、DDL 既定値/手動採番に委ねる(BudgetRepository.appendINV と異なり ID 自動採番ロジックを持たない。採番が必要な場合は将来拡張として RpaCommon.nextId_ 同等のヘルパー追加を検討)
対象年月次回更新日の YYYY-MM(+1 年、+2 年、+3 年の 3 パターン)
決済予定年月対象年月 と同じ
予算バージョン'最新予算(V1)'SHEET_DEFAULTS41_trn_budget エントリに合わせる)
収支区分'支出'
組織名知財マスタの 組織名(未入力時は '指定なし_共通費など'
PJ名知財マスタの PJ名(未入力時は '指定なし_共通費など'
科目名'租税公課'(※ 実装前に 11_mst_account で採用科目を確定すること。本仕様書では仮に '租税公課' を想定)
予算金額直近年金実績の 税込金額
摘要'[IP予測] ' + 知財ID + ' ' + '年金 ' + 対象年月 (例: [IP予測] IP_0001 年金 2027-04

冪等性: 41_trn_budget の既存レコードを BudgetRepository.findAll() で取得し、対象年月 × 摘要 の組で既存キーセットを構築。生成予定のレコードが既存セットに含まれる場合はスキップする。インメモリ Set を 1 回構築して走査するためロックは不要。

Human-in-the-Loop: 本 RPA はプレビュー画面を挟まず直接 41_trn_budget に追記する(既存の generateAdhocInvoices 等と同様)。ユーザーはシート上で 摘要 列の [IP予測] プレフィックスで検索・修正・削除できる。冪等性により再実行しても重複しない。

Step 3: 期限アラート RPA の新設(400_domain/409_rpa_ip_alert.js

ファイル配置: CLAUDE.md のファイル番号体系で 700_batch/ ディレクトリは存在しない(000_infra / 100_config / 200_data / 300_ui / 400_domain / 500_import / 600_report / 800_ops / 900_test のみ)。期限アラートバッチは RPA 系の派生として 400_domain/ レイヤーの空き番号 409_ に配置する。

公開関数: sendIpExpirationAlert()

処理フロー:

  1. IntellectualPropertyRepository.findAll() で全知財を取得し、有効フラグ = TRUE かつステータス = 登録済 のレコードを対象に絞る。
  2. 各レコードについて 次回更新日 を評価し、以下のいずれかを満たすレコードを抽出:
    • 次回更新日 が本日から 90 日以内(本日含む)
    • 次回更新日 が過去日付(本日より前)
    • 次回更新日 が未入力(Date として無効)
  3. 抽出結果を Utilities.formatDate で整形したテーブル形式の HTML 本文に組み立てる。
  4. 送信先は Constants.getParam('IP_ALERT_EMAIL', '')03_sys_params から取得する(未設定時は Utils.logInfo で警告を出力し送信をスキップ)。
  5. MailApp.sendEmail({ to, subject, htmlBody }) で送信する。件名は '[知財アラート] 更新期限が近付いた/超過した知財があります (' + 件数 + ' 件)'
  6. 送信後に Utils.auditLog('SEND', '17_mst_intellectual_property', '', '', 'sendIpExpirationAlert', '', String(件数), 'IP期限アラートメール送信') で監査ログを記録する。

メール本文フォーマット(HTML):

<h3>更新期限が近付いた/超過した知財</h3>
<table border="1" cellpadding="4">
  <tr><th>知財ID</th><th>知財種別</th><th>件名</th><th>次回更新日</th><th>残日数</th><th>ステータス</th></tr>
  <!-- 各レコード -->
</table>
<p>本メールは週次バッチ <code>sendIpExpirationAlert</code> から自動送信されています。</p>

トリガー登録: GAS エディタから手動で週次タイムドトリガー(ScriptApp.newTrigger('sendIpExpirationAlert').timeBased().everyWeeks(1).atHour(9).create() 相当)を設定する。動作確認手順にトリガー登録方法を記載する。

影響範囲

  • 修正ファイル(追記のみ):
    • 000_infra/003_contracts.js(末尾に @typedef 2 件追記)
    • 000_infra/002_constants.jsID_PREFIX_MAP / SHEET_DEFAULTS の配列末尾に各 2 件追記)
    • 200_data/202_repository.js(末尾に IntellectualPropertyRepository / IpCostRepository / BudgetRepository 追記)
    • 100_config/101_sys_config.jssetupAllSchemas()schemas / confSheet.appendRow ブロックに 2 件追記)
  • 新規ファイル:
    • 400_domain/408_rpa_ip_forecast.js
    • 400_domain/409_rpa_ip_alert.js
  • 新規シート(DDL で自動作成):
    • 17_mst_intellectual_property(マスタ)
    • 37_wrk_ip_cost(費用実績)

注意事項

  1. Utils.getSheetByKey(key, fallbackName) に渡すシステムキーは Phase 1 で確定した 'MST_IPRT' / 'WRK_IPCS' / 'TRN_BUDG' のみ使用する。既存キーの命名規則(4 文字大文字 + アンダースコア)を踏襲し、新規キーを勝手に造語しない。
  2. 列参照は data[0].indexOf('有効フラグ') のようにヘッダー名ベースで行う。列番号ハードコード禁止(CLAUDE.md コーディング規約)。
  3. 有効フラグ === false || String(有効フラグ).toUpperCase() === 'FALSE' の行は全処理でスキップする(全 Repository で必須のフィルタ)。
  4. 700_batch/ ディレクトリは CLAUDE.md のファイル番号体系に存在しないため使用不可。期限アラートは 400_domain/409_rpa_ip_alert.js に配置する。
  5. 動作確認手順に記載するメニュー名は Constants.MENU_DEFINITION に実在するラベル(例: 'DDL 全更新 (Full)'setupAllSchemas'全テスト実行'runAllTests)のみ使用する。造語禁止。
  6. 41_trn_budget への書き込みは Step 1-D の案 A(BudgetRepository 新設)で統一する。JournalRepository.append と同形のため追加のヘルパーは不要。
  7. Step 2 の費用予測は Human-in-the-Loop 原則に従い、ユーザーがシート上で直接レビュー・修正する運用とする(プレビュー画面なし)。冪等性により再実行しても重複しない。
  8. Step 3 のメール送信先は 03_sys_paramsIP_ALERT_EMAIL から取得する。未設定時はエラーで落とさず、警告ログを出して処理を終了する(夜間バッチが失敗トリガーを大量発生させないため)。
  9. 11_mst_account に知財費用の勘定科目(例: 租税公課)が登録されていない場合、Step 2 の予算レコードは InvoiceRepository のような自動マッピングを通らないため 諸表区分 / 大分類 は空欄になる。実装前にマスタ登録状況を確認する。

エッジケース

条件動作理由
37_wrk_ip_cost に費用種別 年金 の実績が対象 IP に対して 0 件当該 IP を費用予測対象からスキップし、Utils.logInfo('generateIpForecastBudget', 'IP_XXXX: 年金実績なしのためスキップ') を出力実績 0 からの外挿は不正確
次回更新日 が未入力かつステータス = 登録済アラート送信対象とする(残日数欄は 未入力 と表示)日付未設定は管理漏れリスク。気付ける形で通知する
次回更新日 が過去日付かつステータス = 登録済アラート送信対象とし、残日数をマイナス値(例: -14日)で表示期限超過の可能性あり。即対応が必要
ステータスが 期限切れ / 放棄 / 出願中(= 登録済 以外)アラート送信対象からスキップ管理対象外。出願中 は登録前のため更新期限の概念がない
費用予測の冪等性チェック: 対象年月 × 摘要 キーが既存レコードと一致当該レコードのみスキップ(上書きしない)ユーザーが手修正した行を潰さないため
41_trn_budget への書き込みに失敗(シート取得不可・列数不一致等)Utils.logError でエラーログ出力し、UI アラートで失敗を通知して処理中断データ整合性優先。部分書き込みを避ける
03_sys_paramsIP_ALERT_EMAIL が未登録メール送信をスキップし、Utils.logInfo('sendIpExpirationAlert', 'IP_ALERT_EMAIL 未設定のためスキップ') を出力して正常終了夜間バッチが失敗トリガーを大量発生させるのを防ぐ
同日中に sendIpExpirationAlert が複数回実行される重複送信を許容する(送信抑制ロジックは持たない)週次トリガー運用が前提。手動再実行も監査証跡として 98_audit_log に残る
17_mst_intellectual_property に 1 件もレコードがない両 RPA とも 件数 0 の完了通知のみを出して正常終了(エラーにしない)初期導入期に空シートで実行されるケースをカバー
知財マスタの 知財ID(IP) が重複しているIpCostRepository との結合時に両レコードが同じ実績を参照することになるが、予算生成の重複は 対象年月 × 摘要 冪等性で排除されるID 重複は DDL バリデーションで防止すべきだが、本 RPA 側では冪等性で緩衝
次回更新日 が Date 型ではなく文字列(例: '2027/04/15'Utils.parseDateToYm と同等の前処理で Date に変換。変換不可は 未入力 扱い手入力由来の型ゆらぎに備える
費用予測 科目名11_mst_account 未登録InvoiceRepository.append のような自動マッピングは動作しないため 諸表区分 / 大分類 が空欄のまま 41_trn_budget に追記されるマスタ整備を人間の事前作業とする。実装前検証で科目登録を必須前提として明示

実データ検証

実装着手前に dev 環境で以下を確認する。

  • 11_mst_account に知財費用用の勘定科目が登録されているか。候補: 租税公課(年金は事業運営上の税公課類似)/ 支払手数料(弁理士手数料)/ 無形固定資産 - 特許権(資産計上する場合)。未登録ならマスタ追加を実装前提条件とする。
  • 03_sys_paramsIP_ALERT_EMAIL キーを追加する必要がある(本仕様書で新規定義)。値は代表メールアドレス(例: [email protected])を想定。
  • 12_mst_partner に弁理士事務所が登録されているか(費用種別 = 弁理士手数料 実績の取引先名参照用)。未登録は実装後の運用で随時追加。
  • 既存 41_trn_budget[IP予測] プレフィックスで始まる 摘要 レコードが存在しないこと(冪等性キーの競合チェック)。

関連ドキュメント

仕様書リンク関連箇所
CLAUDE.mdファイル番号体系・コーディング規約・マイグレーション運用ガイドライン
docs/prd.mdプロダクトポリシー(Human-in-the-Loop)
dev_F-25_budget_variance.md41_trn_budget の予実差異分析(本案件の予算行が予実差異にも載る)
dev_N-16_repository_module_split.mdRepository パターンの設計思想(本案件の新 Repository 2 件はこの方針に従う)

人間が検討すべき事項

TODO_future.md F-35 行に記載の検討事項と、Phase 1 調査で判明した追加事項を以下にまとめる。

  1. 管理対象の知財カテゴリ範囲: 特許のみ運用開始するか、商標・意匠・著作権も同時に対象とするか。本仕様では 知財種別 プルダウンに 4 種 + その他 を含めた汎用設計としたが、初期運用は 特許 のみでデータ投入し、他種別は実運用が発生した時点で段階拡張する案を推奨する。
  2. 外部特許管理 SaaS との連携要否: 特許事務所提供の管理システム(例: ソフト VPN、PatentSQUARE 等)との CSV / API 連携を将来的に追加する可能性。本案件は純粋な内製台帳として設計し、外部連携は後続案件で検討する。
  3. 費用予測の外挿ロジック: 「直近年金額をそのまま向こう 3 年計上」で十分か、年齢加算料の段階増額(特許の場合は年数経過で年金が段階的に上昇する制度)を反映すべきか。Phase 1 時点では直近値踏襲で実装し、精度要件が高まった時点で外挿ロジックを拡張する。
  4. 勘定科目の確定: 年金は 租税公課 / 支払手数料 / 特許維持費 のいずれに計上するか。顧問税理士と合意の上、11_mst_account に登録してから実装に入る。
  5. アラート送信先の粒度: 03_sys_paramsIP_ALERT_EMAIL を単一アドレスで運用するか、複数宛先(経理 + 研究開発部門長)に展開するか。複数化する場合はカンマ区切りでパースする。
  6. 資産計上の扱い: 特許権は無形固定資産として計上する場合もあるが、本案件は維持費用(費用計上)のみを扱う。取得時の資産計上は F-03 系の CAPEX RPA の派生として別案件化する。
  7. 次回更新日の自動更新: 年金支払後に 次回更新日 を +1 年する自動更新ロジックを Step 2 の予算生成と連動させるか、手動運用とするか。初期実装は手動更新とし、運用負荷が顕在化した時点で検討する。
  8. 41_trn_budget への 予算ID 採番方式: 本仕様では空欄で追記する暫定方針としたが、将来的に BDG_NNNN の自動採番を BudgetRepository.append 側に持たせるか、新設の RpaCommon.nextBudgetId_ に切り出すか。他の予算系 RPA(adhoc 等)と足並みを揃える。

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

Step 1: データ基盤の新設

あなたはGAS会計システム(bizlp-gas-accounting)のシニア開発者です。
案件 F-35「知的財産ポートフォリオ管理」の Step 1(データ基盤の新設)を実装してください。

## 実行前タスク(必ずRead)
- `000_infra/003_contracts.js` — 既存 @typedef の記法・フィールドコメント形式・ファイル末尾行番号を確認
- `000_infra/002_constants.js` — ID_PREFIX_MAP(L93 付近)と SHEET_DEFAULTS(L73 付近)の要素型・既存エントリの末尾を確認
- `200_data/202_repository.js` — OrderRepository(L107)と JournalRepository(L259)の _getSheet/findAll/save/append パターンを確認。BudgetRepository は未定義であることも確認
- `100_config/101_sys_config.js` — setupAllSchemas() の schemas 定義(L826 付近)と confSheet.appendRow(...) のシステムキー登録(L783 付近)の作法を確認
- `docs/dev/dev_F-35_ip_portfolio.md` — 本仕様書

## 修正対象ファイル
- `000_infra/003_contracts.js`(末尾に追記のみ)
- `000_infra/002_constants.js`(ID_PREFIX_MAP と SHEET_DEFAULTS の配列末尾に追記のみ)
- `200_data/202_repository.js`(末尾に追記のみ)
- `100_config/101_sys_config.js`(setupAllSchemas() 内に追記のみ)

## 実装内容
1. `003_contracts.js` 末尾に IntellectualPropertyDTO / IpCostDTO の @typedef を追加(既存 OrderDTO の記法に完全準拠)
2. `002_constants.js` の ID_PREFIX_MAP 末尾に以下を追加:
   { pattern: '17_mst_intellectual', prefix: 'IP_',  digit: 4, isDate: false },
   { pattern: '37_wrk_ip_cost',      prefix: 'IPC_', digit: 4, isDate: true  }
3. `002_constants.js` の SHEET_DEFAULTS 末尾に新シート2件分のデフォルト値エントリを追加:
   - '17_mst_intellectual_property': { '知財種別': '特許', 'ステータス': '出願中' }
   - '37_wrk_ip_cost': { '費用種別': '年金', '税抜金額': 0, '消費税額': 0, '税込金額': 0, '税区分': '課税', _dynamic: { '発生日(P/L計上日)': 'now' } }
4. `202_repository.js` 末尾に IntellectualPropertyRepository / IpCostRepository / BudgetRepository を追加(OrderRepository パターンを完全踏襲。_getSheet/findAll/save/append の4メソッド構成)。
   - IntellectualPropertyRepository: Utils.getSheetByKey('MST_IPRT', '17_mst_intellectual_property')
   - IpCostRepository: Utils.getSheetByKey('WRK_IPCS', '37_wrk_ip_cost')
   - BudgetRepository: Utils.getSheetByKey('TRN_BUDG', '41_trn_budget')
   - いずれも append の lastRowCol は ID 列(= 1、列 B 基準)
5. `101_sys_config.js` の setupAllSchemas() に以下を追加:
   - confSheet.appendRow 群(L783 付近)に MST_IPRT / WRK_IPCS のシステムキー登録
   - schemas オブジェクトに 'MST_IPRT' / 'WRK_IPCS' の DDL エントリ(headers・color・validations)
   - ヘッダーは 003_contracts.js の @typedef プロパティ名と完全一致させること

## DDL ヘッダー定義
- MST_IPRT: ["有効フラグ","知財ID(IP)","知財種別","出願番号","登録番号","件名","出願日","登録日","次回更新日","ステータス","権利者","担当弁理士・事務所","PJ名","組織名","備考"]
- WRK_IPCS: ["有効フラグ","IP費用ID(IPC)","知財ID(IP)","発生日(P/L計上日)","費用種別","取引先名","税抜金額","消費税額","税込金額","決済手段","証憑URL","摘要"]

## 制約
- 既存のRepository・DTO・定数定義は一切変更しない(追記のみ)
- 列参照はヘッダー名ベース(indexOf)。列番号ハードコード禁止
- メニュー名・定数名・シート名はReadで確認した実在する文字列のみ使用すること

## 動作確認
1. npm run push:dev
2. GASエディタから「DDL 全更新 (Full)」(setupAllSchemas) を実行
3. `17_mst_intellectual_property` と `37_wrk_ip_cost` が作成され、ヘッダー・プルダウン・色が正しいことを確認
4. 01_sys_config に MST_IPRT / WRK_IPCS 行が追加されたことを確認
5. 901_test_runner.js の「全テスト実行」で既存テストが壊れていないことを確認

Step 2: 費用予測 RPA の新設

あなたはGAS会計システム(bizlp-gas-accounting)のシニア開発者です。
案件 F-35「知的財産ポートフォリオ管理」の Step 2(費用予測 RPA)を実装してください。Step 1 完了後に着手すること。

## 実行前タスク(必ずRead)
- `400_domain/405_rpa_adhoc.js` — 既存 RPA の関数シグネチャ(generateAdhocInvoices)と InvoiceRepository.append の呼び出しパターン
- `400_domain/400_rpa_common.js` — RpaCommon の ID 採番・冪等性ヘルパー(参考のみ、本 RPA は予算書き込みのため流用しない可能性あり)
- `200_data/202_repository.js` — Step 1 で追加した BudgetRepository / IntellectualPropertyRepository / IpCostRepository
- `000_infra/003_contracts.js` — BudgetDTO / IntellectualPropertyDTO / IpCostDTO
- `000_infra/004_utils.js` — Utils.logInfo / Utils.auditLog / Utils.parseDateToYm のシグネチャ
- `docs/dev/dev_F-35_ip_portfolio.md` — 本仕様書

## 新規ファイル
- `400_domain/408_rpa_ip_forecast.js`

## 公開関数
- `generateIpForecastBudget()` — メニューから起動される公開関数

## 実装内容
1. IntellectualPropertyRepository.findAll() で全知財を取得
2. 有効フラグ=TRUE かつ ステータス='登録済' のレコードに絞り込み
3. IpCostRepository.findAll() で年金実績を取得し、知財ID(IP) → 直近 税込金額 のマップを構築(発生日(P/L計上日) 最新を採用)
4. 実績なし/次回更新日なしの知財は Utils.logInfo で警告を出してスキップ
5. 各対象知財について、次回更新日 + 1年/+2年/+3年 の 3 レコードの BudgetDTO を構築
6. BudgetRepository.findAll() で既存レコードの「対象年月 + 摘要」キーセットを作成し、重複分をスキップ(冪等性)
7. BudgetRepository.append(dtos) で 41_trn_budget に追記
8. 完了時に SpreadsheetApp.getUi().alert で件数サマリを表示
9. 監査ログ Utils.auditLog('RUN', '41_trn_budget', '', '', 'generateIpForecastBudget', '', String(追記件数), 'IP費用予測バッチ実行') を記録

## 摘要キー仕様
- 形式: '[IP予測] ' + 知財ID + ' 年金 ' + 対象年月(例: '[IP予測] IP_0001 年金 2027-04')
- 冪等性キー: 対象年月 × 摘要(完全一致)

## BudgetDTO 生成仕様
| フィールド | 値 |
|---------|-----|
| 有効フラグ | true |
| 予算ID | 空欄(将来の RpaCommon 拡張で自動採番を検討) |
| 対象年月 | 次回更新日の翌年/翌々年/翌々々年の YYYY-MM |
| 決済予定年月 | 対象年月と同じ |
| 予算バージョン | '最新予算(V1)' |
| 収支区分 | '支出' |
| 組織名 | 知財マスタの 組織名(空欄時は '指定なし_共通費など') |
| PJ名 | 知財マスタの PJ名(空欄時は '指定なし_共通費など') |
| 科目名 | '租税公課'(実装前に 11_mst_account で採用科目を確定) |
| 予算金額 | 直近年金実績の 税込金額 |
| 摘要 | '[IP予測] ' + 知財ID + ' 年金 ' + 対象年月 |

## メニュー登録
- `000_infra/002_constants.js` の MENU_DEFINITION「📋 サイドバー: 📒 経理業務 (RPA / Action)」カテゴリに1行追加:
  { label: '💡 知財 年金予算 生成', funcName: 'generateIpForecastBudget', description: '登録済知財の直近年金実績から向こう3年の予算を41タブに追記' }

## 制約
- 列参照はヘッダー名ベース(indexOf / buildHeaderIndex_)。列番号ハードコード禁止
- 有効フラグ=FALSE の行はスキップ
- 冪等性必須(再実行しても重複レコードを生まないこと)

## 動作確認
1. npm run push:dev
2. 17_mst_intellectual_property に登録済知財を 1 件投入(次回更新日を未来日付にする)
3. 37_wrk_ip_cost に対応する年金実績を 1 件投入
4. メニュー「💡 知財 年金予算 生成」を実行 → 41_trn_budget に 3 行追記されることを確認
5. 再実行 → 冪等性によりスキップされ 0 行追記となることを確認
6. 901_test_runner.js の「全テスト実行」で既存テストが壊れていないことを確認

Step 3: 期限アラート RPA の新設

あなたはGAS会計システム(bizlp-gas-accounting)のシニア開発者です。
案件 F-35「知的財産ポートフォリオ管理」の Step 3(期限アラート RPA)を実装してください。Step 1 完了後に着手すること(Step 2 との依存はない)。

## 実行前タスク(必ずRead)
- `200_data/202_repository.js` — Step 1 で追加した IntellectualPropertyRepository
- `000_infra/002_constants.js` — Constants.getParam('IP_ALERT_EMAIL', '') の使用パターン
- `000_infra/004_utils.js` — Utils.logInfo / Utils.auditLog / Utils.formatDate ヘルパー(存在するもののみ使用)
- `docs/dev/dev_F-35_ip_portfolio.md` — 本仕様書

## 新規ファイル
- `400_domain/409_rpa_ip_alert.js`

## 公開関数
- `sendIpExpirationAlert()` — 週次タイムドトリガーから起動される公開関数

## 実装内容
1. IntellectualPropertyRepository.findAll() で全知財を取得
2. 有効フラグ=TRUE かつ ステータス='登録済' のレコードに絞り込み
3. 各レコードの 次回更新日 について:
   - 90日以内(本日含む)→ 対象
   - 過去日付 → 対象(残日数をマイナスで表示)
   - 未入力 → 対象(残日数欄に '未入力' と表示)
4. 対象件数 0 件なら送信せず Utils.logInfo で終了
5. Constants.getParam('IP_ALERT_EMAIL', '') で送信先を取得。空文字なら Utils.logInfo 出力してスキップ
6. HTML 本文を組み立てて MailApp.sendEmail({ to, subject, htmlBody }) で送信
7. Utils.auditLog('SEND', '17_mst_intellectual_property', '', '', 'sendIpExpirationAlert', '', String(件数), 'IP期限アラートメール送信') を記録

## メール仕様
- 件名: '[知財アラート] 更新期限が近付いた/超過した知財があります (' + 件数 + ' 件)'
- 本文 HTML テーブル: 知財ID / 知財種別 / 件名 / 次回更新日 / 残日数 / ステータス
- 残日数は (次回更新日 - 本日) の日数を整数表示(マイナス可)

## メニュー登録
- `000_infra/002_constants.js` の MENU_DEFINITION「📋 サイドバー: 📒 経理業務 (RPA / Action)」カテゴリに1行追加:
  { label: '📧 知財 期限アラート送信', funcName: 'sendIpExpirationAlert', description: '登録済知財の更新期限90日以内/超過レコードをメール送信' }

## 03_sys_params 登録
- キー: IP_ALERT_EMAIL
- 値: 代表経理メールアドレス(例: [email protected])
- DDL では登録しない。ユーザーが運用開始時に手動で行追加する

## 週次トリガー登録(動作確認時に手動実施)
GASエディタから以下を1回だけ実行:
```
function installIpAlertTrigger() {
  ScriptApp.newTrigger('sendIpExpirationAlert')
    .timeBased()
    .onWeekDay(ScriptApp.WeekDay.MONDAY)
    .atHour(9)
    .create();
}
```

## 制約
- 列参照はヘッダー名ベース。列番号ハードコード禁止
- IP_ALERT_EMAIL 未登録でもエラーにしない(警告ログ + 正常終了)

## 動作確認
1. npm run push:dev
2. 03_sys_params に IP_ALERT_EMAIL キーを自分のメールアドレスで登録
3. 17_mst_intellectual_property に次回更新日を本日 +30日・本日 -10日・空欄 の 3 レコードを投入
4. メニュー「📧 知財 期限アラート送信」を実行 → 3 件分のテーブルが記載されたメールが届くことを確認
5. IP_ALERT_EMAIL を削除して再実行 → 警告ログ出力のみで正常終了することを確認
6. 901_test_runner.js の「全テスト実行」で既存テストが壊れていないことを確認

推奨実行モデル

工程推奨モデル理由
Step 1: データ基盤の新設Claude Sonnet 4.6既存 OrderRepository / schemas 定義を完全踏襲する作業。挿入位置の特定と整合性確認が必要だが設計判断は軽い
Step 2: 費用予測 RPA の新設Claude Opus 4.6複数 Repository 横断・冪等性キー設計・BudgetDTO 組み立て・会計ロジック(科目名の確定)の理解が必要
Step 3: 期限アラート RPA の新設Claude Haiku 4.5単一 Repository 読み取り + MailApp 送信のシンプルなロジック。仕様書で完全定義済

変更履歴

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

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

展開して表示
【タイムアウト回避・実行原則(v1.7・必ず遵守すること)】
1. **拡張思考の使い分け**: Phase 1(設計フェーズ)では拡張思考をフル活用し、ファイル名形式・エッジケース一覧・Step分割粒度・固有名詞(関数名/シート名/列名/行番号)を完全に確定させる。Phase 2(清書フェーズ)の各Step内では拡張思考を最小限に抑え、Phase 1で確定した内容の書き下しに徹する。出力途中で再考しない。
2. **テキスト報告の禁止**: 「〜を作成します」等のtextのみで tool_use なしにturnを終了しない。説明は1文以内。直ちにtoolを呼ぶ。
3. **4-5分割のWrite/Edit実行**: 仕様書作成は以下のStepに分けて実行する。1回のWrite/Editは約300行以内を目安にする。
   - 2-1 骨格Write(〜20行)
   - 2-2 概要〜注意事項 Edit/Bash(〜300行)
   - 2-3a エッジケース〜人間検討事項 Edit/Bash(〜200行)
   - 2-3b 実装プロンプト〜変更履歴 Edit/Bash(〜250行)
   - 2-4 `<details>` にプロンプト全文記録 Edit/Bash(最重量・必ず独立Step)
4. **各Stepで何を書くかを具体指示**: 設計判断をPhase 2実行時に持ち込まないよう、Phase 1でファイルパス・固有名詞・行番号をすべて確定させてからPhase 2に進む。

======================================================================
あなたはGAS会計システム(bizlp-gas-accounting)のシニア開発者兼仕様書ライターです。
CLIエージェント「Claude Code」として、案件 F-35「知的財産ポートフォリオ管理」の開発仕様書を作成してください。
開発仕様書を新規作成した後、`docs/_config.json` の `nav` 配列の適切なセクションにも必ず追記してください。

---

## Phase 1: 実行前タスク(テキスト報告禁止。即座にツール実行)

以下を全てReadし、Phase 2の各Stepで設計判断を再考しないよう、固有名詞・行番号・型構造を完全に確定させる。**Grepは「どこにあるか」の発見まで。「どう書くか」の判断は必ずReadで裏取りする。**

### 1-A: 案件定義の読み込み
- `docs/_internal/TODO_future.md` から F-35 の行を検索し、案件名・概要・期待される効果・人間が検討すべき事項を取得する。

### 1-B: プロジェクト規約の読み込み
- `CLAUDE.md` を読み込み、**ファイル番号体系**(百の位=レイヤー)・コーディング規約・マイグレーション運用ガイドライン・テスト手順を把握する。特に `400_domain/` に存在しない番号(408, 409等)の確認と、700番台ディレクトリが体系に存在しないことを確認する。

### 1-C: 既存仕様書テンプレートの読み込み
- `docs/dev/dev_F-01_variance_analysis.md` または類似の新機能系仕様書を1件読み込み、セクション構成・実装プロンプトのフォーマット(行頭4スペースインデント)を把握する。

### 1-D: 関連コードの調査(Grep→Read の順。推測で書かない)

以下のファイルをReadし、仕様書に書く全ての固有名詞・型・行番号を裏取りすること。

**1. `000_infra/003_contracts.js`**
- 既存 `@typedef` の記法・フィールドのコメント形式・ファイル末尾の追記可能位置を確認する。
- `IntellectualPropertyDTO` / `IpCostDTO` を追加する際の記述フォーマットのベースにする。

**2. `000_infra/002_constants.js`**
- `ID_PREFIX_MAP` 配列の要素型(`{ pattern, prefix, digit, isDate }`)と既存エントリを確認し、マスタ系シートが `isDate: false`、ワーキング系シートが `isDate: true` であることを既存エントリから確認する。
- `SHEET_DEFAULTS` 配列の要素型(`{ pattern, prefix, defaults, _dynamic }`)を確認し、新シート2件分のデフォルト値エントリを設計する。

**3. `200_data/202_repository.js`**
- 内部ヘルパー `readSheetAsDtos_` / `writeDtosToSheet_` / `appendDtosToSheet_` / `findLastRow_` の引数・戻り値を確認する。
- `OrderRepository` または `InvoiceRepository` の `_getSheet` / `findAll` / `save` / `append` 実装パターンを完全に把握し、新設 Repository 2件(`IntellectualPropertyRepository` / `IpCostRepository`)の記述テンプレートを確定する。
- **`BudgetRepository` が定義されているかを確認する**。存在しない場合、`41_trn_budget` への行追記は `JournalRepository.append` と同一パターンで実装可能か、または別の方法が必要かを確定し、仕様書に記載する。

**4. `100_config/101_sys_config.js`**
- `setupAllSchemas()` 内のDDLスキーマ定義方法(列定義・プルダウン設定の書き方)を確認する。
- `Constants.CONFIG_SHEET`(= `'01_sys_config'`)へのシートキー登録方法(`Utils.getSheetByKey` で使う `'WRK_ORDR'` のようなキー名)の命名規則を確認し、新シート用のシステムキー(例: `MST_IPRT` / `WRK_IPCS`)を確定する。
- `onOpen()` で実際に定義されているメニュー名を確認する(動作確認手順に使うため。存在しない名前を造語しない)。

**5. `400_domain/` 配下のファイル一覧確認(Bash)**
- `ls 400_domain/` を実行し、`408_` および `409_` が未使用であることを確認する。
- 期限アラートバッチ用のファイル配置先を確定する。**`700_batch/` ディレクトリは `CLAUDE.md` のファイル番号体系に存在しないため使用不可**。`400_domain/409_rpa_ip_alert.js` が適切かを体系に照らして確定し、仕様書に記載する。

**6. `000_infra/004_utils.js`**
- `Utils.logInfo` / `Utils.auditLog` の引数シグネチャを確認する(実装プロンプトに正確な呼び出し形式を記載するため)。

---

## Phase 2: 仕様書の分割作成

出力先: `docs/dev/dev_F-35_ip_portfolio.md`
**【重要】1回のツール呼び出しで全内容を出力せず、以下のStepに分割して実行すること。**

### Step 2-1: 骨格の作成(File Write, 〜20行)
見出しのみ。本文は空で可。以下のセクションを含めること:
`# F-35: 知的財産ポートフォリオ管理` / `## 概要` / `## 目的` / `## 現在のコード` / `## 修正方針` / `## 影響範囲` / `## 注意事項` / `## エッジケース` / `## 実データ検証` / `## 関連ドキュメント` / `## 人間が検討すべき事項` / `## 実装プロンプト(Claude Code 用)` / `## 推奨実行モデル` / `## 変更履歴` / `## 仕様書作成プロンプト`

### Step 2-2: 前半セクションの追記(File Edit または Bash, 〜300行)
以下を含める。固有名詞は全てPhase 1で裏取りしたものを使用すること。

**## 概要**(テーブル: 案件ID / カテゴリ / Phase / 優先度 / 所要時間 / 対象ファイル / 前提案件)

**## 目的**(1〜3文。知財ライフサイクル管理の台帳化・維持費用の自動予測・更新期限の自動通知を目的とする)

**## 現在のコード**(新規機能のため「現在のコードなし」と明記。既存の利用予定コードを箇条書きで参照)

**## 修正方針**(以下の3 Stepに分割して記述)

**Step 1: データ基盤の新設**
- `000_infra/003_contracts.js` 末尾に `IntellectualPropertyDTO` / `IpCostDTO` の `@typedef` を追加(Phase 1-D.1で確認した記法に準拠)
- `000_infra/002_constants.js` の `ID_PREFIX_MAP` に以下2件を追加(Phase 1-D.2で確認した要素型に準拠):
  - `{ pattern: '17_mst_intellectual', prefix: 'IP_', digit: 4, isDate: false }`
  - `{ pattern: '37_wrk_ip_cost', prefix: 'IPC_', digit: 4, isDate: true }`
- `000_infra/002_constants.js` の `SHEET_DEFAULTS` に `17_mst_intellectual_property` / `37_wrk_ip_cost` のデフォルト値エントリを追加(Phase 1-D.2で確認した要素型に準拠)
- `200_data/202_repository.js` 末尾に `IntellectualPropertyRepository` / `IpCostRepository` を追加(Phase 1-D.3で確認した既存Repositoryパターンを完全踏襲。`_getSheet` / `findAll` / `save` / `append` の4メソッド構成)
- `100_config/101_sys_config.js` の `setupAllSchemas()` に両シートのDDLスキーマ(列定義・プルダウン設定・システムキー登録)を追加(Phase 1-D.4で確認した作法に準拠)

**Step 2: 費用予測RPAの新設**(`400_domain/408_rpa_ip_forecast.js`)
- `IntellectualPropertyRepository.findAll()` でステータス「登録済」レコードを取得
- `IpCostRepository.findAll()` で費用種別「年金」の最新実績金額を取得(1件も存在しない場合は `Utils.logInfo` で警告を出力しスキップ)
- 向こう3年間(月次36件)の予算行を `BudgetDTO` 形式で生成し、`41_trn_budget` に追記(書き込み方法はPhase 1-D.3で確認したパターンに従う)
- **冪等性**: `摘要` 列に `[IP予測] IP_XXXX 年金 YYYY-MM` 形式の一意キーを埋め込み、対象年月×摘要キーで既存レコードを事前照合してスキップまたは上書き。インメモリロック不要
- Human-in-the-Loop: 予算行はプレビューなしで直接書き込む。ユーザーがシート上で結果を確認・修正するフローであることを仕様書に明記

**Step 3: 期限アラートの新設**(`400_domain/409_rpa_ip_alert.js`。配置先はPhase 1-D.5で確定したパスを使用)
- `IntellectualPropertyRepository.findAll()` で「次回更新日」が本日から90日以内かつステータス「登録済」のレコードを抽出
- `MailApp.sendEmail()` で通知(宛先は `03_sys_params` または `Constants.getParam` で取得するパラメータとする。件名・本文フォーマットを仕様書に定義)
- 週次タイムドトリガー(`ScriptApp.newTrigger().timeBased().everyWeeks(1).create()`)での実行を前提とし、トリガー登録手順を動作確認に含める

**## 影響範囲**
- 修正ファイル: `003_contracts.js` / `002_constants.js` / `202_repository.js` / `101_sys_config.js`
- 新規ファイル: `400_domain/408_rpa_ip_forecast.js` / `400_domain/409_rpa_ip_alert.js`(配置先はPhase 1-D.5で確定したパスに従う)
- 新規シート: `17_mst_intellectual_property` / `37_wrk_ip_cost`

**## 注意事項**
1. `Utils.getSheetByKey(key, fallbackName)` に渡すシステムキーはPhase 1-D.4で確認した命名規則に従うこと
2. 列参照はヘッダー名ベース(`indexOf` / `buildHeaderIndex_`)で行う。列番号ハードコード禁止
3. 有効フラグ=FALSE の行は全処理でスキップ
4. `700_batch/` ディレクトリは `CLAUDE.md` のファイル番号体系に存在しないため使用不可。期限アラートは `400_domain/409_rpa_ip_alert.js` に配置する(Phase 1-D.5で確定したパスに従う)
5. 動作確認手順に記載するメニュー名はPhase 1-D.4で確認した実在する文字列のみ使用すること(造語禁止)
6. `41_trn_budget` への書き込みはPhase 1-D.3で確認したパターンに従うこと(`BudgetRepository` の存在有無を事前確認)

### Step 2-3a: エッジケース〜人間検討事項の追記(File Edit または Bash, 〜200行)

**## エッジケース**(テーブル形式)

| 条件 | 動作 | 理由 |
|------|------|------|
| `37_wrk_ip_cost` に費用種別「年金」の実績が0件 | 対象知財をスキップ + `Utils.logInfo` で警告出力 | 実績なしでの外挿は不正確 |
| 「次回更新日」未入力かつステータス「登録済」 | アラート送信対象とする | 日付未設定は管理漏れリスク |
| 「次回更新日」が過去日付かつステータス「登録済」 | アラート送信対象とする | 期限超過の可能性あり |
| ステータスが「放棄」「期限切れ」等 | アラート対象からスキップ | 管理対象外のため |
| 費用予測の冪等性チェック:対象年月×摘要キーが既存レコードと一致 | スキップ(上書きとスキップのどちらかを仕様確定して明記) | 二重計上防止 |
| `41_trn_budget` への書き込みに失敗(シート取得不可等) | `Utils.logError` でエラーログ出力し処理中断 | データ整合性 |

**## 実データ検証**
- `11_mst_account` に知財の費用計上科目名(「特許料」「商標登録費」等)が登録されているか確認する(未登録なら科目マスタへの追加が実装前提条件となる)
- `03_sys_params` にアラート送信先メールアドレスを管理するパラメータが必要か検討し、必要であればキー名を仕様書に明記する

**## 関連ドキュメント**(テーブル: 仕様書リンク | 関連箇所)

**## 人間が検討すべき事項**(TODO_future.md のF-35行から転記 + Phase 1調査で判明した追加事項。なければ「なし(即実装可)」)

### Step 2-3b: 実装プロンプト〜変更履歴の追記(File Edit または Bash, 〜250行)

以下の実装プロンプトを**行頭4スペースインデント・コードブロックなし**で出力すること。

    あなたはGAS会計システム(bizlp-gas-accounting)のシニア開発者です。
    案件 F-35「知的財産ポートフォリオ管理」の Step 1(データ基盤の新設)を実装してください。

    ## 実行前タスク
    - `000_infra/003_contracts.js` をRead: 既存 @typedef の記法・フィールドコメント形式・末尾行番号を確認
    - `000_infra/002_constants.js` をRead: ID_PREFIX_MAP と SHEET_DEFAULTS の要素型・既存エントリの末尾行番号を確認
    - `200_data/202_repository.js` をRead: OrderRepository の _getSheet/findAll/save/append パターンと、BudgetRepository の有無を確認
    - `100_config/101_sys_config.js` をRead: setupAllSchemas() のDDL記法・システムキー登録方法・onOpen() の実在メニュー名を確認

    ## 修正対象ファイル
    - `000_infra/003_contracts.js`(末尾に追記のみ)
    - `000_infra/002_constants.js`(ID_PREFIX_MAP と SHEET_DEFAULTS の配列末尾に追記のみ)
    - `200_data/202_repository.js`(末尾に追記のみ)
    - `100_config/101_sys_config.js`(setupAllSchemas() 内に追記のみ)

    ## 実装内容
    1. `003_contracts.js` 末尾に IntellectualPropertyDTO / IpCostDTO の @typedef を追加(Readで確認した既存記法に準拠)
    2. `002_constants.js` の ID_PREFIX_MAP 末尾に以下を追加:
       { pattern: '17_mst_intellectual', prefix: 'IP_', digit: 4, isDate: false }
       { pattern: '37_wrk_ip_cost', prefix: 'IPC_', digit: 4, isDate: true }
    3. `002_constants.js` の SHEET_DEFAULTS 末尾に新シート2件分のデフォルト値エントリを追加(Readで確認した要素型に準拠)
    4. `202_repository.js` 末尾に IntellectualPropertyRepository / IpCostRepository を追加(OrderRepository パターンを完全踏襲。_getSheet/findAll/save/append の4メソッド構成)
    5. `101_sys_config.js` の setupAllSchemas() に両シートのDDLスキーマを追加(Readで確認した作法に準拠。システムキーはPhase 1で確定した値を使用)

    ## 制約
    - 既存のRepository・DTO・定数定義は一切変更しない(追記のみ)
    - 列参照はヘッダー名ベース(indexOf)。列番号ハードコード禁止
    - メニュー名・定数名・シート名はReadで確認した実在する文字列のみ使用すること

    ## 動作確認
    1. npm run push:dev
    2. ReadしたonOpen()の実在メニュー名から「全シートのスキーマとUIを最新化(DDL)」相当の操作を実行
    3. 17_mst_intellectual_property と 37_wrk_ip_cost が作成され、ヘッダーが正しいことを確認
    4. 901_test_runner.js で既存テストが壊れていないことを確認

**※ Step 2 / Step 3 の実装プロンプトは同形式で仕様書内に続けて記載すること(Step 2: 408_rpa_ip_forecast.js の実装、Step 3: 409_rpa_ip_alert.js の実装)**

**## 推奨実行モデル**

| 工程 | 推奨モデル | 理由 |
|------|----------|------|
| Step 1: データ基盤の新設 | Sonnet | 既存パターン踏襲。挿入位置の特定と整合性確認が必要 |
| Step 2: 費用予測RPAの新設 | Sonnet | 複数Repository横断・冪等性ロジックの設計判断が必要 |
| Step 3: 期限アラートの新設 | Haiku | ロジックが単純。仕様で完全定義可能 |

**## 変更履歴**

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

### Step 2-4: 仕様書作成プロンプトの記録(File Edit または Bash、最重量・必ず独立Step)
以下の形式で末尾に追記する。`<instruction>` タグ内の本プロンプト全文をそのまま記録すること。

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

<details><summary>展開して表示</summary>

(この <instruction> 全文をここに記録)

</details>
```

---

## Phase 3: `_config.json` への追記・changelog更新・コミット

1. `docs/_config.json` をReadし、`nav` 配列の `§E.5 FP&A・レポーティング` または適切なセクションを確認する。
2. 既存エントリの最大番号+1で以下を追記する:
   `{ "file": "dev/dev_F-35_ip_portfolio.md", "title": "E.5.X F-35 知的財産ポートフォリオ管理" }`
3. JSONの構文破損がないことを確認する(例: `node -e "require('./docs/_config.json')" && echo OK`)。
4. `docs/_internal/changelog.md` の先頭行(ヘッダー直後)に追記:
   `| 2026-04-20 | [dev_F-35_ip_portfolio.md](dev_mas-035_ip_portfolio.md) | 初版作成。知財ポートフォリオ管理(2シート新設・Repository・費用予測RPA・期限アラート)|`
5. コミット&プッシュ:
   ```
   git add docs/dev/dev_F-35_ip_portfolio.md docs/_config.json docs/_internal/changelog.md
   git commit -m "docs: F-35 知的財産ポートフォリオ管理の開発仕様書を作成

   2シート新設(17_mst_intellectual_property/37_wrk_ip_cost)、Repository・DTO・費用予測RPA・期限アラートの設計を含む

   https://claude.ai/code/session_XXXXX"
   git push -u origin <現在のブランチ>
   ```

📌 取り込み時の注記 (2026-06-02 sub 復元)

本仕様書は旧 F-番号体系で作成され PR 未マージのまま孤立していたドラフトを、origin/docs/dev-* ブランチから内容無改変で復元し、案件ID のみ MAS 体系へ正規化したもの。status: Open(未実装)

⚠️ ファイル番号ドリフト: 本文「対象ファイル」が指す 600_report/610〜612_*.js は現行 main で 別機能に使用済み(610=投資分析/MAS-013・611=財務モデリング/MAS-010・612=採用sim/MAS-012)。 実装時にファイル番号の再割当が必要。