ship-a-feature について
`CLAUDE.md`とnpmスクリプトを使うプロジェクト向けの機能リリースSkillです。機能の到達性、文書化、見つけやすさ、安定性マーク、変更のないツリーでのゲート実行を確認します。
主な機能
- 01エクスポート入口の到達性確認
- 02未文書化API変更の検出
- 03文書化と見つけやすさの確認
- 04安定性マークの確認
- 05凍結ツリーでのゲート実行
活用シーン
- 01新しいエクスポート機能の検証
- 02公開ドキュメントの不足検出
- 03関連文書から機能へリンクされているか確認
- 04マージ前のプロジェクトチェック
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ zernie/ vigiles --skill ship-a-featureインストール後、Claude Code で/ship-a-featureを入力して読み込まれたか確認します。
同梱ファイルscripts/ship-check.mjsship-a-feature.harness.mjs
詳細
機能を出荷する(中途半端にせず、きちんと出荷する)
完了の定義は9項目からなり、すでに CLAUDE.md の
cohesive-feature-delivery にあります。2026-09-02、equivalentDisasters はテスト済みで、ゲートを通過し、コミットされて出荷されましたが、次の4項目で気づかれないまま失敗しました。すべての公開経路から到達できないこと、隣接するコードのJSDocをひそかに奪っていたこと、ドキュメントがないこと、安定性のマークがないことです。2000行のファイルに書かれた文章では機能しません。こちらは機能します。以下の各チェックには、それが対処するために書かれた失敗が明記されています。ここにあるのは理論ではありません。
1. 書き始める前に — あなたにしか決められない3つのこと
| 決定 | 基準 |
|---|---|
どの経路か?(package.json の exports サブパス) | 無料で決定論的 → .(src/test.ts)。モデルに課金する → ./eval(paid_ プレフィックス)。フックの語彙 → ./hook。経路のバレルから再エクスポートされていないシンボルは、require("vigiles") からは存在しません(失敗1)。 |
安定版か、それとも experimental_ か? | STABILITY.md:エクスポートされていて安定版ではない場合 ⇒ @experimental タグと experimental_ という名前が必要です。公開から1日で利用者が1人いても、安定版ではありません。ESLint の local/experimental-name はタグから名前への対応を確認しますが、タグは付与できません(失敗4)。 |
WHY(理由)を公開する場所は?(document-the-why) | 変更する主張のすぐそばにある docs/*.md のセクションです。equivalentDisasters の場合は、docs/compiled-hooks.md の「blocks 7/7」の隣です。READMEではなく(簡潔さを保つため)、このファイルでもありません(コントリビューター向けの階層です)。 |
回答をPR本文に記載してください。以下のスクリプトは、安定性の項目について回答が明記されるまで合格を認めません。
2. 実装後 — 1 つのコマンドで 5 つのチェック
npm run build
node .claude/skills/ship-a-feature/scripts/ship-check.mjs <symbol> [--stable "<why it is stable>"]
| チェック | 実行内容 | 対応する実測済みの失敗 |
|---|---|---|
| REACHABLE | ビルド済みの dist/ からすべての exports サブパスを import() し、シンボルが ≥ 1 つのキーであることを確認します | src/guardrail-check.ts に equivalentDisasters があり、src/test.ts にはない → undefined (1) |
| SURFACE | api-surface/ を再生成(api:report)し、その後 git diff を読み込みます。+… (undocumented) があれば失敗します | verifyGuardrail の JSDoc と宣言の間に挿入されました。diff には表示されていたのに、誰も読みませんでした (2) |
| DOCUMENTED | \b<symbol>\b が docs/**/*.md または README.md に含まれている必要があります | 指摘されるまで公開先がありませんでした (3) |
| FINDABLE | 2 つのページで名前を記載する必要があります。または、1 つで名前を記載し、別のページからそのセクションのアンカーにリンクする必要があります | 1 度だけ、別の機能についてのガイド内で説明され、そこへのリンクもありませんでした (5) |
| MARKED | 宣言の JSDoc に @experimental を記載するか、名前に接頭辞を付けるか、--stable "<why>" を渡します | 1 日前にエクスポートされたものにタグも接頭辞もなく、lint ルールが検出する手がかりはありませんでした (4) |
DOCUMENTED と FINDABLE は異なる問いです。 前者は、その機能についてどこかに記述されているかを問います。後者は、どのファイルを開けばよいかを知らない読者が、その機能にたどり着けるかを問います。experimental_equivalentDisasters(後に experimental_alternateSpellings に改名)は前者を通過し、後者で失敗しました。別の機能のガイド内にある独自の見出しの下で 1 度だけ説明され、そこへのリンクがなかったため、「自分のガードは実際にブロックするのか」と尋ねる人が参照するテストガイドには、その名前が一度も記載されていませんでした。リンクを 1 つ示せば FINDABLE を満たします。説明を繰り返す必要はありません。
✗ は修正して再実行することを意味します。スクリプトは各検出項目の横に修正方法を表示します。✓ MARKED stable の行には理由が記載されるので、PR の本文に貼り付けてください。
3. ゲート — ツリーを凍結し、フォアグラウンドで、実際の終了コードを確認する
node .claude/skills/ship-a-feature/scripts/ship-check.mjs --gate # = npm run check, frozen
実行前後のツリーをハッシュ化し、ゲートの実行中に変更があれば失敗します。ゲートが不正確な結果を返す実測済みの 3 つの方法と、この方法での対策を示します。
- 実行中の編集 (5):
npm run checkが書きかけのファイルを lint し、どの状態にも属さないエラーで失敗しました。終了するまでツリーに触らないでください。 until ! pgrep -f 'check.mjs'で待機すること (6):待機中のシェル自身のコマンドラインがパターンに一致するため、処理が終わりません。20 分間「まだ実行中」と報告されました。ゲートはフォアグラウンドで実行してください。バックグラウンドで実行する必要がある場合は、自分で起動した PID に対してwaitしてください。自分のコマンドに含まれる文字列をpgrep -fで検索してはいけません。npx vitest run … | tail -8(7):パイプラインの終了ステータスはtailのものです。テストが 3 件失敗していても終了コードは 0 になります。ゲートの後にパイプをつなげてはいけません。ファイルにリダイレクトしてから内容を確認してください。
すでに機械的に検証されています — 呼び出すだけにして、再度記載しないでください
| プロパティ | 担当(重複させないでください) |
|---|---|
タグ @experimental ⇒ experimental_ 名 | ESLint local/experimental-name(npm run lint 内) |
./eval のシンボルに paid_ が付いている | npm run exports:check(npm run check 内) |
| コミット済みスナップショットとの差分 | npm run api:check(npm run check 内) |
ドキュメントの ts ブロックが実際のエクスポートをインポートしている | npm run docs:check — ドキュメントが存在する場合に限る(3) |
docs/ に記載されているすべての CLI 動詞 | src/doc-command-coverage.ts — 動詞のみ。API シンボルは対象外 |
| コマンド一覧全体 | npm run check(node scripts/check.mjs --list で一覧を表示) |
4. 完了の定義
5 つの ✓ 行、✓ GATE 行、そして door・安定性の判断・ドキュメントのセクション名を記載した PR 本文が揃っていることです。import できない機能は機能ではなく、たどり着けないものはドキュメント化されていません。