check スクリプトの実行
このスキルは、lt-devワークフローにおいて package.json の check スクリプトを実行するための 唯一の信頼できる情報源 です。プロジェクトの実行可能性を保証する必要があるすべてのレビュアー、リベーサー、およびオーケストレーターは、この手順を厳密に従わなければなりません。複数のエージェント間でルールを重複させると、定義がずれてしまいます。
目標: 真にグリーンな
check実行(exit 0)は、レビューまたはリベースが完了したとみなすための必須条件です。許容される唯一の残余は、修正エスカレーションラダーを使い尽くした上流の依存関係の脆弱性のみです。
このスキルを使用するタイミング
| 呼び出し元 | フェーズ | トリガー | モード |
|---|---|---|---|
/lt-dev:review | フェーズ 1.5 | 専用レビュアーを生成する前 | アドバイザリー |
lt-dev:code-reviewer | フェーズ 1.5 | シングルパスレビューの前(オーケストレーターが既に実行済みの場合はスキップ) | アドバイザリー |
lt-dev:test-reviewer | (入力ブリーフィング) | ここで定義されたスキップセマンティクスに従う | アドバイザリー |
/lt-dev:take-ticket | STEP 8 | すべてのテストピラーがグリーンになった後 | ブロッキング |
/lt-dev:git:ship | STEP 1, STEP 4b | プレフライト、およびリベース後の再検証後 | ブロッキング |
/lt-dev:ticket-cycle | take-ticket + git:ship 経由 | サイクル全体 | ブロッキング |
lt-dev:branch-rebaser | フェーズ 6.5 | lint/format後、テスト前 | ブロッキング |
呼び出し元のモード
手順は両方のモードで同一です。未解決のエラーが発生した場合の処理のみが異なり、その違いこそがこの区別の要点です。
- アドバイザリー — 呼び出し元の仕事は 報告 することです。Red の
checkは重大な発見として表面化され、ワークフローは継続します。ユーザーは残りのレビューをまだ必要としているからです。 - ブロッキング — 呼び出し元の仕事は 出荷 することです。Red の
checkはワークフローを停止します。何もプッシュされず、MR/PRは作成されず、何もマージされません。
MR/PR またはマージにつながるすべてのパスはブロッキングモードで実行されます。 Red の check がベースブランチに到達すると、チーム全体にコストが発生します。全員のCIが赤くなり、次の take-ticket は壊れたコードからブランチを作成し、最終的に修正する人はどの変更が原因かを特定できなくなります。そのため、ステップ3のラダーには反復回数の上限がなく、ステップ5の残差リストが非常に狭く定義されている理由です。
手順
ステップ 1 — check スクリプトを発見する
専用のヘルパースクリプト(lt-devプラグイン内にあります)を使用します。
bash "${CLAUDE_PLUGIN_ROOT}/scripts/discover-check-scripts.sh"
出力はTSV形式で、1プロジェクトにつき1行です。
<package.json path>\t<check script>\t<includes_tests:no|unit+api|yes>\t<package manager>
includes_tests の値 — 呼び出し元はそれぞれの値をどう扱うかを決定します。発見自体は動作を規定しません。
| 値 | 意味 | Playwright カバレッジ |
|---|---|---|
no | チェックチェーン内にテストランナーが検出されませんでした。 | カバーされていません。 |
unit+api | check チェーンは lt check.mjs ラッパーに委譲しており、ラッパーは Unit (app) + API (api) テストステップを実行し、Playwright を意図的にスキップします(Playwright は lt dev test / CI 経由で実行されます — scripts/check.mjs を参照)。 | カバーされていません — Playwright が必要な場合は、別途実行する必要があります。 |
yes | チェックチェーン内の test、vitest、jest、または playwright への直接パターンマッチ(推移的に、1レベルの複合解決)。スコープはスクリプトが定義するものに依存します。 | 不明 — Playwright カバレッジが必要な場合、呼び出し元はローカルで確認する必要があります。 |
ヘルパーは以下のことを行います。
git ls-files "package.json" "**/package.json"を使用するため、.gitignoreを尊重し、node_modulesをスキップします。jq→node -e→grep+sedフォールバックチェーンを介してJSONを解析します(jqがインストールされていなくても機能します)。- 1レベルの複合スクリプトを解決します(
"check": "pnpm run ci"→ciを検索)。 - プロジェクトごとにロックファイルを介してパッケージマネージャーを検出します(
pnpm-lock.yaml→pnpm、など。デフォルトはpnpm)。
ヘルパーが何も返さない場合 → check を定義しているプロジェクトがない → このスキルの残りをスキップします。
ステップ 1a — oxlint の提案修正がない場合
oxlint --fix-suggestions は、oxlint 自身が動作を変更する可能性があるとマークした修正を適用します。その no-console 提案は呼び出しを削除します。--fix-dangerously はさらに進みます。現在のテンプレートはどちらも渡しませんが、古いテンプレートのプロジェクトは、チェックラッパー、lint:fix、lint-staged、またはプロジェクト自身の scripts/check.mjs で依然として渡しています。lt fullstack update はワークスペースルートとアプリからそれらを削除します(追跡され、クリーンなファイルのみ)。APIプロジェクトは自身のファイルを保持するため、そこでのヒットは手動または現在の nest-server-starter ファイルを取得することで削除されます。nest-server(2026-09、claude-code PR #10)で観測されたように、コミットフックが console.log を空の関数本体に変換し、それでも「合格」と報告しました。ステップ2の前に、これらのフラグの使用を探します。コメント内での言及はカウントしません。
git grep -n -E "(^|[[:space:]\"'])(--fix-(suggestions|dangerously))" -- '*package.json' '*.lintstagedrc*' '*lint-staged.config.*' '*scripts/check.mjs' \
| grep -v -E '^[^:]+:[0-9]+:[[:space:]]*(//|/?\*|#)'
2番目のフィルターはコメント行を除外します。現在の nest-server-starter ラッパーは、なぜプレーンな --fix のみを渡すかをコメントで説明しています。
ヒットがあった場合、check は自動修正なしで実行されます。
- lt ラッパーを読み取り専用ゲートとして実行します:
<pm> run check --no-fix(npm:npm run check -- --no-fix)。まだフラグのいずれかを渡しているすべてのラッパーは、すでに--no-fixを認識しています。プロジェクト自身のチェーンがlint:fixを呼び出している場合、またはプロジェクト自身のscripts/check.mjsがヒットの1つである場合は、そのプロジェクトのステップをlint:fixの代わりにlintで実行します。 - lint の発見事項を手動で、またはプレーンな
oxlint --fixで修正します。プロジェクトのフォーマッタで通常通りフォーマットします。 - すべてのヒット(
file:line)をステップ8のレポートに、その修正方法とともに名前を付けます。ルートとアプリはlt fullstack update、APIプロジェクトはフラグを手動で削除(または現在の nest-server-starter ファイルを取得)します。
ステップ 2 — プロジェクトごとに check を実行する
発見された各プロジェクトについて、そのディレクトリに cd し、検出されたパッケージマネージャーで check スクリプトを実行します。
cd "$(dirname <package.json path>)"
<package manager> run check
stdout、stderr、終了コードをキャプチャします。1から始まる反復カウンターを追跡します。
ステップ 3 — 自動修正ループ(真にグリーンになるまで反復)
プロジェクトの check が非ゼロで終了した場合:
- 現在の実行からすべてのエラーを解析します(型チェック、lint、ビルド、インポート欠落、型不一致、未使用シンボル、監査結果など)。
- すべてのエラーを根本原因から修正します(
Read+Edit経由)。既存のエラーも修正されます — エラーがこの差分から発生したか、既に存在していたかは、プロジェクトが実行可能かどうかには違いをもたらさず、red のcheckはいずれにせよ次の人を同様にブロックします。スコープの境界は実行可能性には適用されません。ここで何かを決定する唯一の質問は「これは修正できるか?」であり、答えが「はい」である限り、修正されます。 - 最初から
checkを再実行します。 部分的な状態を信頼してはいけません。 - 以下の終了条件のいずれかが満たされるまで反復を続けます:
- (a) GREEN —
checkが 0 で終了 → このプロジェクトは完了 - (b) STALLED — 完全な反復でエラー数が純減しなかった
- (a) GREEN —
- 厳格な反復上限はありません。 各反復でエラー数が厳密に減少している限り、継続します。目標は真のグリーンです。
1つの狭い例外があり、それはスコープではなく衝突に関するものです。 ポイント2は変わりません。red の check は、誰が書いたかに関係なく次の人をブロックするため、既存のエラーは修正されます。ポイント2がカバーしないのは、別のライブセッションが処理中のコミットされていない作業 内のエラーです。それを再整形することはスコープの問題ではなく、2つのセッションが1つのファイルを編集していることであり、ピアが書き換えられたリファクタリングに戻ったときに、修正によって節約された時間以上の時間を失うことになります。ツリーがダーティで、かつ bash "${CLAUDE_PLUGIN_ROOT}/scripts/change-provenance.sh" が失敗したパスをライブピアのものと属性付ける場合: それが些細で自己完結型の修正(欠落したインポート、フォーマット違反、散らばった console.log)であれば修正し、そうでなければ著者を明記してブロッカーとして報告し、さらに診断を伝える1つの SOLVED を付けて、彼らが自分の作業を1ステップで修正できるようにします。ライブの人なし、または属性付け不可能: ポイント2が変更なく適用されます。
STALLED はアプローチを変更するシグナルであり、停止する許可ではありません。 同じ修正が再試行されているときにカウントは減少しなくなるため、次の反復ではエラーに異なる方法で取り組む必要があります。報告された行の周辺をパッチするのではなく、失敗しているファイル全体を読み、2つのエラーが1つの原因を共有していないか確認し、動作している兄弟モジュールが同じ問題をどのように解決しているか調べ、集約実行で飲み込まれた出力を見るために失敗しているステップだけを実行し、それがステップ6.5から6.8の既知の危険の1つかどうかを確認します。真に異なるアプローチが試され、それでもカウントが変わらない場合にのみ、ステップ5の残差分類が適用されます。そしてブロッキングモードでは、ラダーを使い果たした依存関係の脆弱性を除くすべてが依然としてワークフローを停止します。
ステップ 4 — 監査結果: 必須修正エスカレーションラダー
pnpm audit / npm audit / yarn audit(check によって呼び出される)が脆弱性を報告した場合、その発見を「承認済み」として分類する前に、このラダーを使い果たしてください。各ステップの後に check を再実行します。
| # | ステップ | コマンド (pnpm / npm / yarn) |
|---|---|---|
| 1 | 最新の互換性のあるバージョンに更新 | pnpm update <pkg> / npm update <pkg> / yarn upgrade <pkg> |
| 2 | 自動修正 | pnpm audit --fix / npm audit fix / yarn audit --fix |
| 3 | セマバーメジャーアップグレードを強制 | pnpm audit --fix --force / npm audit fix --force |
| 4 | アドバイザリが修正をリストしている場合、直接依存関係を次のメジャーにバンプ | pnpm add <pkg>@<major> / npm install <pkg>@<major> / yarn add <pkg>@<major> |
| 5 | 推移的依存関係のバージョンを強制 | pnpm.overrides / resolutions (yarn) / overrides (npm) ブロックを package.json に追加し、再インストール |
| 6 | 脆弱なパッケージではなく、コンシューマーを上げる | それを引き込む直接依存関係、およびフレームワークがそれを固定している場合は lt フレームワーク(@lenne.tech/nest-server / @lenne.tech/nuxt-extensions)— 完全な /lt-dev:maintenance:maintain が徹底的な方法です |
| 7 | コンシューマーにパッチを当てる — 以下の条件がある場合のみ | pnpm patch <pkg> → patchedDependencies |
| 8 | パッケージを置き換える | 放棄されている場合は、メンテナンスされている代替品に切り替える |
ステップ6はスキップされがちな段ですが、最も効果的なことが多い段です。 ステップ1から5はすべて、脆弱な パッケージを前方にプッシュします。それが失敗する場合、通常は脆弱なパッケージ自体が原因ではなく、脆弱な範囲を固定したり、パッチされたメジャーが削除したAPIを使用したりして、それを引き留めるコンシューマーが原因です。したがって、「誰がこのバージョンをここに留めているのか?」を問う必要があり、その答えは直接依存関係、またはオーバーライドが打ち負かせない固定を持つフレームワークです。オーバーライドは固定であり、固定は実際のバージョンバンプよりも厳密に悪いものです。ツリーを上流のテストから乖離させ、静かに腐敗します。存在するバンプを取得してください。
ステップ7(パッチ)は意図的に狭く定義されており、その狭さこそが要点です。 パッチされたメジャーがロードに失敗するだけの場合(削除されたデフォルトエクスポート、名前が変更されたエントリポイント)、1行のパッチは、抑制するのではなく、適切にアドバイザリを閉じているように見えます。時々そうなります。ただし、最初に3つの条件が満たされている必要があり、3番目が通常失敗する条件です。
- パッチは、脆弱なパッケージ内の安定したパスをターゲットとし、1つの正確なバージョンに固定されます。パッチを壊すのは
dist/自体ではありません(公開されたパッケージはdist/のみを出荷します)が、リリース間で移動するパスです。dist/chunks/<hash>.mjsは次のビルドで名前が変更され、パッチはチームの全員に対して失敗します。dist/index.mjsはパッケージ自身のエントリポイントであり、そのまま残ります。縮小されたシンボルに名前を付けるパッチでも、バージョン固定があれば許容されます。なぜなら、固定によってリスクが、静かなミスパッチではなく、大きなpnpm installの失敗に変わるからです。脆弱な依存関係にパッチを当ててください。たまたまそれをインポートするコンシューマーではありません。以下に測定されたケースを示します。最初の評価ではコンシューマーのチャンクを見て、その根拠でその段を却下しました。 - プロダクションクロージャとメンテナンスコストを比較検討します。パッチは将来のすべてのバンプに対する継続的な義務であるため、プロダクションに到達できない開発ツールパスの場合、多くの場合、購入する以上のコストがかかる可能性があります。単一のプロジェクトではそうです。TEMPLATE はその計算を逆転させます。生成されたすべてのプロジェクトが1つのパッチを継承する一方で、残差はそれぞれで再議論する必要があります。これは判断であり、拒否権ではありません。条件1と3が難しい条件です。
- ロードできることと、動作することは同じではありません。エクスポートを削除したメジャーは通常、動作も変更しているため、パッチされたインポートはモジュールをインポート可能にする一方で、コンシューマーはテストされたことのないAPIに対して実行され続けます。そのメジャーで他に何が変更され、なぜそれがここで重要でないのかを言えない場合、パッチは修正の格好をした推測にすぎません。
脆弱なパッケージにパッチを当て、コンシューマーには当てないでください。 これが、その段が機能するかどうかを決定する区別であり、エラーがコンシューマーを指しているため、誤解しやすいです。測定例: lt-crm 2026-10-06: @nuxt/[email protected] は import Git from 'simple-git' を行い、simple-git を唯一の修正行(そのデフォルトエクスポートを削除した4.x)に引き上げると、nuxt prepare が does not provide an export named 'default' で中断しました。最初の評価は devtools 自身の dist/chunks/module-main.mjs を見て、そこにインポートを発見し、コンパイルされたチャンクであるとして条件1でパッチを却下しました。これは間違ったファイルに対する正しい判断でした。パッチは1レベル下、simple-git 自身の dist/index.mjs に属します。そこでは、モジュールが既に simpleGit としてエクスポートしているのと同じファクトリを default として再エクスポートする1行が追加されます。強化されたコードについては何も変更されません。モジュールの表面だけが戻ってきます。
これにより、3つの条件すべてが満たされます。脆弱なパッケージであり、コンシューマーの成果物ではありません。1つの正確なバージョンに固定されています(patchedDependencies: { '[email protected]': … } に加えてオーバーライドターゲット)。そしてデブツールが実際に呼び出すAPI — branch、revpars...
(以下同様)」 }