• Status: Accepted
  • Mode: Standard
  • Kruchten Type: Executive/Property
  • Scope: platform
  • Implementation Status: Phase 1-2 Done (PR #957 Phase 1, PR #968 Phase 2a, PR #972 Phase 2b, PR #974 Phase 2c — Lock 統合 + Turborepo 2.x + turbo.json + CI pnpm 移行 + syncpack + Catalogs 完了; Phase 3 (packages/types + packages/engines + sync-engines 廃止) は将来別 ADR)
  • 起案者: [email protected]
  • 起案日時 (JST): 2026-05-25 13:23
  • 承認日時 (JST): 2026-05-26
  • Deciders: [email protected] (単独)
  • Pipeline Validation: 2026-05-25, 47/50 (Standard 閾値 40 超過, Critical 閾値 45 超過)

1. コンテキスト

1.1 背景 (Background)

bizlp-gas-accounting リポジトリは、GAS 本体 (root) と 4 サブプロジェクト (webapp_client, drp, docs-search-worker, docs/) が混在する準 monorepo 状態にあり、依存管理・build orchestration・型同期の各所で構造的負債が顕在化している。Jr 入社 (2026-10 予定) を控え、AI agent (Claude Code) 主体の個人開発体制で持続可能な構造への移行が必要となった。

1.2 現状 (Current State / As-Is)

  • npm (root) と pnpm (サブプロジェクト) が並存し、各サブプロジェクトが独立 lock ファイルを保持
  • root に pnpm-workspace.yaml が存在するが、内容は allowBuilds: fsevents: set this to true or false というプレースホルダのみ
  • root の npm run build:spa で webapp_client をビルドする手動 orchestration
  • sync-engines.mjs によるファイルコピーベースの型同期 (sidebar_api.d.ts 等) が CI 非統合

1.3 課題 (Problem)

  1. 依存管理の破綻予兆: npm / pnpm 並存と独立 lock ファイルにより phantom dependency のリスクが各所に潜在
  2. 手動 build orchestrator の拡張性限界: サブプロジェクト増加に伴い手動 orchestration が破綻寸前
  3. 脆弱な SSoT 同期: sync-engines.mjs のファイルコピーベース型同期は CI 非統合でドリフト検知が属人的
  4. 壊れた pnpm-workspace.yaml: プレースホルダのまま放置され workspace 設定が未構成
  5. AI agent 探索効率の最適化要請: Claude Code が主要開発ツールである本プロジェクトでは、monorepo 構造の明確化が AI agent のファイル探索・コンテキスト理解効率に直結する (探索パス判断ミスがトークン浪費・誤修正に繋がる)

1.4 制約・要件 (Constraints & Requirements)

  • GAS 本体 (root) は clasp 3.x の rootDir 制約があり、安易なディレクトリ移動は .clasp.json / 全スクリプトパス破壊に直結
  • 個人開発 + AI agent 主体 (Jr 入社 2026-10 予定) のため、学習コスト・運用負荷を最小化する必要
  • 既存 CI (GitHub Actions) との互換性維持が必須

1.5 目標 (Goals / To-Be)

  • pnpm workspaces + Turborepo + Catalogs による依存管理・build orchestration・型共有の構造的統合
  • Phase 1 では root (GAS) を workspace から除外しつつ、3 サブプロジェクトを統一管理する段階的移行の起点を確立
  • Non-Goals: Phase 1 時点での root (GAS) workspace 包含、sync-engines.mjs の即時廃止、Phase 3 完了形の確定

2. 決定

RQ-053 Synthesis (3 LLM 並列調査 + MCDA 加重和評価) の結果に基づき、案 C (GPT 段階的移行) を採択 (MCDA 加重和 0.927/1.0、最高スコア)。pnpm 10.x + pnpm workspaces (Catalogs catalogMode: strict) + Turborepo 2.x + TypeScript Project References + Vercel Remote Cache + syncpack + GitHub Actions (pnpm/action-setup@v4 + turbo run --affected) を tooling stack とする。Phase 1 では root を workspace に含めず 3 サブプロジェクト (webapp_client, drp, docs-search-worker) のみを対象とし、Phase 2 で lock 統合 + Turborepo 導入、Phase 3 で packages/types/ + packages/engines/ の共有 packaging を実施する。Root 包含可否は Phase 3 でデータドリブンに再判断する。

3. 判断基準 (Decision Drivers)

3.1 評価軸 (Q42 9 タグから選定)

#重要度 (係数)案件特有の解釈
1#maintainable[Must] (×2.0)AI agent / Jr が 6 ヶ月後に構造を再現できるか
2#suitable[Must] (×2.0)既存接続 (sync-engines.mjs, sidebar_api.d.ts) + CLAUDE.md / ADR-0019 との整合性
3#operableHigh (×1.0)実装コスト (Claude Code セッション数)
4#usableMedium (×0.5)Jr オンボーディング学習コスト

K.O. criterion: Must 軸の score < 3 は不採用 (機能要件未充足)。

係数設定根拠: Must (×2.0) は「欠如すると運用不能」な軸、High (×1.0) はベースライン、Medium (×0.5) は「あると良い」軸。ADR-0050 §4.2 の標準係数体系に準拠。#secure / #reliable / #efficient / #flexible / #safe は本件の build infrastructure 選定には直接影響しないため省略 (Q42 公式テンプレートで 5 軸選定が標準)。

3.2 評価軸 x 案スコア表

係数案 C (採択)案 A案 B
#maintainable [Must]×2.0545
#suitable [Must]×2.0553
#operable High×1.0452
#usable Medium×0.5445
加重和 (正規化, max 27.5)0.9270.8360.673
K.O. 通過 (Must >=3)passpasspass

加重和は絶対判定ではなく K.O. 通過候補のタイブレーク用 (Suhr 1999 CBA criterion 準拠)。

4. 検討した代替案 (Alternatives Considered)

  • 案 A (Claude 同梱型): GAS root + サブを同一 workspace に即時包含 -- 不採用理由: GAS が root にある状態で workspace に含めると、AI agent が GAS コードと orchestrator コードを混同する探索効率劣化 (#maintainable=4 vs 案 C の 5: 案 C は Phase 3 まで GAS を workspace 外に置くことで AI agent の探索スコープを明確に分離)。clasp rootDir とワークスペース境界の衝突リスク。MCDA 加重和 0.836/1.0
  • 案 B (Gemini 分離型): GAS を apps/gas-core/ に移動 -- 不採用理由: GAS ディレクトリ移動が破壊的 (.clasp.json / 全スクリプトパス書換え = mega 工数)。#operable=2 で K.O. ぎりぎり。個人開発では ROI が成立しない。MCDA 加重和 0.673/1.0
  • 案 D (現状維持): 不採用理由: 壊れた pnpm-workspace.yaml の放置、sync-engines.mjs のドリフトリスク増大、サブプロジェクト追加時の手動 orchestration 限界が近い

4.1 Tooling Stack (3 モデル合意ベース)

Layer採用根拠
Package managerpnpm 10.x3 モデル合意 (phantom dep 防止、Catalogs、content-addressable store)
Workspacepnpm workspaces + Catalogs (catalogMode: strict)Claude / Gemini 合意 + GPT 明示支持。Catalogs でバージョンドリフトを構造的に防止
Build orchestratorTurborepo 2.x3 モデル合意 (Nx は個人開発に overkill、Vercel Remote Cache 2024-12-22 無料化済)
共有型管理TypeScript Project References + workspace:*3 モデル合意 (path aliases 非推奨、TypeScript 公式推奨)
Remote cacheVercel Remote Cache (無料)Claude / GPT 合意、CI <-> local cache 共有を個人開発でも実現。データガバナンス注記: Vercel の DPA (Data Processing Agreement) を確認済、ソースコードはキャッシュされない (ビルド成果物のみ)。rate limit は個人開発規模では問題にならないが、CI 並列度増加時は self-hosted cache (turborepo-remote-cache OSS) にフォールバック可能
Dep drift 監視syncpack + pnpm catalog: enforcementClaude 推奨、Gemini も Catalogs 推奨 (実質合意)
CIGitHub Actions + pnpm/action-setup@v4 + turbo run --affected3 モデル合意

4.2 Root 包含戦略: 段階的 (案 C)

  • Phase 1 (本 ADR スコープ): Root を pnpm-workspace.yaml に含めないpackages: ['webapp_client', 'drp', 'docs-search-worker'] -- workspace は 3 サブプロジェクトのみ
  • Phase 2: Lock 統合 (各サブの package-lock.json / pnpm-lock.yaml 削除 -> pnpm import -> 統一 pnpm-lock.yaml)。Turborepo 導入、root npm run build:spaturbo run build --filter=webapp_client に置換
  • Phase 3: 共有 packaging。packages/types/ (sidebar_api.d.ts 移設) + packages/engines/ (400_domain 抽出、sync-engines.mjs 廃止)。Root 包含可否は Phase 3 でデータドリブンに再判断 (現時点では確定しない)。GAS bundling 戦略: GAS は標準で Node.js モジュール解決をサポートしないため、共有パッケージを GAS 側で利用するには esbuild / rollup 等のバンドラ導入が前提。Phase 3 計画時に bundler 選定 ADR を別途起案する

4.3 壊れた pnpm-workspace.yaml の処置

Phase 1 開始時に現在の無効なプレースホルダを削除し、正しい workspace 設定で再作成。allowBuilds (pnpm v10+ 機能) は初期省略、必要時 pnpm approve-builds で選択的承認。

5. 影響 (Consequences)

5.1 正の影響 (Good)

  • 依存管理統一: pnpm Catalogs + syncpack でバージョンドリフトが構造的に不可能に
  • AI agent 探索効率: monorepo 構造の明確化で Claude Code の探索パス判断精度が向上、トークン消費削減
  • CI 高速化: Turborepo + Vercel Remote Cache で変更影響範囲のみビルド (--affected)
  • build orchestration 自動化: turbo run build で依存グラフベースの自動実行 (手動 npm run build:spa 廃止)
  • 型安全の向上: TypeScript Project References + workspace:* でコンパイル時型チェック (sync-engines.mjs のファイルコピー廃止)

5.2 負の影響 (Bad)

  • 移行工数: 3 Phase 合計で ~15-20h Claude Code セッション (Phase 1 ~1h / Phase 2 ~4-6h / Phase 3 ~10-13h; 1.5x バッファ込み)
  • pnpm 学習コスト: npm から pnpm への移行で、Jr (2026-10 入社) に追加学習負荷。ただし業界標準ツールのため長期的にはプラス
  • Turborepo 運用知識: turbo.json のタスクグラフ定義、cache 設定の理解が必要

5.3 中立・トレードオフ (Neutral / Trade-offs)

  • Phase 3 で root (GAS) 包含可否を実データに基づき再判断 -- 現時点で確定しないことが「適切な不確定性」

5.4 影響範囲

Phase 1Phase 2Phase 3
ファイルroot pnpm-workspace.yaml全サブ lock ファイル + turbo.json + CI workflowspackages/ 新規 + import パス書換え
モジュールなし (GAS コード影響ゼロ)root package.json scriptswebapp_client / decision-pipeline imports
データなしなしなし
ステークホルダーAI agent (探索パス変更なし)AI agent + CIAI agent + CI + Jr (2026-10 入社後)

5.5 コスト試算

項目Phase 1Phase 2Phase 3合計
Claude Code セッション~1h~4-6h~10-13h~15-20h
人間レビュー~15 min~30 min~1h~2h
CI 設定変更なし~1h~1h~2h
月次運用コスト (移行後)------~2h/年 (syncpack check + turbo cache 監視)

Phase 1 -> Phase 2 間隔は最低 1 週間 (Phase 1 安定性確認: CI green 連続 5 日以上)。Phase 2 -> Phase 3 間隔は最低 1 ヶ月 (Phase 2 安定性 + KPI baseline 取得: CI green 連続 2 週間 + incident 0 件)。

6. 運用上の罠・後任がハマりそうな落とし穴

  1. clasp rootDir との衝突: pnpm workspace に root を含めると、node_modules/.pnpm 構造と clasp の rootDir: '.' が干渉する可能性。Phase 1 で root を除外するのはこのリスク回避が主目的の一つ
  2. pnpm Catalogs の strict mode 罠: catalogMode: strict では workspace 内の全 package.json で catalog に定義されていない依存を追加するとエラー。新規依存追加時は必ず pnpm-workspace.yamlcatalog: セクションに先に追加する運用が必要。Phase 1 完了時に CLAUDE.md に依存追加手順を明記する
  3. Turborepo cache invalidation: turbo.jsoninputs / outputs 定義が不正確だと stale cache が残り、ビルド結果が古い。Phase 1-2 期間中は GAS (workspace 外) から webapp_client (workspace 内) への型同期が Turborepo の依存グラフ外となるため、cache invalidation 不能で誤ビルドリスクが残る。対策: sync-engines.mjs 実行後に turbo run build --force を明示的に実行する CI step を追加
  4. lock ファイル統合時の依存解決: Phase 2 で pnpm import を実行する際、npm lock と pnpm lock の依存解決差異で一部パッケージの version が変わる可能性。統合前に npm ls --all / pnpm ls --depth Infinity の diff を取って検証する
  5. Vercel Remote Cache の rate limit: 無料プランの rate limit を事前確認。個人開発規模では問題にならないが、CI 並列度が上がると hit する可能性。フォールバック: turborepo-remote-cache (OSS self-hosted)
  6. Phase 3 の sync-engines.mjs 廃止タイミング: 新しい packages/engines/ が完全に動作確認できるまで sync-engines.mjs を残す (並行運用期間を設ける)。一括廃止は rollback 困難
  7. Phase 3 の GAS bundling: GAS は CommonJS 風で TypeScript Project References の output をそのまま import できない。packages/engines/ を GAS 側で利用するにはバンドラ (esbuild 等) の導入・設定が必須。Phase 3 着手前に bundler 選定 ADR を別途起案する

7. 撤退条件 (Rollback Plan)

各 Phase に独立した rollback 経路を設計し、Phase 間の依存を最小化:

Phase撤退手順想定所要時間影響範囲
Phase 1pnpm-workspace.yaml 削除のみで即時完全復旧~5 分workspace 設定のみ (GAS / サブプロジェクト挙動影響なし)
Phase 2git revert + 各サブプロジェクト pnpm install 再実行~30 分lock ファイル + CI 設定
Phase 3Phase 2 完了時に必ず git tag monorepo-phase-2-stable を打つ。Phase 3 着手後の問題発生時はこの tag に復元~1hpackages/ + import パス
  • 6 ヶ月後 KPI (下記 Confirmation) 達成不可: Phase 計画を見直し (Phase 間隔延長、scope 縮小、或いは tooling stack の部分変更) を検討。Phase 2 状態が安定している場合は Phase 2 で留まる選択肢を優先

8. Confirmation (準拠確認 / Fitness Function)

8.1 検証可能な完了条件 (6 ヶ月後 KPI)

3 LLM KPI 提案を統合。6 ヶ月後 (2026-11 頃) に評価:

KPI測定方法成功閾値
pnpm install 全 workspace 時間CI ログ<=90 sec (cold)
Turbo cache hit rateturbo run build --summarize JSON>=60%
共有依存バージョンドリフト数syncpack list-mismatches 週次 CI0 件
Cross-package PR 比率GitHub label / git diff>=30%/月
Claude Code 探索パス修正回数grep -c "wrong directory" ~/.claude/projects/*/memory/*.md + Claude Code session ログの re-navigation 回数50% 削減 (移行前 baseline を Phase 1 着手前に 2 週間計測)
GAS runtime 'unexpected module' エラーStackdriver ログ0 件
依存コンフリクト incident 数PR カウント0 件維持

8.2 Phase 別 中間 checkpoint

Phase安定性判定基準最低期間
Phase 1 -> Phase 2CI green 連続 5 日以上 + pnpm install 全 workspace 成功 + GAS runtime エラー 0 件1 週間
Phase 2 -> Phase 3CI green 連続 2 週間 + incident 0 件 + turbo run build 全プロジェクト成功 + Remote Cache 接続確認1 ヶ月
  • Phase 1 完了条件: pnpm-workspace.yaml が valid、pnpm install が全 workspace で成功、既存 CI が green
  • Phase 2 完了条件: 統一 lock ファイル、turbo run build が全プロジェクトで成功、Remote Cache 接続確認
  • Phase 3 完了条件: sync-engines.mjs 廃止、TypeScript Project References で型チェック通過、全 import パス書換え完了

8.3 Fitness Function 3 要素

  • 検証手段:
    • 週次 CI に syncpack list-mismatches を組み込み、ドリフト 0 件を gate 化
    • turbo run build --summarize の JSON output を CI artifact として保存、cache hit rate を月次集計
    • pnpm install 時間を CI ログから抽出し閾値超過時に warning
    • GAS Stackdriver で unexpected module エラーをアラート設定
  • 実行頻度: 週次 (CI 自動), 月次 (KPI 集計), 6 ヶ月後 (総合 KPI レビュー), 1 年後 (Review After)
  • 違反時の対応:
    • KPI 単項目未達 -> 原因調査 + ADR 追記 (Phase 計画見直し)
    • 6 ヶ月後 KPI 総合未達 -> Phase 計画見直し (Phase 間隔延長、scope 縮小、tooling 部分変更)
    • GAS runtime エラー発生 -> 即時 Phase 1 rollback (~5 分)

9. 長期的影響

Review After: 2027-05-26 (1 年後)

  • Phase 3 完了後に root (GAS) を workspace に含めるかの最終判断
  • Turborepo -> 別ツール (Nx 等) への移行必要性を KPI で評価
  • Jr 開発者の monorepo 運用習熟度を 1-on-1 で確認

負債化リスク

  • Phase 2 で停滞するリスク: Phase 2 完了後に Phase 3 着手の動機が薄れ、sync-engines.mjs が「動いているから触らない」状態で残存。対策: Phase 2 完了時に Phase 3 着手予定日 (最遅 2027-02) を ADR に追記 + GitHub Issue を自動作成 (scheduled reminder)
  • Turborepo EOL リスク: Vercel の Turborepo 開発優先度変更。ただし MIT ライセンスで fork 可能、pnpm workspace 自体は Turborepo 非依存
  • pnpm メジャーバージョンアップ: Catalogs API の breaking change。ただし pnpm チームは後方互換性を重視する傾向

10. 参照 (References)

10.1 過去 ADR との関係

  • Refines ADR-0019: drp のサブプロジェクト化 (ADR-0019 §2 で pnpm + 独立 lock を採用) が本 ADR の段階的 monorepo 化の先例。本 ADR は ADR-0019 の「サブプロジェクト独立管理」方針を「workspace 統合管理」に発展させる。Supersede ではない (ADR-0019 の Pipeline 移行決定自体は有効)
  • Reuses ADR-0050: Q42 5 軸 + WSM + CBA K.O. フレームワーク。本 ADR で MCDA 加重和を適用
  • Pattern-aligned with ADR-0054 / ADR-0058: Lint Rule Reference SSoT パターン -- monorepo 構造で SSoT の一元管理がさらに容易に
  • Pattern-aligned with ADR-0065: 設計根拠 citation framework -- 本 ADR §10.2 で 5 タイプ citation 準拠
  • No Supersede / No Conflict: 本 ADR は既存 ADR を上書き・矛盾させない

10.2 設計根拠 (Theoretical Foundation)

ADR-0065 §7.2 準拠、5 タイプ citation 形式:

  • pnpm Workspaces -- pnpm 公式 workspace ドキュメント: https://pnpm.io/workspaces (canonical)
  • pnpm Catalogs -- pnpm 公式 Catalogs ドキュメント: https://pnpm.io/catalogs (canonical)
  • Turborepo -- Vercel 公式 Turborepo ドキュメント: https://turborepo.com/docs (canonical)
  • Potvin & Levenberg (2016) -- Google の monorepo 運用実態: "Why Google Stores Billions of Lines of Code in a Single Repository", Communications of the ACM, Vol. 59, No. 7. DOI: 10.1145/2854146 (DOI)
  • monorepo.tools -- monorepo ツール比較・ベストプラクティス集: https://monorepo.tools (canonical)

10.3 関連リソース

  • RQ-053 Synthesis: docs/_internal/01_discovery/research_prompts/RQ-053_monorepo_topology_synthesis.md
  • 3 LLM 調査結果: docs/_internal/01_discovery/research_prompts/RQ-053_monorepo_topology_result_{claude,gemini,gpt}.md
  • PR #948 (Synthesis merged): commit cfd4bbd
  • PR #933 (RQ-053 起案 + 3 LLM 結果): commit cf64dde

11. Pipeline 審査履歴

11.1 初回審査 (2026-05-25, 順方向起案)

  • 投入方法: POST /drafts (id: adr-monorepo-pnpm-turborepo, retroactive: false) + POST /chat/start
  • Triage: Standard (monorepo 化による依存管理・ビルド効率・AI 探索効率の改善。段階的移行でリスクを抑制)
  • Socratic: Pass (情報充足、追加質問なし)
  • Consistency: PASS (既存 ADR との矛盾なし、Supersede 不要)
  • Score: 47/50 (Standard 閾値 40 超過、Critical 閾値 45 超過)
採点項目点数改善対応
問題定義4v2 で Phase 1 着手前に baseline 計測タスクを追記検討
代替案5--
判断基準5--
過去 ADR 整合性4v2 で Refines ADR-0019 の具体記述を補強済 (§10.1)
影響範囲4v2 で §5.4 を軸別表に再構成済
運用上の罠5--
ロールバック性5--
コスト試算5--
完了条件5--
長期的影響5--
  • Parallel Review (3 モデル): Gemini / Claude / o3 の主要指摘と対応
    • Claude Code 探索ミス率 KPI の主観性 (3 モデル共通) -> §8.1 で定量指標 (re-navigation 回数 + baseline 計測) に変更
    • Phase 3 GAS bundling 戦略の欠如 (Gemini, Claude) -> §4.2 Phase 3 + §6 罠 #7 に esbuild/rollup 前提を明記
    • Vercel Remote Cache データガバナンス (o3) -> §4.1 Remote cache 行に DPA 確認 + self-hosted フォールバック追記
    • 工数見積もり過少リスク (o3) -> §5.5 で 1.5x バッファ込みに上方修正
    • MCDA 係数設定根拠の不透明性 (Claude) -> §3.1 に係数設定根拠を追記
    • Phase 進行判定の主観依存 (Claude) -> §8.2 に定量的安定性判定基準を追記
    • 撤退時の案 A 転換矛盾 (Claude) -> §7 で Phase 計画見直しに修正 (案 A 自動転換を削除)