verify-before-commit について
verify-before-commit は、実装後にチェックとスモークテストを行い、コミットをゲートするエージェントスキルです。コミット成功後、該当するドラフトを wiki に昇格させ、関連タスクのライフサイクルを完了できます。
主な機能
- 01型チェック、lint、テストを実行
- 02利用可能な回帰・タスクゲートを実行
- 03アプリのゴールデンパスを確認
- 04理由を重視したメッセージでコミット
- 05ドラフトを昇格しタスク状態を更新
活用シーン
- 01コミット前の変更検証
- 02必須チェック失敗時のコミット防止
- 03完了した作業の wiki への記録
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ rheinmir/ setup --skill verify-before-commitインストール後、Claude Code で/verify-before-commitを入力して読み込まれたか確認します。
詳細
スキル:verify-before-commit
WHAT
目的とコンテキスト
- 目的: すべてのコミットをゲートします。コミット前に typecheck、lint、test、smoke を実行し、コミット後に draft を wiki に昇格させ、タスクのライフサイクルを完了します。
- トリガー(使用するタイミング): 実装タスクの後、
git commitの前。 - 対象外: 新機能は実装しません。「変更が小さい」という理由で手順を省略しません。宣言済みの
code-logger.pyコマンド以外で、タスクの state-machine を独自に変更しません。
メンタルモデル
diff → typecheck → lint → test → qc-regression → task_lifecycle gate → smoke → commit (why) → promote draft (+ ## Origin) → log + index → task state=done。
入出力の契約
| Field | Required? | 意味 | |
|---|---|---|---|
| In | 実装済みのコード変更 | はい | ゲートの対象 |
| In | llmwiki/wiki/sources/draft/ 内の機能に対応する draft | いいえ | ない場合(hotfix/refactor)は、log に「no draft — 」と記録 |
| In | draft の frontmatter にある task: T-… | いいえ | ない場合はステップ 8 をスキップ(fail-open) |
| Out | commit | はい | what ではなく why を示すメッセージ |
| Out | ## Origin を含む昇格済みの wiki ページ | draft がある場合 | concepts/ または sources/ |
| Out | llmwiki/wiki/log.md + index.md | はい | 更新 |
ルールと機能
- RULE-01(MUST):すべてのステップが必須です。例外はありません。
- RULE-02(MUST):コミット後の処理は必須です。決してスキップしないでください。
- 機能:リポジトリの typecheck/lint/test/smoke を実行します(manifest から自動検出)。利用可能な場合は validator harness を実行します。git commit、wiki、およびタスクのライフサイクルログを記録します。
失敗時の境界
- Typecheck/lint/test が失敗 → blocked:修正して再実行し、コミットしません。
qc-regression.py --runが失敗 → blocked(修正済みのバグが再発、または未修正)。qc-*テストがない場合は fail-open とし、ブロックしません。task_lifecycle.pyがブロック(task-ID が state-machine に適合しない) → blocked。ファイルがない場合(古いインストール)はスキップします。- draft がない場合 → 昇格せず、理由を log に記録します(限定的な succeeded)。
task:ID がない場合はステップ 8 をスキップし、エラーとはしません。
HOW
メインワークフロー
| ステップ | 種類 | 入力 | アクション | 出力/終了条件 | 失敗時/次の処理 |
|---|---|---|---|---|---|
| W01 | 決定論的 | repo | 型チェック(リポジトリからコマンドを検出) | rc 0 | エラー → 修正して繰り返す |
| W02 | 決定論的 | repo | Lint | rc 0、警告を記録 | エラー → 修正して繰り返す |
| W03 | 決定論的 | repo | テスト + qc-code 再現テスト(3b、ハーネスがある場合) | rc 0 | 失敗 → 修正して繰り返す |
| W04 | 決定論的 | draft/task | 第3の柱ゲート task_lifecycle.py(ハーネスがある場合) | rc 0 | ブロック → blocked |
| W05 | 判断 | app | ゴールデンパスのエンドツーエンドのスモークチェック | ゴールデンパスが動作 | 破損 → 修正 |
| W06 | 効果 | diff | コミット、理由 をメッセージに記載 | commit hash | — |
| W07 | 効果 | draft | draft を昇格 + ## Origin + ログ + インデックス | wiki ページ | draft なし → B01 |
| W08 | 効果 | task: id | code-logger.py でタスクのライフサイクルを完了(ベストエフォート) | state=done | id なし → B02 |
各ステップの詳細(W01~W08 の正となる情報源。W01~W03 = ステップ1~3b、W04 = 4、W05 = 5、W06 = 6 のコミット前、W07 = 6~7 のコミット後、W08 = 8):
コミット前:
RUN: <type-check-cmd>— リポジトリから検出します:npx tsc --noEmit(package.json)/go build ./...(go.mod)。すべてのエラーを修正します。RUN: <lint-cmd>— 検出します:npx eslint src//go vet ./...。エラーを修正し、警告を記録します。RUN: <test-cmd>— 検出します:npm test/go test ./...。失敗を修正します。 3b. qc-code 再現テスト(ハーネスがある場合):RUN: [ -f harness/scripts/qc-regression.py ] && python3 harness/scripts/qc-regression.py --run—/qc-codeが生成したqc-*テスト(発見したバグを再現するテスト)を実行します。赤 = 修正済みのバグが再発したか、まだ修正されていません。完全に決定論的で、0 トークン、LLM を呼び出しません。qc-*テストがまだない場合(プロジェクトで qc-code を使っていない場合)はフェイルオープンし、ブロックしません。- 第3の柱ゲート(ハーネスがある場合):
RUN: [ -f harness/validators/task_lifecycle.py ] && python3 harness/validators/task_lifecycle.py --root .— task-ID がステートマシンに反する状態遷移(逆戻り/飛び越し/ゲート回避)を行った場合、または draft が不明なタスクを参照している場合は、ハードブロックします。ファイルがない場合(旧インストール)はスキップします。これは、以下のステップ8のベストエフォート処理を強制化したものです。 - スモークチェック:ゴールデンパスがエンドツーエンドで動作することを確認します。
- メッセージには 内容 ではなく 理由 を記載してコミットします。
コミット後 — 必須。絶対にスキップしないでください:
6. llmwiki/wiki/sources/draft/ から機能に一致する draft を探します。
llmwiki/wiki/concepts/またはllmwiki/wiki/sources/に昇格します(永続化)。## Originセクションを追加します:Draft: <path>/Commit: <hash> — <msg>/Date: YYYY-MM-DDCHECK: grep -l "## Origin" <promoted-file>— ファイルが返される必要があります。
RUN: echo "promoted" >> llmwiki/wiki/log.mdを実行し、ログを適切に編集してからllmwiki/wiki/index.mdを更新します。- 第3の柱 — ライフサイクルの完了(ベストエフォート、フェイルオープン): draft の frontmatter に
task: T-…がある場合 →python3 harness/scripts/code-logger.py --task set <T-id> state=done note="<commit-hash>"を実行します。このコマンドはフェイルオープンです(--task/id がない場合はスキップし、コミットをブロックしません)。確認:--task show <T-id>が lifecycle proposed→approved→dispatched→done を出力し、--auditで transition が不変のチェーン内にあることを検証します。
draft がない場合(hotfix/refactor):log.md に "no draft — " と記録し、ステップ6をスキップします。
task:id がない場合(旧インストール/propose が mint をスキップ):ステップ8をスキップします — フェイルオープンであり、エラーではありません。
すべてのステップが必須です。例外はありません。
分岐
| ID | 種類 | ガード条件 | 動作 | スキップ/失敗 | 再合流 |
|---|---|---|---|---|---|
| B01 | 条件付き必須 | draft がない(hotfix/refactor) | log.md に "no draft — " と記録し、コミット後のステップ6をスキップ | — | W08 |
| B02 | 条件付き必須 | draft に task: id がない(旧インストール/propose が mint をスキップ) | ステップ8をスキップ — フェイルオープン | — | 終了 |
| B03 | 機能があれば実行 | harness/ がある(qc-regression、task_lifecycle、code-logger) | 3b、4、8 を実行 | ファイルがない場合 → スキップ、フェイルオープン | 次のステップ |
検証と停止条件
決定論的な検証:typecheck/lint/test/qc-regression/task_lifecycle の rc。CHECK: grep -l "## Origin" <promoted-file> でファイルが返されること。--task show <T-id> + --audit でライフサイクルを確認します。レビューが必要:ゴールデンパスのスモークチェック。コミット前後のすべてのステップが完了したら停止します。コミット前に赤が出た場合はコミットしません。
例
- 成功例: リポジトリに
package.jsonがある →npx tsc --noEmit、npx eslint src/、npm testが成功、qc-regression.py --runが成功 → 「なぜ」を記したコミット → 下書きDDMMYY-login-otp.mdをwiki/concepts/に昇格し、## Originを追加 →code-logger.py --task set T-12 state=done note="<hash>"。 - 境界・失敗例:
go test ./...で1つのテストが失敗 → W03 で停止して修正し、再実行します。まだコミットしません。下書きのないホットフィックス → 「下書きなし — ホットフィックスのタイプミスを修正」と記録し、昇格をスキップします。
納品 — 出力レポート
スキルの主要タスクがすべて完了した後、wiki に提案用の下書きを作成します。
手順
1. ファイル名を作成します:
- 形式:
DDMMYY-<ten>.md DDMMYY= 今日の日付(例:2026年6月2日の場合は020626)<ten>= 実施内容を要約する2〜4語のケバブケース(例:landing-page-coteccons、brand-kit-fintech、ingest-auth-spec)
2. llmwiki/wiki/sources/draft/DDMMYY-<ten>.md を作成します:
---
type: draft
title: "DDMMYY-<ten>"
status: proposed
tags: [<skill-name>, output-report]
timestamp: YYYY-MM-DD
---
# DDMMYY-<ten>
**Type:** draft
**Status:** proposed
**Tags:** <skill-name>, output-report
**Proposed:** YYYY-MM-DD
## What
<One sentence — what this skill invocation produced or decided>
## Output
<Key artefacts, files created/modified, or decisions made>
## Files
| File | Action |
|------|--------|
| `path/to/file` | created / modified |
## Notes
- Invoked via: `/<skill-name>` skill
## Origin
- **Draft:** `wiki/sources/draft/DDMMYY-<ten>.md`
- **Commit:** _(filled by verify-before-commit)_
- **Date promoted:** _(filled by verify-before-commit)_
3. wiki のインデックスとログを更新します:
llmwiki/wiki/index.md— 1行追加します:| [DDMMYY-<ten>](sources/draft/DDMMYY-<ten>.md) | draft | YYYY-MM-DD |llmwiki/wiki/log.md— 次の行を追加します:## YYYY-MM-DD — <skill-name> — <ten>
スキルが成果物も決定事項も一切生み出さない場合に限り、スキップします(例:
/caveman-statsのような表示のみのモード)。