概要

項目
案件IDMAS-147
カテゴリ自動入力パイプライン
優先度P1 ★★★
ステータス仕様書完了 (v2)
バージョンv2 (Document AI + Gemini ハイブリッド)
前提案件MAS-215 (GCP プロジェクト整備・Document AI 有効化) / MAS-152 (電帳法リネーム、フォルダ運用統合先)
関連案件MAS-157 (写真 OCR)、MAS-150 (証憑→20番台マスタ)、MAS-171 (CC N:1 合算マッチ・Subset Sum 共通ヘルパー)
関連 ADRADR-0007 Gemini API を領収書解析に使用
対象ファイル (新規・主)500_import/504_invoice_importer.js / 400_domain/413_invoice_matcher.js / templates/invoice_hitl_sidebar.html
対象ファイル (改修)000_infra/001_env.js (DocAI プロセッサ ID 参照) / 000_infra/004_utils.js (Jaccard・Subset Sum) / appsscript.json (スコープ追加)
v2 改訂日2026-04-21
v1 資産feat/I-03-invoice-ocr-auto-posting ブランチに凍結 (基本起票 / 多ページ重複排除 / buildInvDtoFromOcr_ / 日付別 ID 採番)。v2 実装着手時に必要部分のみ cherry-pick 再利用

目的

顧客から受領した請求書 PDF を OCR + AI でパースし、既存の予算マスタ (20 番台タブ) と突合して 32 タブ WRK_INVC に自動起票する。責務分離の方針:

  • Document AI (Fact 抽出): T 番号・金額・日付・明細行座標など、税法上 1 円のブレも許されない確定値を機械学習確率モデル (0.0-1.0) で抽出
  • Gemini (Reasoning 推論): 真のベンダー推定 (Stripe 等の決済代行排除)・請求タイプ判定 (SUBSCRIPTION / USAGE_BASED / ONE_OFF)・請求構造判定 (SINGLE / BUNDLE / MULTI) などの意味的推論のみ

→ 誤マッチによるデータ汚染リスクをゼロに抑えつつ、Auto-Link 率 85% 超を実現。HitL 工数を月 60 分 → 月 7.5 分に削減 (月間 100 通想定)。

v1 (Gemini 単独 OCR) は「30 枚未満/月」の小規模運用では有効だが、bizlp の成長期には v2 ハイブリッドが妥当と MAS-306 で結論付けた。

現状のコード

既存 OCR 基盤 (MAS-157 で実装済、流用可能)

  • 500_import/502_receipt_reader.js: callGeminiForReceipt_() で領収書 PDF/画像を Gemini で OCR 抽出
  • GEMINI_API_KEY をスクリプトプロパティ経由で参照
  • generativelanguage.googleapis.com エンドポイント (MAS-216 で Vertex AI 移行予定)

既存の WRK_INVC (32 タブ) 構造

  • DDL 管理、100_config/101_sys_config.jsschemas.WRK_INVC で定義
  • T 番号カラム未搭載 → v2 で追加必須
  • 既存列: 請求ID / 取引先名 / 発生日 / 税込金額_計画 / 税抜金額_計画 / 消費税額_計画 / 請求ステータス / 等

既存の 12_mst_partner

  • T 番号カラム未搭載 → v2 で追加必須
  • MAS-120 (取引先マスタ拡張) で決済条件列は追加済。T 番号はインボイス対応で今回追加

v1 凍結資産 (feat/MAS-147-invoice-ocr-auto-posting ブランチ)

  • 基本起票関数の骨格
  • 多ページ PDF の重複排除ロジック
  • buildInvDtoFromOcr_() ヘルパー
  • 日付別 ID 採番 (既存パターン)

→ v2 でも再利用可能な部分は cherry-pick して取り込む。

修正方針

v1 からの継承 / 変更 / 廃止

