mcpField
E
entropy-check

entropy-check

github.com/fellowship-devテスト・品質3192 回インストール2 週間前に更新
リポジトリ

entropy-check について

Entropyは、リポジトリ内の各領域について、ドキュメントや関連する品質シグナルを評価する読み取り専用スキルです。適用可能なシグナルを採点して報告し、QUALITY_SCORE.mdを更新できますが、問題の修正は行いません。

主な機能

  1. 01機械的なシグナルによる領域品質の採点
  2. 02ドキュメントの網羅性と古さの確認
  3. 03フロー、課題、テスト、Hookshotのシグナル評価
  4. 04PR対象とリポジトリ全体のスキャン
  5. 05結果をQUALITY_SCORE.mdに反映

活用シーン

  1. 01PRマージ後のドキュメント確認
  2. 02定期的なリポジトリ全体の品質スキャン
  3. 03リファクタリング前の状態把握
  4. 04古い、または不足しているドキュメント領域の特定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/fellowship-dev/dogfooded-skills --skill entropy-check

インストール後、Claude Code で/entropy-checkを入力して読み込まれたか確認します。

同梱ファイルscripts/contents-writeback.shtests/contents-writeback.test.sh

詳細

Entropy

センサー。検出し、評価し、報告します。修正は一切しません。

npx でインストール:

npx skills add fellowship-dev/dogfooded-skills/skills/ops/entropy-check

使用する場面

  • イベント駆動(PR のマージ時): PR のマージ後にトリガーされます。影響を受けるドメインをスキャンし、ドキュメントの古さを確認します。
  • 週次 cron(全体スキャン): 各製品リポジトリに対して実行され、最新の評価で QUALITY_SCORE.md を更新します。
  • 手動: ドキュメントが実装と乖離している疑いがある場合や、リファクタリング前に現在の健全性スナップショットを確認したい場合に実行します。

概要

Entropy は読み取り専用のセンサーです。機械的な指標からドメインの品質評価を算出します。

指標測定内容重み
ドキュメントの網羅性docs/code-structure.md はこのドメインを網羅していますか?二値
フローの網羅性重要なパスに FlowChad フローが定義されていますか?二値(フロントエンドリポジトリのみ)
古さの差最後のコードコミットから最後のドキュメント更新までの日数30 日超=古い
未解決のイシューGitHub でこのドメインに関連付けられたイシュー未解決が 3 件超=シグナル
テストカバレッジ利用可能な場合、カバレッジレポートから取得60% 未満=シグナル
Hookshot の網羅性doc-coverage.json はドキュメントに対して最新ですか?古さ

評価基準:

  • A — 適用されるすべての指標が良好
  • B — 適用される指標のうち、1 つが欠落または黄色
  • C — 適用される指標のうち、2 つが欠落
  • D — 適用される指標のうち、3 つ以上が欠落
  • F — このドメインのドキュメントがまったくない

適用されない指標は、評価の分母から除外されます。適用される 4 つの指標がすべて合格したリポジトリの評価は A です。


手順

0. 対象リポジトリの特定
REPO_ROOT=$(git rev-parse --show-toplevel)
REPO_NAME=$(basename $(git remote get-url origin) .git)
ORG=$(git remote get-url origin | sed 's/.*github.com[:/]\([^/]*\).*/\1/')
FULL_REPO="$ORG/$REPO_NAME"
TODAY=$(date +%Y-%m-%d)

QUALITY_SCORE.md が存在する場合は読み込み、更新の基準とします。 ARCHITECTURE.md が存在する場合は読み込み、ドメイン一覧を抽出します。 どちらも存在しない場合は、ディレクトリ構成(トップレベルのソースディレクトリをそれぞれ 1 つのドメインとする)からドメインを推定します。

1. 指標の適用可否を判定

評価の前に、このリポジトリに適用される指標を判定します。レポートに適用可否を記録してください。

