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. 04支持 PR 范围扫描和全仓扫描
  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

详细介绍

熵

传感器。检测、评级、报告。绝不修复。

通过 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. 确定信号是否适用

评级前,确定哪些信号适用于此仓库。记录报告中的适用情况。

前端检测(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)

区分以下两种情况:

  • 未配置 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 个适用信号全部为绿色 → 等级为 A,而不是 B。

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,每次合并都会产生冲突,还会重复触发完整的审查流程。

  • 分支: 仓库的默认分支,在运行时解析(fellowship-dev/pylot 使用 develop,其发布流程会将 develop → main)。切勿硬编码。
  • 机制: 通过 scripts/contents-writeback.sh 调用 GitHub Contents API,而非使用 git push。Pylot worker 的 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 次。任何其他代码,或第三次出现 rc=3,都表示运行失败,必须明确报告。

  • 始终编辑刚刚获取的内容;绝不能用过期的本地副本覆盖它。
  • 提交消息保留字面标记 [skip ci],确保该提交不会触发 CI 或部署。
  • 直接提交不会创建 PR,因此不会再次触发合并后的熵规则。
  • 提交成功后本次运行即完成;记录提交 URL,用于步骤 8。
5. 信号适用性部分

在每份报告输出中都包含一个「信号适用性」表格:

## 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. 导入的 Lib 漂移(架构检查)

此检查已从维护部分移至此处。 这是架构信号,而非基础设施检查。

已废弃:导入命令漂移检查针对的是已不再使用的工作流。 跳过此步骤;无需报告 ## 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.

在评论末尾包含「信号适用性」表格(见步骤 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."

评论

支持 Markdown