項目ステータス理由
T 番号カラム追加・HitL サイドバー🟢 継承誤マッチ 0% を保証する絶対キー
多段 Pass / 1 円差許容🟢 継承Pass 0〜3, 5 のロジックと消費税誤差吸収は不変
OCR 抽出エンジン🟡 変更Gemini 単独 → DocAI (構造抽出) + Gemini (意味推論) ハイブリッド
非同期キュー バッチサイズ🟡 変更3〜5 件 → 1〜2 件 (DocAI 処理時間増のため)
確信度スコア🟡 変更LLM 主観スコア → DocAI の確率モデル (0.0-1.0) ベースの複合計算式
1:N (明細分割) マッチ (Pass 4)🟡 変更ハルシネーション懸念で「見送り」 → DocAI 明細信頼性を盾に「実装
ファイル保存・リネーム運用🔵 新規MAS-152 統合で月次サブフォルダ + 電帳法リネームをパイプライン化
Gemini JSON Schema 抽出🔴 廃止Gemini に金額/日付抽出させるプロンプト全廃、推論専用の軽量プロンプトへ

Step 1: DocAI インフラ + OAuth 権限設定 (W1)

1-A: GCP 側の Document AI 有効化

前提: MAS-215 (GCP プロジェクト整備) 完了。dev/prod 両プロジェクトで以下を実施。

  1. Google Cloud Console → 対象プロジェクトを選択
  2. 「API とサービス」→「ライブラリ」→「Document AI API」を有効化
  3. Document AI → プロセッサ作成:
    • タイプ: Invoice Parser (INVOICE_PROCESSOR)
    • リージョン: asia-northeast1 優先 (未提供時は us)
    • プロセッサ ID を控える
  4. スクリプトプロパティ DOCAI_PROCESSOR_ID_DEV / DOCAI_PROCESSOR_ID_PROD を両環境の GAS エディタに登録

1-B: 000_infra/001_env.js への Env メソッド追加

Env.vertexRegion() に倣って docaiProcessorId() / docaiLocation() を追加:

/** @returns {string} DocAI プロセッサ ID (環境別) */
docaiProcessorId: function () {
  var key = _load().isDev ? 'DOCAI_PROCESSOR_ID_DEV' : 'DOCAI_PROCESSOR_ID_PROD';
  return _getProps().getProperty(key) || '';
},
/** @returns {string} DocAI プロセッサのリージョン (未設定は asia-northeast1) */
docaiLocation: function () {
  return _getProps().getProperty('DOCAI_LOCATION') || 'asia-northeast1';
},