フロントエンドの検出(S2 FlowChad)
HAS_FRONTEND=false
if [ -f "$REPO_ROOT/package.json" ]; then
  grep -q '"next"\|"react"\|"vue"\|"angular"\|"svelte"' "$REPO_ROOT/package.json" && HAS_FRONTEND=true
fi
if [ -d "$REPO_ROOT/app" ] || [ -d "$REPO_ROOT/pages" ] || [ -d "$REPO_ROOT/src/components" ]; then
  HAS_FRONTEND=true
fi

HAS_FRONTEND=false の場合、S2 FlowChad は適用されません。評価の分母から除外してください。

Hookshot の検出(S6)
HOOKSHOT_EXISTS=false
git -C "$REPO_ROOT" log -1 --format="%ci" -- .claude/doc-coverage.json 2>/dev/null | grep -q . && HOOKSHOT_EXISTS=true
[ -f "$REPO_ROOT/.claude/doc-coverage.json" ] && HOOKSHOT_EXISTS=true

S6 は常に適用されますが、スコアのメッセージは異なります。以下の「指標 6」を参照してください。

2. 対象範囲の決定

PR トリガーモード: PR 番号が指定された場合、変更されたファイルを特定します。

# Get changed files from PR
GH_TOKEN=$GH_TOKEN gh api repos/$FULL_REPO/pulls/{PR_NUMBER}/files \
  --jq '.[].filename'

ディレクトリのプレフィックスを使って、変更された各ファイルをドメインに対応付けます。変更のあるドメインのみ評価します。

全体スキャンモード: すべてのドメインを評価します。ARCHITECTURE.md からドメイン一覧を読み込むか、推定してください。

3. ドメインごとの評価

対象範囲内の各ドメインについて、次を行います。

指標 1:ドキュメントの網羅性
# Is this domain mentioned in docs/code-structure.md?
grep -i "{domain_name}" $REPO_ROOT/docs/code-structure.md 2>/dev/null && echo "COVERED" || echo "MISSING"

スコア:✅ 網羅されている / ❌ 欠落

指標 2:FlowChad の網羅性

HAS_FRONTEND=false の場合は完全にスキップしてください。適用可否の表には「N/A — フロントエンドを検出できませんでした」と記録してください。

# Only run if HAS_FRONTEND=true
if [ "$HAS_FRONTEND" = "true" ]; then
  ls $REPO_ROOT/.flowchad/flows/ 2>/dev/null | grep -i "{domain_slug}" && echo "COVERED" || echo "MISSING"
fi

スコア(フロントエンドのみ):✅ フローあり / ❌ フローなし

指標 3:古さの差

このドメイン内のファイルについて、最も新しいコードコミットの日付を確認します。

# Last commit touching domain files
git -C $REPO_ROOT log -1 --format="%ci" -- "{domain_directory_glob}" 2>/dev/null

ドメインのドキュメントセクションの最終更新日を確認します。

# Last commit touching docs/code-structure.md
git -C $REPO_ROOT log -1 --format="%ci" -- docs/code-structure.md 2>/dev/null

差は、最後のコードコミットから最後のドキュメント更新までの日数です。 スコア:✅ 差が 30 日以内 / ⚠️ 差が 31~60 日(黄色) / ❌ 差が 60 日超

指標 4:未解決のイシュー
# Open issues tagged to this domain (use domain name as label or search term)
GH_TOKEN=$GH_TOKEN gh issue list --repo $FULL_REPO \
  --state open --search "{domain_name}" \
  --json number,title | jq length 2>/dev/null || echo "0"

スコア:✅ 未解決が 0~3 件 / ⚠️ 未解決が 4~6 件(黄色) / ❌ 未解決が 6 件超

指標 5:テストカバレッジ
# Look for coverage reports
ls $REPO_ROOT/coverage/ $REPO_ROOT/.nyc_output/ $REPO_ROOT/tmp/coverage/ 2>/dev/null
cat $REPO_ROOT/coverage/index.html 2>/dev/null | grep -o '[0-9.]*%' | head -1
# Rails: simplecov
cat $REPO_ROOT/coverage/.last_run.json 2>/dev/null | jq '.result.covered_percent'

