2025年12月、MetricShip リポで MetricShip構想 を実装した。AI が「実装できました」と言ったとき、それを人間じゃなくて基準で判定するためのツール。
構成(モノレポ)
packages/judge— YAML の判定基準を読んで PASS / BLOCK / HUMAN を出すpackages/collector— メトリクスを集めるexamples/todo-app— React + Hono の例アプリ(判定を試す用)
最初は Next.js の UI(apps/ui)も付けていたけど、途中で「CLI だけでいい」と判断して UI を削除。判定結果は CLI でカラー表示(PASS=緑 / BLOCK=赤 / HUMAN=黄)に変えた。テストは Bun ネイティブに移して、judge / collector ともカバレッジ 100% まで持っていった。
判定基準を YAML で固定する
肝は、完了条件をコードじゃなくて YAML に固定すること。metricship.criteria.yaml に、項目ごとにコマンド・閾値・落ちたときの扱いを書く。
criteria:
quality:
type_errors:
command: "bun x tsc --noEmit 2>&1 | grep -c 'error TS' || echo 0"
parse: number
lte: 0
on_fail: BLOCK # 1つでもあれば即マージ不可
description: "TypeScript型エラー数(0必須)"
test_coverage:
command: "bun test --coverage | grep 'All files' | awk '{print $4}' | tr -d '%'"
parse: number
gte: 80
warn: 90
on_fail: HUMAN # 通っても人間レビューに回す
項目は correctness(ビルド・ユニット・E2E)→ quality(型 / lint / カバレッジ / any 型 / console.log 残り)→ security(脆弱性 / ハードコードされた秘密)→ reliability(バンドルサイズ / P95 レイテンシ)→ maintainability(循環参照 / 巨大ファイル)の順で評価する。比較演算子は eq / lte / gte / lt / gt。
判定は3段階。
- BLOCK … 1つでもあれば即失敗(マージ不可)
- HUMAN … 全部 PASS でも、HUMAN があれば人間レビューに回す
- PASS … 全クリア
GitHub Actions で PR 作成時に走らせて、collector が集めた metrics.json を judge が評価し、結果を PR にコメントする。レイテンシは autocannon で計測。
学び
「作る AI」と「疑う AI」を分ける、という構想の入口は、結局 判定基準を YAML で外に出すところから始められた。基準がコードに埋まっていると毎回ブレるけど、YAML に固定すると「何をもって完了か」が常に同じになる。warn / HUMAN を挟めるので、白黒つけられない項目も握りつぶさずに残せるのが良かった。
おわり
PoC から本番への壁は、機能じゃなくて完了判定の自動化だ、というのがこのシリーズの結論。MetricShip はその回答の最初の形。判定項目はまだ増やせるし、プロジェクトごとの criteria を育てていく前提。