1-C: appsscript.json の OAuth スコープ追加 (失敗パターン #26 対応)

Document AI は https://www.googleapis.com/auth/cloud-platform が必須。既存の全スコープを完全列挙した上で追加する。

⚠️ 絶対禁止: 部分宣言 (新スコープだけ追加) は自動検出を OFF にし、既存の SpreadsheetApp / DriveApp / MailApp / Utils.auditLog を全て破壊する (failure_patterns #26)。

正しい手順:

  1. GAS エディタ → プロジェクト設定 → OAuth スコープ の現在値をすべてコピー
  2. appsscript.jsonoauthScopes 配列に元の全スコープを明示列挙
  3. 末尾に "https://www.googleapis.com/auth/cloud-platform" を追加

1-D: 500_import/504_invoice_importer.js の通信テスト関数

軽い確認用関数 testDocaiConnection() を追加:

  • 簡易 1 ページ PDF を DocAI に送信 → entities.length > 0 を検証
  • fieldMask=entities,text で必要項目のみ取得 (50MB 制限回避)

Step 2: 物理ファイル ルーティング基盤 (W1)

MAS-152 (電帳法リネーム) と統合し、処理済み PDF を月次サブフォルダに自動配置 + 電帳法準拠リネーム。

2-A: フォルダ階層設計

[受信箱ルート]/
  01_inbox/              ← 未処理 PDF の投入先
  02_processed/          ← 電帳法対応の保管庫
    請求書/
      2026-04/           ← 月次サブフォルダ (自動生成)
        20260421_..._税込_docNumber.pdf
      2026-05/
  03_hold_hitl/          ← HitL 保留 (未承認)
  99_error/              ← 抽出失敗 / 通貨違い等

月次サブフォルダ必須の理由: フラットな大フォルダは Drive API タイムアウトの原因になる。

2-B: リネーム規則

YYYYMMDD_取引先名_税込金額_docNumber.pdf

  • 電帳法検索要件を担保 (日付・相手方・金額の 3 要素)
  • 同名衝突時は _(1) _(2) を付与
  • 抽出失敗時は _UNKNOWN_{元ファイル名}.pdf (HitL 補正後に再リネーム)

2-C: 権限管理 (MAS-206 / MAS-201 連携)

  • 02_processed/ はシステム以外の編集・削除不可 (Drive 共有権限で「閲覧者」に絞る)
  • 電帳法 10 年保管ポリシー適用 (MAS-201 バックアップ対象)

2-D: ヘルパー関数

500_import/504_invoice_importer.js に追加:

  • routeInvoicePdf_(fileId, meta) — メタ情報を元に 02_processed/請求書/YYYY-MM/ に移動 + リネーム
  • resolveMonthlyFolder_(yyyymm) — 月次サブフォルダを getOrCreate

Step 3: ハイブリッド抽出パイプライン (W2)

DocAI パース → Gemini 推論 → 統合 JSON の流れを実装。

3-A: Document AI 標準エンティティ → WRK_INVC 対応表

DocAI エンティティ取得方針WRK_INVC / 活用先
supplier_name🤖 DocAI取引先名_OCR
supplier_tax_id🤖 DocAI (T 番号形式検証)T 番号 (新規列)
supplier_address🚫 破棄 (fieldMask で除外)-
supplier_website🤖 DocAIGemini 推論コンテキストへ
supplier_bank_account🤖 DocAI振込先 (HitL 表示)
supplier_payment_terms🤖 DocAI決済日_計画 補強
receiver_name🤖 DocAI (宛名検証)自社宛チェックフラグ
invoice_id🤖 DocAI請求書番号
invoice_date🤖 DocAI (和暦→西暦)発生日
due_date🤖 DocAI (欠損時 partner_terms 補完)決済日_計画
currency🤖 DocAI (JPY 検証)通貨エラーフラグ
total_amount🤖 DocAI (最重要、confidence アンカー)税込金額_計画
net_amount🤖 DocAI税抜金額_計画
total_tax_amount🤖 DocAI消費税額_計画
line_items[]🤖 DocAIPass 4 (1:N 分割) のソース
line_items/description🤖 DocAI摘要ファジーマッチキー
line_items/amount🤖 DocAI分割起票時の金額
tax_details[]🤖 DocAI税率混在検知
trueVendorName🧠 Gemini 推論真の取引先名 (Stripe 排除)
billingType🧠 Gemini 推論請求タイプ (SUBSCRIPTION/USAGE_BASED/ONE_OFF)
invoiceStructure🧠 Gemini 推論請求構造 (SINGLE_SVC/BUNDLE_SVC/MULTI_INDEP)
mainServiceSummary🧠 Gemini 推論摘要 (15 文字以内)

3-B: 500_import/504_invoice_importer.js の主要関数

  • callDocAiForInvoice_(pdfBlob) — DocAI Invoice Parser 呼び出し (fieldMask=entities,text)
  • callGeminiForInvoiceReasoning_(docAiResult) — Gemini に意味推論のみ依頼 (軽量プロンプト)
  • mergeDocAiAndGemini_(docAiResult, geminiResult) — 統合 JSON 生成

3-C: Gemini プロンプト設計 (推論専用)

あなたは会計士アシスタントです。以下の Document AI 抽出結果から
「真の提供者」「請求タイプ」「請求構造」「摘要 (15 文字)」のみを推論してください。
金額・日付・T 番号の抽出は禁止 (Document AI の確定値を上書きしてはいけません)。

入力:
{docAiJson}

出力 (JSON):
{
  "trueVendorName": "...",
  "billingType": "SUBSCRIPTION" | "USAGE_BASED" | "ONE_OFF",
  "invoiceStructure": "SINGLE_SVC" | "BUNDLE_SVC" | "MULTI_INDEP",
  "mainServiceSummary": "...",
  "confidenceScore": 0.0-1.0
}

3-D: 確信度スコア統合

const amtConf = docAi.total_amount.confidence;
const vndConf = docAi.supplier_tax_id
  ? docAi.supplier_tax_id.confidence
  : docAi.supplier_name.confidence;
const baseFactConf = Math.min(amtConf, vndConf); // 最弱リンク
const geminiConf = geminiOutput.confidenceScore;
const finalScore = (baseFactConf * 0.8) + (geminiConf * 0.2);

閾値:

  • HIGH (≥ 0.85): Auto-Link (バックグラウンド自動紐付)
  • MEDIUM (0.60〜0.84): HitL (サイドバーで 1 クリック承認)
  • LOW (< 0.60): OCR エラー警告、手動補正

即死ルール (即 LOW に落とす):

  • total_amount.confidence < 0.80
  • currency != JPY

Step 4: マッチングエンジン + HitL サイドバー実装 (W3-W4)

4-A: 多段 Pass マッチング (Pass 0〜6)

400_domain/413_invoice_matcher.js (新規) に実装:

Pass条件確度処理
Pass 0T 番号完全一致 + 金額完全一致 (許容 ±0 円)最高Auto-Link
Pass 1T 番号完全一致 + 金額 ±1 円 (消費税端数吸収)Auto-Link if HIGH
Pass 2取引先名完全一致 + 金額完全一致Auto-Link if HIGH
Pass 3取引先名完全一致 + 金額 N:1 合算マッチ (Subset Sum)HitL 候補提示
Pass 41:N 分割マッチ (line_items.description × 予算 品目名 Jaccard ≥ 0.7)HitL 候補提示
Pass 5取引先ファジーマッチ (004_utils.js の正規化 + Levenshtein)HitL 候補提示
Pass 6新規予算登録推奨 (MAS-150 連携)最低20 番台マスタ追加提案

Pass 3 Subset Sum: MAS-171 CC N:1 合算マッチ の共通ヘルパーを 000_infra/004_utils.js に統合 (重複実装を避ける)。

4-B: DDL 拡張 (T 番号カラム追加)

100_config/101_sys_config.js で以下を変更:

  • schemas.MST_PARTNER.headers 末尾に "T番号" を追加
  • schemas.WRK_INVC.headers の適切位置に "T番号" を追加
  • setupAllSchemas() 実行で既存シートに列追加 (既存データの T 番号列は空欄、別途マイグレーション or 手動投入)

既存取引先のマイグレーション: I-28 法人番号自動取得 (国税庁 Web-API) と連携、本案件では DDL 列追加までが範囲。

4-C: 32_wrk_invoice への書込み

  • 確信度 HIGH → 新規 INV レコード作成、請求ステータス=処理中自動仕訳JNL_ID=null (Action A 待ち)
  • 確信度 MEDIUM → 確認FLG=FALSE (HitL 保留扱い)、サイドバーで承認

4-D: HitL サイドバー (templates/invoice_hitl_sidebar.html)

UI 要素:

  1. PDF プレビュー (左ペイン): DriveApp.getFileById(id).getBlob() の iframe 埋込
  2. 抽出結果パネル (右上): Document AI の各フィールド + 確信度バー
  3. マッチング候補 (右中): Pass 2〜5 の候補を優先度順で 3 件提示
  4. アクションボタン (右下):
    • 承認 (候補の 1 つを選択)
    • ✏️ オーバーライド (値を手動修正)
    • 🗑️ スキップ (99_error/ に移動)
    • 新規予算登録 (MAS-150 連携ダイアログ)

承認フロー:

  1. 02_processed/請求書/YYYY-MM/ に移動 + 電帳法リネーム (Step 2)
  2. 32_wrk_invoice に書込み + 確認FLG=TRUE
  3. Utils.auditLog('APPROVE', '32_wrk_invoice', invId, ...) 記録
  4. Action A 待ち状態へ (既存ワークフローに合流)

4-E: 非同期キューイング (処理順序制御)

  • 03_hold_hitl/ にある PDF を 1 バッチ 1〜2 件ずつ処理 (DocAI + Gemini で 10〜15 秒/件)
  • GAS 時間トリガー (5 分間隔) で runInvoiceBatch_() 実行
  • 6 分実行時間制限を超えないよう 1 件毎に LockService で排他制御

影響範囲

対象ファイル変更量既存動作への影響
新規 インポーター500_import/504_invoice_importer.js約 400 行新規なし (新規ファイル)
新規 マッチャー400_domain/413_invoice_matcher.js約 300 行新規なし (新規ファイル)
新規 HitL UItemplates/invoice_hitl_sidebar.html約 200 行新規なし (新規ファイル)
Env モジュール拡張000_infra/001_env.js約 10 行追加既存 Env.xxx メソッドは変更なし
Utils 拡張000_infra/004_utils.jsJaccard / Subset Sum 追加 約 80 行MAS-171 と共通化、既存関数は変更なし
DDL 変更100_config/101_sys_config.js (schemas.MST_PARTNER / WRK_INVC)各 1 列追加setupAllSchemas() 再実行で既存シートに列追加
appsscript.jsonOAuth スコープに cloud-platform 追加1 行追加既存全スコープの完全列挙が必須 (failure_patterns #26)
MENU_DEFINITIONConstants.MENU_DEFINITION に「📥 請求書 PDF 取込」追加1 項目既存メニュー変更なし
新 OAuth スコープcloud-platform有効化ユーザー再認証が必要

注意事項

  1. OAuth スコープ崩壊を絶対に避ける (failure_patterns #26): appsscript.jsonoauthScopes を変更する際は、既存の全スコープを完全列挙してから新スコープを追加する。部分追加は全機能崩壊を招く
  2. Document AI の 50MB レスポンス制限: fieldMask=entities,text でレスポンスを必要最小限に絞る
  3. DocAI 処理時間 10〜15 秒/件: バッチサイズを 1〜2 件に抑え、6 分実行時間制限内に収める
  4. Gemini に金額・日付・T 番号を抽出させない: 推論専用プロンプトでこれらを禁止 (DocAI の確定値を上書きしてはいけない)
  5. 即死ルール: total_amount.confidence < 0.80 または currency != JPY は強制 LOW に落とす
  6. T 番号カラムの DDL 追加: setupAllSchemas 実行で既存シートに列追加。既存行の T 番号データは別途 MAS-170 (法人番号 API 連携) で投入
  7. 月次サブフォルダの自動生成: フラットフォルダは API タイムアウトの原因。必ず 02_processed/請求書/YYYY-MM/ で分離
  8. Gemini の Vertex AI 移行: MAS-216 完了後は Gemini 推論も Vertex AI 経由に移行。現時点は generativelanguage.googleapis.com で並行稼働可

エッジケース

条件挙動対策
多ページ PDF (3 ページ以上)DocAI タイムアウトリスク最初の 2 ページのみを DocAI に送信 (総額・サマリは先頭に集中)
外貨 (USD/EUR 等)誤読リスクcurrency != JPY で即 LOW に落とし HitL で警告
手書き領収書DocAI 精度低下docType 判定で確信度低ければ Gemini 直接入力 (v1 フォールバック)
T 番号欠損信頼性低下supplier_name の confidence で代替、MEDIUM ゾーンへ
複数請求書 1 PDFDocAI が正しく分割しないリスク1 ファイル 1 請求書の運用を徹底、HitL で手動分割
SUM(line_items) != total_amount割引・送料の分離等1:N 探索を放棄し BUNDLE_SVC として HitL 手動分割
軽減税率混在8% / 10% 混在時の税額計算ブレtax_details で複数税率検知、HitL で警告
同名ファイル衝突電帳法リネーム時に衝突_(1) _(2) サフィックス付与
DocAI プロセッサ ID 未設定docaiProcessorId() が空文字graceful degradation で 99_error/ 直行 + ログ
Drive フォルダ存在しない保存先欠落getOrCreate で動的生成
非同期キューの多重起動同一 PDF の二重処理LockService で排他制御
Gemini JSON パース失敗推論フィールド欠損invoiceStructure を SINGLE_SVC に fallback、HitL 候補提示のみ
確信度 HIGH でも新規取引先T 番号一致なしPass 6 で新規予算登録推奨ダイアログ (MAS-150 連携)

実データ検証

実装前に以下を確認:

  1. Document AI プロセッサ作成: dev プロジェクトで Invoice Parser を作成、プロセッサ ID 取得
  2. 既存請求書 PDF サンプル (10 件程度) で DocAI 抽出精度検証
  3. T 番号付き請求書T 番号なし請求書 の両方で確信度スコアが期待値通りか確認
  4. 外貨請求書 で即死ルールが発動するか (強制 LOW) 検証
  5. 多ページ請求書 (2〜5 ページ) でタイムアウト挙動を確認
  6. line_items の抽出精度 (物理座標ベースでハルシネーションなし) を確認
  7. 12_mst_partner.T番号 カラムの命名規則確認 (既存 MAS-120 の列と整合)
  8. Env.docaiProcessorId() の戻り値が正しい (未設定時は空文字)

関連ドキュメント

ドキュメント関連箇所
ADR-0007 Gemini API を領収書解析に使用する判断MAS-147 の OCR 戦略の前提
ADR-0008 本番 AI API を Vertex AI に集約MAS-216 完了後の Gemini 呼び出しを Vertex 経由に切替
MAS-215 GCP プロジェクト整備Document AI 有効化の前提
MAS-152 電帳法リネームStep 2 フォルダ運用の統合先
MAS-157 写真 OCROCR 基盤の流用元
MAS-171 CC 明細 N:1 合算マッチPass 3 Subset Sum の共通ヘルパー
MAS-150 証憑取込→20番台マスタPass 6 新規予算登録の連携先
MAS-306 設計検討 Gemini Deep Think 結果v2 の根拠となる設計結果
failure_patterns #26 OAuth スコープ崩壊Step 1-C の必須対応

人間が検討すべき事項

  1. DocAI プロセッサのリージョン: asia-northeast1 優先だが、Invoice Parser が未提供の場合は us リージョン + データ residency の考慮
  2. Gemini → Vertex AI 移行のタイミング: MAS-216 完了前に MAS-147 実装を始める場合、先に generativelanguage.googleapis.com で開発 → MAS-216 完了時に {region}-aiplatform.googleapis.com にエンドポイント切替
  3. T 番号未登録の取引先の扱い: 自動起票時に HitL で警告するか、Pass 6 で新規予算登録を推奨するか
  4. 1:N 分割マッチの閾値: Jaccard 0.7 は仮置き。実データで検証してチューニング
  5. 非同期キューのバッチサイズ: 1〜2 件が推奨だが、将来 DocAI の処理時間が改善されれば 3〜5 件に戻すか
  6. Auto-Link の閾値 (HIGH = 0.85): 保守的な数値。誤マッチ 0 件を優先するなら 0.90 に引き上げも検討
  7. 新規予算登録の自動化 (MAS-150 連携): Pass 6 で新規取引先を検知した際、20 番台マスタへの自動追加を Human-in-the-Loop 承認付きでやるか、運用者手動に委ねるか
  8. 電帳法対応範囲: MAS-152 と統合するが、請求書以外 (領収書・契約書等) の保管フォルダも同じ階層ポリシーにするか
  9. HitL サイドバーのデスクトップ幅: PDF プレビュー + 候補提示で横幅を広く取る必要あり (Google Sheets の標準サイドバー 300px では不足の可能性)
  10. 失敗時のリトライ戦略: DocAI 5xx エラー時の指数バックオフ、Gemini タイムアウト時の Gemini 単独 fallback

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

あなたは GAS 会計システム (bizlp-gas-accounting) のシニア開発者です。
案件 MAS-147「請求書 PDF → INV 自動起票 (v2 Document AI ハイブリッド)」を実装してください。
v2 設計の根拠は MAS-306 結果 (docs/_internal/research_prompts/RQ-008_I-03_matching_design_result.md) 参照。

## 実行前タスク
1. docs/dev/dev_mas-147_invoice_ocr_auto_posting.md を Read して v2 仕様を全把握
2. docs/_internal/failure_patterns.md #26 (OAuth スコープ崩壊) を必ず確認
3. 既存 OCR 基盤 `500_import/502_receipt_reader.js` を Read して OCR パターンを把握
4. `100_config/101_sys_config.js` の schemas.MST_PARTNER / WRK_INVC の現状列構造を Read
5. `000_infra/001_env.js` の Env オブジェクトの拡張パターンを把握
6. `docs/dev/dev_mas-171_cc_combo_matching.md` の Subset Sum ロジックを確認 (共通化対象)
7. dev GCP プロジェクトで Document AI プロセッサを手動作成し、プロセッサ ID を取得済であることを確認
8. スクリプトプロパティ `DOCAI_PROCESSOR_ID_DEV` / `DOCAI_LOCATION` が dev GAS に登録済であることを確認
9. v1 凍結ブランチ feat/MAS-147-invoice-ocr-auto-posting から再利用可能な部分 (多ページ重複排除 / buildInvDtoFromOcr_) を cherry-pick 候補として特定

## 修正対象ファイル
- 新規: 500_import/504_invoice_importer.js (約 400 行)
- 新規: 400_domain/413_invoice_matcher.js (約 300 行)
- 新規: templates/invoice_hitl_sidebar.html (約 200 行)
- 改修: 000_infra/001_env.js (約 10 行追加、docaiProcessorId() / docaiLocation())
- 改修: 000_infra/004_utils.js (Jaccard + Subset Sum 追加)
- 改修: 100_config/101_sys_config.js (schemas.MST_PARTNER / WRK_INVC に T 番号列追加)
- 改修: appsscript.json (OAuth cloud-platform スコープ追加、既存全スコープ完全列挙)
- 改修: 000_infra/002_constants.js (MENU_DEFINITION に「📥 請求書 PDF 取込」追加)

## 実装順序 (Step 1-4)
### Step 1: DocAI インフラ + OAuth 権限設定
- Env モジュールに docaiProcessorId / docaiLocation 追加
- appsscript.json の OAuth スコープ更新 (既存全スコープ完全列挙 + cloud-platform)
- testDocaiConnection() でサンプル PDF 通信テスト

### Step 2: 物理ファイル ルーティング基盤
- routeInvoicePdf_() / resolveMonthlyFolder_() 実装
- フォルダ階層 01_inbox → 02_processed/請求書/YYYY-MM/ → 03_hold_hitl → 99_error
- 電帳法リネーム YYYYMMDD_取引先名_税込金額_docNumber.pdf

### Step 3: ハイブリッド抽出パイプライン
- callDocAiForInvoice_() で DocAI Invoice Parser 呼び出し (fieldMask=entities,text)
- callGeminiForInvoiceReasoning_() で意味推論のみ取得 (金額/日付抽出は禁止)
- mergeDocAiAndGemini_() で統合 JSON 生成
- 複合確信度スコア計算 (baseFactConf × 0.8 + geminiConf × 0.2)
- 即死ルール (total_amount.confidence < 0.80 or currency != JPY) で強制 LOW

### Step 4: マッチングエンジン + HitL サイドバー
- 413_invoice_matcher.js に Pass 0〜6 実装
- schemas.MST_PARTNER / WRK_INVC に T 番号列追加 + setupAllSchemas 動作確認
- invoice_hitl_sidebar.html で PDF プレビュー + 候補提示 + 承認/オーバーライド/スキップ
- runInvoiceBatch_() で 1〜2 件バッチ処理、LockService で排他、時間トリガー 5 分間隔

## 制約
- appsscript.json の OAuth スコープを変更する際は failure_patterns #26 の手順を必ず守る (既存全スコープを完全列挙してから cloud-platform を追加)
- Gemini に金額/日付/T 番号の抽出を依頼しない (DocAI の確定値を上書きしない)
- fieldMask=entities,text を必ず付けて 50MB レスポンス制限を回避
- MAS-171 の Subset Sum と共通化するため、Pass 3 のロジックは 004_utils.js に切り出す
- 確信度の即死ルールを厳密に守る
- 既存コード (502_receipt_reader.js / BudgetRepository / PartnerRepository 等) のパターンを踏襲

## エッジケース
- 多ページ PDF (3 ページ以上) → 最初の 2 ページのみ DocAI
- currency != JPY → 強制 LOW、HitL 警告
- 手書き領収書 → Gemini 直接入力にフォールバック
- T 番号欠損 → supplier_name confidence で代替
- DocAI プロセッサ ID 未設定 → 99_error/ 直行 + ログ

## 動作確認
1. npm run push:dev でデプロイ
2. testDocaiConnection() で DocAI 通信 OK 確認
3. setupAllSchemas() で T 番号列追加を確認
4. サンプル請求書 PDF を 01_inbox/ に投入
5. runInvoiceBatch_() 手動実行 → Pass 0/1 の Auto-Link が動作するか
6. T 番号欠損 PDF で HitL サイドバー表示確認
7. 外貨 PDF で 99_error/ 直行確認

### 拡張思考の使用状況
| フェーズ | 拡張思考 | 備考 |
|---|---|---|
| 実行前タスク (Read) | あり | v2 仕様の全貌把握 + OAuth 崩壊回避策 |
| Step 1 DocAI 基盤 | あり | OAuth スコープ列挙の完全性確保 |
| Step 2 ルーティング | なし | 仕様書通りの実装 |
| Step 3 抽出パイプライン | あり | Gemini プロンプト設計で精度調整 |
| Step 4 マッチング + HitL | あり | Pass 順序 + 確信度閾値の動作検証 |

推奨実行モデル

工程推奨モデル理由
Step 1 (DocAI インフラ + OAuth)Claude Opus 4.7failure_patterns #26 対応で OAuth 全スコープ列挙の判断が必要
Step 2 (ルーティング基盤)Claude Sonnet 4.6既存パターン拡張、中程度の判断
Step 3 (ハイブリッド抽出)Claude Opus 4.7DocAI + Gemini 統合ロジック、複合確信度計算、プロンプト設計
Step 4 (マッチングエンジン + HitL)Claude Opus 4.7多段 Pass 設計、MAS-171 共通化、HitL UX 設計
動作確認Claude Haiku 4.5手順実行のみ

変更履歴

日付変更内容
2026-04-17v1 初版作成 (Gemini 単独 OCR 前提、4 Step 実装)
2026-04-21v2 全面改訂: Gemini 単独 → Document AI + Gemini ハイブリッドに全面書き直し。責務分離 (Fact = DocAI / Reasoning = Gemini)、T 番号カラム必須化、多段 Pass 0〜6、複合確信度スコア (baseFactConf × 0.8 + geminiConf × 0.2) と即死ルール、1:N 分割マッチ実装格上げ、フォルダ分離・電帳法リネーム運用 (MAS-152 統合)、非同期キュー 1〜2 件化、採否判断マトリクス (30 枚/200 枚/1000 枚)。前提案件に MAS-215 / MAS-152 を追加。MAS-171 の Subset Sum 共通化方針を明記。v1 資産 (feat/MAS-147-invoice-ocr-auto-posting ブランチ) は凍結、v2 で必要部分のみ cherry-pick 再利用。MAS-306 Gemini Deep Think 結果が根拠