カバレッジレポートが利用できない場合、この指標はスキップします(中立として扱い、❌にはしません)。 スコア:✅ 80% 以上 / ⚠️ 60~79% / ❌ 60% 未満(カバレッジデータがある場合のみ)

指標 6:Hookshot カバレッジの古さ
COVERAGE_DATE=$(git -C $REPO_ROOT log -1 --format="%ci" -- .claude/doc-coverage.json 2>/dev/null)
DOCS_DATE=$(git -C $REPO_ROOT log -1 --format="%ci" -- docs/code-structure.md 2>/dev/null)

次の 2 つのケースを区別します。

  • Hookshot が未設定 — .claude/doc-coverage.json が一度も存在したことがない(Git 履歴がなく、ファイルも存在しない): スコア:❌「Hookshot が未設定 — セットアップを推奨」

  • Hookshot が古い — ファイルが存在したことがある(Git 履歴で確認できる)が、ドキュメントのほうが新しく更新されている: スコア:⚠️「Hookshot が古い(カバレッジ {COVERAGE_DAY} < ドキュメント {DOCS_DAY})」— 日数ではなくコミット日

  • Hookshot が最新 — カバレッジがドキュメントの更新後、または同日に更新されている: スコア:✅「Hookshot は最新」

検出ロジック:

if [ -z "$COVERAGE_DATE" ] && [ ! -f "$REPO_ROOT/.claude/doc-coverage.json" ]; then
  # Never been set up
  S6_SCORE="❌"
  S6_NOTE="Hookshot not configured — recommend setup"
elif [ -n "$DOCS_DATE" ] && [ -n "$COVERAGE_DATE" ]; then
  # Both exist — compare dates
  DOCS_EPOCH=$(date -d "$DOCS_DATE" +%s 2>/dev/null || date -j -f "%Y-%m-%d %H:%M:%S %z" "$DOCS_DATE" +%s 2>/dev/null)
  COV_EPOCH=$(date -d "$COVERAGE_DATE" +%s 2>/dev/null || date -j -f "%Y-%m-%d %H:%M:%S %z" "$COVERAGE_DATE" +%s 2>/dev/null)
  STALE_DAYS=$(( (DOCS_EPOCH - COV_EPOCH) / 86400 ))
  if [ "$STALE_DAYS" -gt 0 ]; then
    S6_SCORE="⚠️"
    S6_NOTE="Hookshot stale (coverage ${COVERAGE_DATE%% *} < docs ${DOCS_DATE%% *})"
  else
    S6_SCORE="✅"
    S6_NOTE="Hookshot current"
  fi
else
  S6_SCORE="❌"
  S6_NOTE="Hookshot not configured — recommend setup"
fi
グレードの算出

該当するシグナルのみを収集します。該当するシグナルのうち、失敗したシグナル(❌)のみをカウントします。

APPLICABLE_SIGNALS = all signals minus inapplicable ones
FAILING = count of ❌ in APPLICABLE_SIGNALS
YELLOW = count of ⚠️ in APPLICABLE_SIGNALS
SCORE = FAILING + (YELLOW * 0.5), rounded up
  • SCORE = 0 → A
  • SCORE = 1 → B
  • SCORE = 2 → C
  • SCORE ≥ 3 → D
  • ドキュメントがまったくない場合 → F

例:フロントエンドがないリポジトリ(S2 はスキップ)で、該当するシグナルが 5 つすべてグリーンの場合、グレードは B ではなく A です。

4. QUALITY_SCORE.md を更新する

既存のファイルを読み込みます。グレードを算出した各ドメインの行を更新します。新しいドメインが見つかった場合は追加します。 対象外のドメインの既存の行は保持します(再スキャンした内容のみを更新します)。

## Domains

