mastra-ai/mastra -- 導出ルール集
出典: repos/mastra-ai/mastra/ | 生成日: 2026-02-14 用途: CLAUDE.md にそのまま貼り付けて AI コンテキストとして活用
型システムとスキーマ設計
[MUST]Zod スキーマを定義したらz.infer<typeof schema>で型を導出し、手書きの型定義と二重管理しない- 根拠: type-system-patterns -- コードベース全体でスキーマから型を導出し、定義の乖離を防止している
[MUST]判別共用体(Discriminated Unions)の判別子にはリテラル型を使い、switch/ifによる型の絞り込みを可能にする- 根拠: type-system-patterns --
StepResult型はstatusリテラルで 6 バリアントを判別し型安全にアクセスできる
- 根拠: type-system-patterns --
[MUST]スキーマライブラリのバージョン検出にはinstanceofではなく構造的プロパティチェック(duck typing)を使う- 根拠: schema-validation-patterns --
instanceofは dual-package hazard で失敗する。_def/_zodの存在とparse/safeParseの有無で判定
- 根拠: schema-validation-patterns --
[SHOULD]外部ライブラリの複数バージョンを扱う場合、nominal 型ではなく構造的部分型(特定メソッドの有無)で互換性レイヤーを作る- 根拠: type-system-patterns --
ZodLikeSchemaは Zod v3/v4 両方を構造的判定で受け入れている
- 根拠: type-system-patterns --
[SHOULD]設定値が「静的な値」と「実行時に解決する関数」の両方を取りうる場合、T | ((ctx) => T | Promise<T>)のユニオン型(DynamicArgument パターン)で表現する- 根拠: type-system-patterns, design-philosophy -- Agent の instructions/tools/model 全てでこのパターンを使い、テスト時は静的値、本番では動的解決を同一 API で扱える
[SHOULD]ブランド型(unique symbol+ intersection)を使って、特定の関数からのみ生成可能な値を型レベルで強制する- 根拠: type-system-patterns --
InnerOutput型はsuspend()の戻り値専用のブランド型で、不正な void 値をコンパイル時に防止
- 根拠: type-system-patterns --
[SHOULD]チェーンメソッド(Builder パターン)ではthisの型を更新して返し、前ステップの出力型を次ステップの入力型に伝播させる- 根拠: type-system-patterns, composability-patterns --
Workflow.then()が型パラメータを伝播し、ステップ間の型互換性をコンパイル時に検証
- 根拠: type-system-patterns, composability-patterns --
[SHOULD]関数オーバーロードを使う場合、最後にフォールバックオーバーロードを置いてエラーメッセージを改善する- 根拠: type-system-patterns --
createStepは意図的にフォールバックオーバーロードを配置し、マッチしなかった場合のエラー品質を向上
- 根拠: type-system-patterns --
[AVOID]ジェネリクスを 5 つ以上持つ public API を作る。型エラーが難読化し IDE の補完品質も低下する- 根拠: type-system-patterns, abstraction-patterns --
Workflowの 8 ジェネリクスは強力だが型エラーが数百行に膨れ、関連する型をインターフェースにグループ化して削減すべき
- 根拠: type-system-patterns, abstraction-patterns --
エラーハンドリング
[MUST]catch (e)で受け取ったエラーを直接操作せず、中央の正規化関数(getErrorFromUnknown相当)を通してから使用する- 根拠: error-handling-idioms --
eはunknown型であり、全コンポーネント共通の正規化で cause チェーンの深度制限やシリアライズまで一元化
- 根拠: error-handling-idioms --
[MUST]エラーの catch-rethrow では、既にドメインエラーでラップ済みかどうかをinstanceofでチェックしてから再ラップする- 根拠: error-handling-idioms -- 23 のストレージアダプター全てで
if (error instanceof MastraError) throw error;を適用し、二重ラップを防止
- 根拠: error-handling-idioms -- 23 のストレージアダプター全てで
[SHOULD]構造化エラーには、エラーの発生源を示すドメインと責任者を示すカテゴリ(USER / SYSTEM / THIRD_PARTY)を付与する- 根拠: error-handling-idioms, design-philosophy --
MastraErrorはErrorDomain(17種) とErrorCategory(4種) の組み合わせでエラーを分類
- 根拠: error-handling-idioms, design-philosophy --
[SHOULD]リトライロジックを高階関数として切り出し、リトライ対象の判定・バックオフ計算・ロギングを呼び出し元から分離する- 根拠: error-handling-idioms -- LibSQL/MongoDB のアダプターが
createExecuteWriteOperationWithRetryでリトライの詳細を隠蔽
- 根拠: error-handling-idioms -- LibSQL/MongoDB のアダプターが
[SHOULD]リトライ対象エラーの判定は、エラーメッセージの文字列検索ではなくエラーコード(error.code)やエラー型(instanceof)で行う- 根拠: error-handling-idioms -- 文字列マッチは誤判定のリスクがある。コードベース判定を主軸とし、メッセージ判定はフォールバック
[SHOULD]ワークフロー等の長時間処理では、ステップ実行結果を例外ではなく判別共用体({ ok: true, result } | { ok: false, error })で返す- 根拠: error-handling-idioms -- リトライ消尽後も例外を投げず Result 型で返すことで、全体の実行フローが予測可能になる
[SHOULD]エラーメッセージに「なぜこのエラーが起きやすいか」と「典型的な解決策」を含める- 根拠: api-design-practices --
createUndefinedPrimitiveErrorは{ ...config }スプレッドによるゲッター消失という具体的原因を指摘
- 根拠: api-design-practices --
[AVOID]ライフサイクルコールバック(onFinish/onError)の例外を本体の制御フローに伝播させない- 根拠: error-handling-idioms, concurrency-patterns -- コールバック例外は
try/catchで吸収しログに記録するだけにとどめる
- 根拠: error-handling-idioms, concurrency-patterns -- コールバック例外は
テスト戦略
[MUST]同一インターフェースの複数実装をテストする場合、テストスイートファクトリを作成して共通テストを集約する。各実装の差異は capability フラグで宣言的に表現する- 根拠: testing-practices -- 20 超のストレージアダプターに対し 90+ のテストケースを共有し、各テストファイルは 1-5 行のファクトリ呼び出しで済んでいる
[MUST]モノレポの CI ではテスト実行範囲を変更差分に限定する仕組みを導入する(--changedフラグ、paths-filter等)- 根拠: testing-practices, ci-cd --
vitest --changedとdorny/paths-filterの組み合わせで PR ごとに変更関連テストのみ実行
- 根拠: testing-practices, ci-cd --
[SHOULD]テストユーティリティやテストスイートファクトリはワークスペース内の独立パッケージとして管理する- 根拠: testing-practices --
stores/_test-utils,server-adapters/_test-utilsがそれぞれ独自のpackage.jsonを持ちバージョン管理
- 根拠: testing-practices --
[SHOULD]Vitest のプロジェクト名にunit:/e2e:/typecheck:のプレフィックスを付与し、CI で glob フィルタリングできるようにする- 根拠: testing-practices, dev-conventions --
--project 'unit:*'で単体テストのみ実行し、4 シャード並列化で CI 時間を短縮
- 根拠: testing-practices, dev-conventions --
[SHOULD]テストデータのクリーンアップメソッドにはdangerouslyプレフィックスを付与し、プロダクションコードでの誤用を防止する- 根拠: testing-practices -- 全ドメインストレージに
dangerouslyClearAll()を実装し、テストの afterAll でのみ使用
- 根拠: testing-practices -- 全ドメインストレージに
[AVOID]テストファイル冒頭でのvi.setConfig({ testTimeout: ... })によるタイムアウト一律延長。遅いテストの根本原因を調査する- 根拠: testing-practices -- インフラセットアップのみ
beforeAllの第 2 引数で長いタイムアウトを指定するのが適切
- 根拠: testing-practices -- インフラセットアップのみ
抽象化と拡張性
[MUST]プラグインインターフェースでは、コア機能を abstract メソッドとし、オプショナル機能はデフォルト実装(warn ログ or no-op)を提供する- 根拠: abstraction-patterns, extensibility-mechanisms -- 全 abstract class がこのパターンを採用し、50 超のアダプター実装コストを最小化
[MUST]複数バックエンドを統一する抽象レイヤーでは、バリデーションと共通ロジックを基底クラスの protected メソッドに集約する- 根拠: abstraction-patterns --
MastraVector.validateExistingIndex()が 18 のベクトル DB アダプター全てで一貫したバリデーションを保証
- 根拠: abstraction-patterns --
[MUST]フレームワークのオプショナル機能には NoOp 実装を用意し、未設定時に例外ではなく安全な無動作を提供する- 根拠: architecture, design-philosophy --
NoOpObservability,noopLoggerにより最小構成でもフレームワーク全体が動作
- 根拠: architecture, design-philosophy --
[MUST]合成対象のコンポーネントが異なる型を持つ場合、統一インターフェースを定義し、各コンポーネント型からの変換関数を型ガード付きで提供する- 根拠: composability-patterns --
createStepが Agent/Tool/Processor/StepParams を Step に統一変換
- 根拠: composability-patterns --
[SHOULD]異なるバックエンドが同一機能に対して異なる制約を持つ場合、共通 DSL + Translator パターンで抽象化する- 根拠: abstraction-patterns --
BaseFilterTranslatorとその 14 のベンダー実装が MongoDB-like フィルタ文法を統一 API として提供
- 根拠: abstraction-patterns --
[SHOULD]複数プロバイダーの機能を組み合わせる場合、Composite パターンで委譲する(継承ではなく合成)- 根拠: abstraction-patterns, composability-patterns --
CompositeVoiceが入力/出力/リアルタイムを個別プロバイダーに委譲
- 根拠: abstraction-patterns, composability-patterns --
[SHOULD]インフラ層は機能ドメインごとに独立したインターフェースに分割し、異なるバックエンドの合成を可能にする- 根拠: architecture, design-philosophy --
StorageDomainsが 10 個のドメインを独立定義し、MastraCompositeStoreで異種バックエンド混合が可能
- 根拠: architecture, design-philosophy --
[SHOULD]非同期初期化が必要なリソースには Proxy ベースの遅延初期化を適用し、利用側が初期化タイミングを意識しなくてよい API を提供する- 根拠: architecture, extensibility-mechanisms --
augmentWithInitが Proxy で全メソッドの前にensureInit()を挿入
- 根拠: architecture, extensibility-mechanisms --
API 設計
[MUST]パブリック API のコンストラクタ引数は単一の設定オブジェクトにし、3 個以上の位置引数を避ける- 根拠: api-design-practices -- 全主要クラスが設定オブジェクトパターンを一貫して採用し、後方互換を保ちながら段階的にオプションを追加
[SHOULD]クラスコンストラクタの代わりにcreateXxxファクトリ関数をパブリック API として公開し、型推論をファクトリに任せる- 根拠: api-design-practices --
createTool/createStep/createWorkflow/createScorerが一貫してジェネリクスの明示的指定なしで正確な型推論を実現
- 根拠: api-design-practices --
[SHOULD]破壊的リネーム時は旧名を@deprecatedエイリアスとして同一ファイルに残し、段階的移行を支援する- 根拠: code-organization --
MastraStorage extends MastraCompositeStoreのように旧クラスを空の派生クラスとして残し即時破壊を防止
- 根拠: code-organization --
[SHOULD]大規模パッケージのメインエントリポイント(index.ts)は最小限に保ち、モジュール別のインポートはサブパスエクスポートで提供する- 根拠: code-organization --
@mastra/coreのメインエントリは 1 行のみで、20 超のサブパスエクスポートで機能を公開
- 根拠: code-organization --
[SHOULD]LLM から受け取ったツール入力は、検証前に正規化パイプラインを通す(null/undefined 正規化、型強制、文字列化 JSON の復元)- 根拠: schema-validation-patterns -- LLM プロバイダごとの癖を 5 段階パイプラインで吸収
[AVOID]index.tsでexport *だけを連鎖させて公開 API を暗黙的にする。名前衝突リスクが高まり API 境界が曖昧になる- 根拠: code-organization -- 名前付きエクスポートで API を明示する方が境界が明確
モノレポ管理
[MUST]パッケージ数が 15-20 を超える場合、機能カテゴリ別のトップレベルディレクトリに分割する- 根拠: project-structure, code-organization --
stores/(23),voice/(13),auth/(6) 等 11 のトップレベルカテゴリで 90 超のパッケージを管理
- 根拠: project-structure, code-organization --
[MUST]公開パッケージと非公開パッケージは npm スコープで明確に分離し、非公開パッケージにはprivate: trueを設定する- 根拠: project-structure --
@mastra/*(公開) と@internal/*(非公開) で changesets の ignore が 1 パターンで完結
- 根拠: project-structure --
[MUST]モノレポの開発ツール(テストランナー、型チェッカー、リンター)のバージョンは pnpm catalog 等の一元管理機構で統一する- 根拠: project-structure, dependency-management -- catalog で vitest/typescript/zod を一元管理し、120 超パッケージ間のバージョン不整合を防止
[SHOULD]アダプターパッケージはコアをpeerDependenciesとして宣言し、semver 範囲にプレリリースを含める>=X.Y.Z-0 <(X+1).0.0-0形式を使う- 根拠: project-structure, dependency-management -- 全パッケージで統一形式を使用し、prerelease での依存解決エラーを防止
[SHOULD]非公開パッケージのディレクトリ名にアンダースコアプレフィックス(_)を付与し、ファイルシステム上で公開パッケージと視覚的に区別する- 根拠: project-structure, code-organization --
_test-utils/,_config/,_vendored/が一貫してアンダースコアプレフィックスを使用
- 根拠: project-structure, code-organization --
[SHOULD]Changesets の ignore 設定ではホワイトリスト方式(デフォルト全無視 + 公開パッケージのみ有効化)を採用する- 根拠: dependency-management --
"ignore": ["*", "@internal/*", "!mastra", "!@mastra/*"]で internal パッケージ追加時の設定漏れを構造的に防止
- 根拠: dependency-management --
[SHOULD]密結合パッケージは changeset のfixedグループで同一バージョンリリースを保証する- 根拠: dev-conventions, dependency-management -- core/server/deployer を固定グループにして常に同一バージョンでリリース
ビルドと CI/CD
[MUST]monorepo のバンドラーで型生成する場合、バンドラー組み込みの DTS 生成を避け、tsc を別ステップで実行する- 根拠: build-and-tooling -- 全 80+ パッケージで
dts: false+onSuccessでの tsc 実行を採用し、型パス解決の問題を回避
- 根拠: build-and-tooling -- 全 80+ パッケージで
[MUST]Turborepo のタスクinputsにテストファイルやドキュメントの除外パターンを明示し、不要なキャッシュ無効化を防ぐ- 根拠: build-and-tooling --
!**/*.md,!**/*.test.tsを明示的に除外
- 根拠: build-and-tooling --
[MUST]モノレポの CI では変更のないパッケージのテストをスキップし、スキップ時にも明示的に success ステータスを返す- 根拠: ci-cd --
turbo-changedアクションで推移的依存を含む変更検出を行い、skip-testsジョブで required check をパス
- 根拠: ci-cd --
[SHOULD]CI のセットアップ手順は composite action に集約し、全ワークフローで再利用する- 根拠: ci-cd --
setup-pnpm-nodeアクションが 20 超のワークフローで使われ、バージョン一元管理を実現
- 根拠: ci-cd --
[SHOULD]ワークフローレベルでpermissions: {}を宣言し、ジョブごとに必要最小限の権限のみを付与する- 根拠: ci-cd -- ワークフロー全体の権限を空にし、各ジョブで
contents: readのみ付与
- 根拠: ci-cd -- ワークフロー全体の権限を空にし、各ジョブで
[SHOULD]ビルドキャッシュの読み書き権限を役割で分離する(ビルド: rw、テスト: r のみ)- 根拠: ci-cd -- テスト結果のキャッシュは誤キャッシュを招くため読み取り専用にする
[AVOID]コミットメッセージの文字列マッチでワークフロー間を連携させること。workflow_callやrepository_dispatchを使う- 根拠: ci-cd -- コミットメッセージ変更で連携が壊れるリスクがある
開発規約
[MUST]モノレポのリンター設定は内部パッケージとして集約し、各パッケージは 1 行のインポートで取り込む- 根拠: dev-conventions --
@internal/lintで 80 超パッケージの ESLint 設定を一元管理
- 根拠: dev-conventions --
[MUST]TypeScript プロジェクトではno-floating-promisesとconsistent-type-importsを有効にする- 根拠: dev-conventions -- Promise ハンドリング漏れの防止と型インポートの明示的分離をエラーレベルで強制
[SHOULD]共有リント設定は依存パッケージの存在を動的検出し、フレームワーク固有ルールを条件付きで適用する- 根拠: dev-conventions --
import.meta.resolveで React/Vitest 等の存在を検出し、1 つの設定で全パッケージに対応
- 根拠: dev-conventions --
[SHOULD]リンターで無効にしたルールには、無効にした理由をコメントで記録する- 根拠: dev-conventions -- 無効にした各
@typescript-eslintルールの理由が詳細にコメントされている
- 根拠: dev-conventions -- 無効にした各
[SHOULD]pre-commit hook では変更ファイルのみ lint + format し、全体チェックは CI に委ねる- 根拠: dev-conventions --
.husky/pre-commitでlint-stagedのみ実行し、全体チェックは CI で行う
- 根拠: dev-conventions --
[AVOID]FIXME コメントをコードベースに残す(TODO は許容するが FIXME はエラーとして扱う)- 根拠: dev-conventions --
no-warning-commentsで FIXME をエラーレベルに設定し、緊急の未解決問題のコミットを防止
- 根拠: dev-conventions --
並行処理
[MUST]長時間中断が想定される非同期処理では、中断と再開を第一級の概念として設計し、状態をシリアライズ可能にする- 根拠: concurrency-patterns -- ワークフローは suspend 時にスナップショットを永続化し、プロセス再起動後も再開できる
[MUST]並列実行する操作に副作用の競合がある場合、並行度を自動的に 1 に降格させる仕組みを持つ- 根拠: concurrency-patterns -- 承認や suspend が必要な tool call では明示的な concurrency 設定よりも安全性制約が優先
[SHOULD]高頻度の書き込みには debounce + staleness 上限のハイブリッド戦略を適用する- 根拠: concurrency-patterns --
SaveQueueManagerは debounce でバッチ化しつつ MAX_STALENESS_MS を超えたら即座に flush
- 根拠: concurrency-patterns --
[AVOID]バッチ並列実行でPromise.allを使う場合に、失敗時の他タスクのキャンセル戦略を持たないこと- 根拠: concurrency-patterns -- AbortController と組み合わせるか
Promise.allSettled+ abort signal を検討すべき
- 根拠: concurrency-patterns -- AbortController と組み合わせるか
ルール優先度の解釈
[MUST]: 違反するとバグ・セキュリティリスク・重大な設計劣化を招くルール[SHOULD]: 従うことで品質が向上するが、文脈によっては例外を許容するルール[AVOID]: 意図的に避けるべきアンチパターン・非推奨プラクティス