検索/フルスタックのモノレポで、共有パッケージを壊さずに変更を加える

フルスタックのモノレポで、共有パッケージを壊さずに変更を加える

アプリと共有パッケージが1つにまとまったモノレポをAIに直させる時に使う。変更を正しいモジュールに置き、生成されるバンドルを作り直し、組織ごとのデータを混ぜず、テスト結果つきのプルリクエストにまとめる。

このAIルールを使うには
## 変更を、その役目を持つモジュールに置く 編集を始める前に、ワークスペースの構成を把握する。製品アプリケーション、再利用可能なUIパッケージ、共有ビジネスロジック、データスキーマとマイグレーション、型パッケージ、設定プリセット、ドキュメント、デプロイ用アセット、テストハーネスを区別する。 機能固有の動作は、その機能を所有するアプリケーションまたは機能モジュールに置く。再利用可能なドメインロジックと共有型は、利用側が明確なパッケージに置く。インフラストラクチャやデプロイ用の付随物は、実行時のソースコードから分離する。単体テストは対象となる安定したロジックと同じ場所に配置し、ブラウザフローの仕様はアプリケーションのエンドツーエンド領域に置く。 パッケージの変更を避けるためだけに、共有ロジックをアプリケーション内へ複製してはならない。依存関係の向きに従い、共有パッケージを変更した際は下流の利用箇所をすべて検証する。 ## 事前ビルドのパッケージを作り直し、古いキャッシュを避ける 事前にcompileされ、アプリケーションのpublic assetへコピーされるパッケージを特定する。実行中のアプリケーションはパッケージのsourceではなくdistribution outputをimportしている場合があるため、sourceを編集しただけでは変更を確認できないことがある。 事前compile済みパッケージ、またはそのbundleに影響する依存関係を変更した後は、次の手順を実行する。 1. そのパッケージについて既知のdistribution outputとコピー済みartifactだけを削除する。 2. 影響を受ける依存関係graphではbuild systemのcacheを使用しない。 3. 公式のworkspace taskを通じてパッケージを再buildする。 4. browser cacheを更新するか無効にする。 5. 再buildしたassetがまだ読み込まれない場合に限り、development serverを再起動する。 コピー済みbundleや生成artifactを手作業で編集してはならない。cacheの無効化は検証手順の一部として扱い、source変更が失敗した証拠とはみなさない。 ## 共有のリントと型の決まりに合わせて書く local overrideではなく、repositoryで共有されているlint、format、compiler presetを使用する。既定のindent、行幅、引用符、semicolon、import groupのruleに従う。 componentとcomponent folderには一貫した名前を付け、functionとvariableにはlower camel caseを使用し、本当の定数にだけupper snake caseを使用する。mockは指定されたmock配置場所に置き、解決方法とimport順を安定させる。 明確さが保たれる場合は型推論を優先し、共有domain typeを使い、型付けされていない逃げ道を避ける。component propsは不変として扱う。componentの役割を絞り、effectの範囲を狭くし、hookの依存関係を正しく保つ。memoizationは習慣ではなく、測定された必要性に基づいて使用する。 ## サーバー処理を分け、キャッシュのキーを1か所の仕組みで作る routeの組み立て、service logic、feature moduleを分離する。server actionはserviceを呼び出し、一貫した成功またはerrorのenvelopeを返す。context providerはproviderの外で使用された場合に明確に失敗し、変更可能な参照ではなく安定したsnapshotを使ってeffectをcleanupしなければならない。 1回のrequest内で重複する処理には、request scopeのmemoizationを使用する。requestをまたぐ高コストな処理には、承認済みの共有cache abstractionまたは明示的なdistributed cacheを使用する。repositoryで採用しないと決めた不安定なframework cache APIを導入してはならない。 すべてのcache keyは、正規のkey factoryで作成する。user、tenant、environment、locale、feature modeの間で互換性のないentryが共有されないよう、結果を変え得るすべての次元をkeyに含めなければならない。 ## 画面の文字は翻訳を通し、タイムゾーンを言語と分けて扱う user向けのすべてのtextはtranslation functionを通し、既定の小文字によるdot区切りkey規約に従う。手作業で編集する唯一の翻訳sourceとして、1つのsource locale fileを維持する。生成されたlocale fileを手動で編集してはならない。source textを変更した後はlocalization generatorとkey validatorを実行する。 user向けの日時は共有helperを通じて表示する。表示localeはapplicationにおけるlanguageの正本から取得し、暗黙のbrowser defaultから取得してはならない。localeとtime zoneは独立したものとして扱う。localeは表示形式を制御し、time zoneは表現される時点を制御する。 localeからtime zoneを推測してはならない。製品がtime zoneの正本を定義していない限り、既存の保存値の意味を維持する。storage、API、export、integration、logでは、明示的なUTCまたはISO表現など、安定した非localize形式を使用する。 ## 組織ごとのデータを混ぜず、クエリを速く保つ すべてのdata operationを、organizationやenvironmentなどrepositoryのtenant境界でscopeする。無効化または削除されたrecordが別のquery経路から再び現れないよう、soft deletion filterを一貫して適用する。 件数の取得には、offset形式のpagination引数ではなく、条件を指定したcount queryを使用する。独立したcount queryとdata queryは並行して実行する。大規模datasetにはcursor paginationを優先し、時間でfilterする場合はindexが設定されたownership fieldを含める。 schemaとmigrationの変更は、影響を受けるすべてのquery経路と併せてreviewする。data isolationは横断的な不変条件である。tenant predicateの欠落は軽微なperformance問題ではなく、data境界の侵害につながる可能性がある。 ## カバレッジの数字でなく、利用者への影響でテストを選ぶ coverage率ではなく、確信の強さを最適化する。 - 重要なuser journey、UI regression、componentの動作にはbrowser end-to-end testを使用する。 - validator、transformer、evaluator、計算、edge caseなど安定したpure logicにはunit testを使用する。 - release準備状況にはstagingでの手動確認を使用し、重大な指摘にはbug修正、backport、再testのloopを設ける。 browser testは焦点を絞り、適切に命名し、実行時間の長いsuiteを明示する。networkとstorageの境界は共有helperを通じてmockする。壊れやすいcomponent snapshot、markup assertion、実装詳細のtest、時間依存の回避策、巨大なflow、coverageを上げるためだけの価値が低いtestを追加してはならない。 review前に標準unit suiteを実行し、重要なflowが変わる場合はcoverageを確認し、journey riskには直接影響を受けるend-to-end suiteを実行する。 ## ドキュメントとコンポーネントの見本を最新に保つ documentation systemのfile contract、metadata field、heading rule、承認済みのstep componentまたはcallout componentに従う。限定版のcontentには、新しいbadgeや文言を考案せず、標準のnoticeを付ける。 component exampleはcomponentのそばに置き、そのpublic entry pointを通じてimportする。controlはrepositoryの標準groupに整理する。default state、対応している場合はdisabled stateとicon state、すべてのvariant、意味のあるedge caseを網羅する。 UIを構築またはreviewする前に、影響を受けるsurfaceのdesign contextを読み込む。共有design guidanceはcode規約を補完し、token、component、motion、visual qualityの正本であり続ける。 ## CIのワークフローに、必要な権限だけを渡す 自動化用tokenには、各workflowに必要な権限だけを付与する。hosted Linux jobの冒頭では、承認済みのrunner hardening stepを実行し、project codeが動く前にnetworkとprocessの動作を制約する。 dependency lockを正本として維持し、repositoryが選定したpackage managerを通じてworkspace commandを実行する。task graph、共有environment、cache metadataを迂回する単発のinstall commandやbuild commandは避ける。 workflowを変更する際は、event trigger、permission、secretの露出、cache key、artifact、failure propagationを検証する。後続stepがgreenでも、失敗した前提stepを隠してはならない。 ## テスト結果と画面の証拠をつけて、プルリクエストを出す 完了前にdead codeと未使用importを取り除き、正規のlint commandを実行し、変更を証明する最小のtest setと直接影響を受ける広いflowを実行する。 commitは焦点を絞り、repositoryのcommit規約に従う。pull requestには問題を記載し、解決策を要約し、根拠となるissueまたはspecificationへのlinkを付け、migrationまたはenvironment変更を明示する。 UI作業には視覚的な証拠を添付し、関連するlint、test、build、migration commandの結果を記載する。reviewerがdiffから作業を再構築しなくても、何を変更したのか、なぜそのmoduleに属するのか、生成物をどのように更新したのか、どのriskを検証したのか判断できるようにする。