| Domain | Grade | Last audit | Notes |
|--------|-------|------------|-------|
| {domain} | {grade} | {TODAY} | {brief note on what's missing, or "All signals green"} |

更新したファイルを書き込み、次に History セクションへ追記します。

| {TODAY} | {trigger: PR #{N} / weekly sweep / manual} | {N} domains scanned, {N} regressions, {N} improvements |
4a. 書き戻しをインテグレーションブランチに直接コミットする — ブランチも PR も作成しない

オーナーの決定(2026-10-07):書き戻しは [skip ci] を付けて、スキャン対象リポジトリの インテグレーションブランチに直接コミットします。ブランチや PR は作成しません。同じ書き戻しを行う PR はすべて QUALITY_SCORE.md を編集し、マージのたびに競合してレビューの一連の処理を繰り返していました。

  • ブランチ: 実行時に解決する、リポジトリのデフォルトブランチ(リリース時に develop → main へ昇格する fellowship-dev/pylot では develop)。ブランチ名をハードコードしないでください。
  • 方法: git push ではなく、scripts/contents-writeback.sh を通じた GitHub Contents API を使用します。 Pylot ワーカーの git-push-guard.sh は main/master/develop へのプッシュを拒否します (パスを限定した許可は fellowship-dev/pylot#3555 ですが、まだリリースされていません)。拒否されたプッシュを再試行したり、 別の回避策を探したりしないでください。
  • 対象範囲: QUALITY_SCORE.md のみです。このヘルパーは、それ以外のパスや [skip ci] を含まないメッセージを拒否します(終了コード 2)。 実行を明示的に失敗させてください。この方法で別のファイルを書き込んではいけません。
  1. 変更なし → 報告のみ。 グレードが変更されず、ドメインも追加されず、新しい Tooling のドリフトも見つからなかった場合、変更は History の行だけです。これを破棄して、コミットは行わず、ステップ 8/9 のレポートを投稿して終了します。
  2. それ以外はコミット。 ブランチの最新ファイルを取得し、この実行での編集を適用して、次のようにします。
WB="${PYLOT_WORKSPACE:-$HOME/.claude}/skills/entropy-check/scripts/contents-writeback.sh"
BASE=$(GH_TOKEN=$GH_TOKEN gh repo view "$FULL_REPO" --json defaultBranchRef --jq .defaultBranchRef.name)
MSG="chore: entropy scan — PR #{N} {title} [skip ci]"   # weekly/manual: chore: entropy scan — weekly sweep $TODAY [skip ci]
FRESH=$(mktemp)
SHA=$(GH_TOKEN=$GH_TOKEN bash "$WB" fetch "$FULL_REPO" "$BASE" "$FRESH")

この実行での行の更新、新しいドメイン、Tooling セクション、History の行を、ブランチの現在の内容である $FRESH に再適用します。その際、その他の行はすべてそのまま保持してください。次に:

GH_TOKEN=$GH_TOKEN bash "$WB" put "$FULL_REPO" "$BASE" QUALITY_SCORE.md "$FRESH" "$SHA" "$MSG"; echo "rc=$?"

rc=0 の場合はコミット SHA が出力されます。rc=3 は SHA が古くなったことを意味します(HTTP 409/422 — 別の書き戻しが先に反映されています)。再取得して再適用してください。試行回数は合計 3 回までです。それ以外のコードが返された場合、または 3 回目に rc=3 が返された場合は、実行を明示的に失敗させます。

  • 必ず新たに取得した内容を編集してください。古いローカルコピーで上書きしてはいけません。
  • コミットメッセージには文字列どおりの [skip ci] タグを含め、コミットによって CI やデプロイが実行されないようにします。
  • 直接コミットでは PR が作成されないため、マージ後のエントロピールールが再実行されることはありません。
  • コミットが反映された時点で実行は完了です。ステップ 8 用にコミット URL を記録します。
5. シグナルの該当性セクション

すべてのレポート出力に「Signal Applicability」テーブルを含めます。

## Signal Applicability

| Signal | Applicable? | Reason |
|--------|------------|--------|
| S1 Doc Coverage | Yes | — |
| S2 FlowChad | No | No frontend framework detected (bash/python scripts only) |
| S3 Staleness | Yes | — |
| S4 Open Issues | Yes | — |
| S5 Tests | Yes | No test framework found — recommend adding bats for shell scripts |
| S6 Hookshot | Yes | — |

Reason 列には具体的な内容を記入します。

  • S2 が非該当:「フロントエンドフレームワークが検出されませんでした」に加えて、見つかったもの(例:「bash/python スクリプトのみ」、「Go/Rails リポジトリ」)
  • S2 が該当:検出されたフレームワークを列挙します(例:「package.json で Next.js を検出」)
  • S5 のデータなし:「カバレッジレポートが見つからないため、シグナルをスキップ」
  • S5 のデータあり:Reason は空欄のままにするか、カバレッジ率を記入します
  • S6:常に該当します。Reason には hookshot のステータスの詳細を記入します
6. 古さのレポート

C、D、F のいずれかにグレード付けされたドメイン、または前回からグレードが下がったドメインについて、所見を出力します。

## Entropy Findings — {TODAY}

### Regressions (grade dropped)
- {Domain}: {old grade} → {new grade}
  Missing: {list of failing signals}
  Last doc update: {date}
  Last code commit: {date}

### Stable issues (same low grade)
- {Domain}: {grade} (unchanged since {date})
  Missing: {list}

### Improvements (grade improved)
- {Domain}: {old grade} → {new grade}

### Clean (A or B)
- {Domain}: {grade}
7. インポート済みライブラリのドリフト(アーキテクチャチェック)

このチェックはメンテナンスからここに移動しました。 インフラチェックではなく、アーキテクチャシグナルです。

廃止済み:インポートされたコマンドのドリフトチェックは、現在使われていないワークフローを対象としていました。 このステップはスキップしてください。報告する ## Tooling のドリフトはありません。

8. PR をトリガーとする出力

PR のマージイベントによってトリガーされた場合、ステップ 4a が完了した後(書き戻しをコミットするか、報告のみとするかを決定した後)に、コメントとして投稿できる要約を出力し、マージされた PR に投稿します。

## Entropy Scan — PR #{N} merged

Domains affected: {list}
Write-back: {commit URL on the default branch, or "none — no QUALITY_SCORE.md change"}

| Domain | Grade | Change | Notes |
|--------|-------|--------|-------|
| {domain} | {grade} | {→ or unchanged or ↑ or ↓} | {note} |

{If any regressions:}
⚠️ Doc staleness detected in: {domain list}
Recommended: update docs/code-structure.md for these domains before the next PR in this area.

コメントの末尾に「Signal Applicability」テーブルを含めます(ステップ 5 を参照)。

9. 全件スイープの出力(週次 cron)
## Entropy Weekly Sweep — {DATE}

{N} domains across {REPO_NAME}

### Grades
{Full grade table}

### Signal Applicability
{Signal applicability table}

### Action Items
{Domains graded D or F → recorded via file-finding.sh (existing issue or weekly digest)}

D/F ドメインの場合は、共有の報告ヘルパー(pylot-cli → scripts/file-finding.sh)を使って検出結果を記録します。古いドキュメントはブロッキングではないため、ヘルパーは同じドメインまたはアプリに関するオープンな issue にコメントするか、週次の digest issue に追記します。新しい issue を作成することはありません:

FF="${PYLOT_WORKSPACE:-$HOME/.claude}/skills/pylot-cli/scripts/file-finding.sh"
GH_TOKEN=$GH_TOKEN bash "$FF" --repo "$FULL_REPO" \
  --title "Entropy: {domain} docs critically stale (grade {grade})" \
  --search "\"{domain} docs critically stale\"" \
  --body "Domain **{domain}** scored **{grade}** in the weekly entropy scan.

**Missing signals:**
{list}

**Last code commit to this domain:** {date}
**Last doc update:** {date}

Fix: update \`docs/code-structure.md\` and run \`/hookshot\` to regenerate hooks."

コメント