Community研究与数据分析github.com

chrislacey89/excavate(遗留仓库挖掘)

用户调用的侧路技能,用于接入一个没有文档、解决方案、研究档案或书面决策的遗留仓库。挖掘最近12个月的git历史(以及当gh可用时的PR正文和审查线索),生成排序后的热点、引用的恢复决策、以及一个询问人员的地图,然后提供一个包含docs/solutions/条目的PR。不适用于已经复合的仓库、评判他人或模型自动调用。

excavate(遗留仓库挖掘) 是什么?

Excavate 是一个用户调用的侧路技能,专为遗留仓库的接入设计。它能通过分析最近12个月的Git历史(包括PR正文和审查线索,当gh可用时),自动生成一份详尽的离树档案,包括:按变更频率和复杂度代理(LOC)加权排序的热点区域、耦合分析、恢复的架构决策、一个人员询问地图(who-to-ask map),以及一份覆盖范围报告,明确说明历史记录能/不能告诉我们什么。该技能严格遵循Tornhill的版本控制行为分析方法论,确保热点是概率性的诊断,而非裁决。输出还包括一个基于`/compound`格式的可选PR,用于创建`docs/solutions/`条目,使得其他技能(如`/research`、`/write-a-prd`、`/execute`)能够通过关键字grep来引用这些文档。Excavate 的使用场景仅限于遗留仓库的首次接入,不应在已经运行过`/compound`的仓库或进行人员绩效评估时使用。该技能在设计上禁止模型自动调用,要求全程人工参与(HITL),并严格遵循“接地规则”:所有SHA、PR编号、路径、计数和引用的解释都直接从`git`和`gh`输出中复制,模型仅负责撰写周围的说明文字。该技能最终与主流水线通过`/shape`技能连接,以指导首次特性的构建。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/chrislacey89/skills/tree/HEAD/excavate

Installed? Explore more 研究与数据分析 skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

excavate(遗留仓库挖掘) 是做什么的?

在首次功能特性盲目投入之前,恢复遗留仓库已经记录的自知信息。输出内容包括一份离树档案(热点、耦合关系、恢复的决策、询问人员地图,以及说明历史记录能/不能告诉我们什么的覆盖范围块),以及一个基于/compound格式的可选docs/solutions/条目PR,以便/research、/write-a-prd和/execute通过它们已有的关键字grep机制读取这些条目。

有两件事保持其诚实性。Tornhill的方法将版本控制视为一种行为记录:热点是变更频率与复杂度的交集,而非单一轴,限定于固定窗口,它是一个需要检查的概率,而非一个需要执行的裁决。接地规则(references/visual-rendering-core.md § 1)则分解每个产物:SHA、PR编号、路径、计数和引用的解释均从git和gh输出中复制,绝不重新输入;模型只撰写围绕它们的说明文字。一个决策如果其“原因”是模型的猜测,那它就不是被恢复的,而是被发明的,并且它不会进入仓库。

调用位置

侧路,仅限用户调用。 当人类输入/excavate时触发;disable-model-invocation: true 确保其描述不会出现在其他会话的上下文中,因为它在每个仓库中仅在接入时输入一次,且永远没有理由自我触发。计划模式,全程人工参与;没有无人值守路径,因为每个绑定到提交的项目都需要人类阅读它所基于的引用。

请将其作为单独的消息发送,而不是新工作区的第一条消息。一个隐藏的技能如果输入到由主持人附加了前言的第一个消息中,会被视为散文而不会加载;/lfg的调用位置记录了此现场事件(chrislacey89/skills#383)。请将其重新输入为第二条消息。

/help 步骤 2 说明了起始信号。请勿在pipeline已经复合过的仓库(在那里运行/compound)、作为对任何人的绩效评估(见第 5 节)或作为缺陷查找器(/qa和/triage-issue负责此项)时使用此技能。

它位于主流水线旁边,并在/shape处重新连接:首次功能特性在拥有档案和条目的情况下进行设计。当首要热点是工作时,它可能会转交给/request-refactor-plan,当历史记录显示存在一个从未关闭的带有修复标签的集群时,可能会转交给/qa。

方法规则

以下规则是下面流程的具体化。每一条都指出了其来源;本文档其他部分不再重述。

  • 按修订次数排序,按代码行数限定,切勿单独使用一个轴。 频率而不考虑大小会标记配置文件;大小而不考虑频率会标记那些多年前通过调试达到正确性且此后从未触碰的代码(Tornhill,第1-4章)。通过wc -l计算的行数是复杂度的代理:不假设存在cloc,且行数是本书默认使用的代理。
  • 限定于固定窗口。 如果没有参考周期,原始修订次数毫无意义。默认十二个月;对于高速度仓库可以缩短。打印实际窗口。
  • 预期幂律分布并在拐点处截断。 少数文件承担了大部分成本。在曲线趋于平缓处停止,切勿在整数处停止。
  • 一个趋势需要复杂度和大小。 恶化意味着缩进复杂度的上升速度快于源代码行数;重构意味着两者都在下降;稳定意味着两者都持平(Tornhill,第5-6章)。仅凭源代码行数无法得出这些标签。
  • 在耦合分析之前过滤非领域文件;在报告之前对每个耦合进行分类。 锁定文件、清单文件、生成的和厂商提供的代码都是误报。与其测试主体耦合的测试是有意为之的,应将其排除;保留并标记复制粘贴、非支撑边界以及生产者-消费者耦合(Tornhill,第8-9章)。挤压后的历史会破坏提交级别的耦合;使用PR级别的变更集,或者说明该部分不可用。
  • 热点是概率。 在命名机制之前先打开文件,并且对于未打开的文件不提供条目。
  • 所有权数据有四个合法用途: 寻找审查者、入职引导、决定测试位置、以及判断结构是否适合团队。它绝不能用于对人进行排名或评估,并且需要通过.mailmap读取,同时排除机器人程序和初始导入(Tornhill,第12-14章)。
  • 现有文档是理想化的。 在将ADRs、READMEs或CHANGELOGs中的声明记录为既定决策之前,需要对照当前代码树进行验证(Spinellis, Code Reading)。
  • 针对热点的首要行动是在一个关键点编写表征测试,而不是重构(Feathers, Working Effectively with Legacy Code)。档案的“建议首要行动”部分会为每个热点说明这一点。
  • 一个热点因极端而入选,因此其排名部分包含噪声。 均值回归是零假设:在一个窗口排名靠前的文件在下一个窗口可能平平无奇而无需任何操作,而一个在重构后冷却的文件无论如何都会冷却(高尔顿;卡尼曼)。根据窗口两半之间的持续性进行排名,将每个热点标记为persistent或single-window,并仅将持续性的热点路由到建议行动列表。排名是诊断性的,绝非目标;一个以此设定目标的团队会得到博弈,而非质量(古德哈特)。
  • 在决策旁记录假设。 理由最容易被遗忘,而未记录的假设会固化为无人敢于更改的数字(莱韦森, Engineering a Safer World, 第10章)。每个恢复的决策都带有其引文所陈述的约束(“选择X因为Y,假设Z”),并且Z是否在代码树中仍然成立就是反转检测器。
  • 一个决策条目具有ADRs的形式和合规行。 标题、状态、上下文、包含原因的决策、后果以及如何验证;没有最后一项,记录就是考古学而非治理(理查兹与福特, Fundamentals of Software Architecture, 第19章)。此处的验证是针对当前代码树运行的grep或路径检查。
  • 该档案是由一个处于专业知识诅咒下的新手阅读的。 以简短的术语表和拐点热点开头,将完整表格放在其后,并使首个欢迎任务成为理解并总结某个热点的恢复决策,而非修复它(赫尔曼斯, The Programmer's Brain)。

流程

以下每个围栏代码块都将按编写原样运行。每次Bash工具调用都是一个全新的shell,因此没有变量能从一次调用存活到下一次。步骤0的变量块运行一次;其后的块将每个解析后的值写入$WORK/vars.sh,并且后续的每个shell(无论是你的还是某个挖掘者的)都以. "$WORK/vars.sh"开始,而不是重新运行步骤0(后者会重置SINCE为其默认值,并丢弃--since或NONDOMAIN扩展)。跳过该文件的shell会在没有错误的情况下失败:git log --since=""不返回提交,grep -Ev ""不打印任何内容,而空输出会被读作有效的答案“无还原”。 WORK是从仓库派生的路径,因此新shell会使用步骤0中的WORK=表达式重新派生它,并在其下源化该文件;挖掘者在其简报中接收到的是vars.sh的绝对路径,而非继承任何变量。 <path>是唯一的占位符,根据每个热点进行替换。 标志的语义遵循工具自身的文档(git-log, git-shortlog, git-rev-parse, gh pr list);本文档不重复这些内容。 scripts/test-documented-git-commands.sh会针对一个预先设置好的测试夹具运行每个git块,因此一个不再是有效调用的块将在CI中失败。

0. 预检

解析参数:--since <date>(默认值 12 months ago;git log --since接受的任何形式)和 --paths <pathspec>...(替换下面每个块中的.)。然后设置共享变量:

SINCE='12 months ago'
WORK="${TMPDIR:-/tmp}/excavate-$(git rev-parse --show-toplevel | cksum | cut -d' ' -f1)"
mkdir -p -m 700 "$WORK"
START=$(git log --since="$SINCE" --no-merges --format=%cs HEAD </dev/null | tail -1)
NONDOMAIN=(':(exclude)*.lock' ':(exclude)*package-lock.json' ':(exclude)*pnpm-lock.yaml' ':(exclude)*yarn.lock' ':(exclude)*.min.*' ':(exclude)*.snap' ':(exclude)*.generated.*' ':(exclude)CHANGELOG.md' ':(exclude)*/vendor/*' ':(exclude)*/node_modules/*')
BOTS='[[]bot[]]|dependabot|renovate'
MAXFILES=30
export GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=core.quotePath GIT_CONFIG_VALUE_0=false

GIT_CONFIG_* 导出让本次运行中的每个git调用都设置core.quotePath=false(参见git-config, 环境),这样包含非ASCII字节的路径会以原始形式打印,而不是打印为wc和下面的连接操作无法打开或匹配的引号转义。

START是窗口内第一个提交日期,从git派生而非date派生,因为date -d是仅为GNU系统所有,而date -v是仅为BSD系统所有。 NONDOMAIN是一个起始列表:在步骤1之前,使用此仓库的生成、厂商提供、快照和镜像路径进行扩展(对任何可疑项检查git check-attr linguist-generated linguist-vendored)。 MAXFILES是变更集大小的上限,超过此上限的提交将被视为批量扫描(重新格式化、导入、大规模重命名),并从频率和耦合计数中排除。步骤2中的共享日志在构建日志时应用一次;后续块不再重复。

WORK以仓库的顶级路径为键,而非HEAD,因为步骤8会将HEAD移动到文档分支;它在各shell之间保持有效,并在步骤9中被删除。如果中断运行的目录已存在,请在第一个步骤2块之前删除它,以防止过时的文件被误认为是本次运行的输出。

一旦NONDOMAIN被扩展(以及在步骤1关卡之后,如果用户更改了窗口:源化文件,设置SINCE,重新运行步骤0的START=行,然后再次运行此块),持久化解析后的值:

{
  declare -p SINCE START NONDOMAIN BOTS MAXFILES WORK
  declare -px GIT_CONFIG_COUNT GIT_CONFIG_KEY_0 GIT_CONFIG_VALUE_0
} > "$WORK/vars.sh"

然后,在一个以. "$WORK/vars.sh"开头的shell中测量覆盖范围:

git rev-parse --is-shallow-repository
git rev-list --count --since="$SINCE" --no-merges HEAD
git log --max-parents=0 --format=%cs HEAD </dev/null | sort | head -1
git log --since="$SINCE" --no-merges --format=%s HEAD </dev/null | awk '{ t++ } /\(#[0-9]+\)$/ { s++ } END { printf "%d of %d subjects end in (#N)\n", s, t }'

四行输出分别是:是否浅克隆、窗口内的提交数、根提交日期(如果是浅克隆,则为浅层边界,因此输出“未知”)、以及挤压比例。高挤压比例意味着每个提交就是一个完整的PR,因此提交级别的耦合即PR级别的耦合;低挤压比例且其他地方存在挤压合并的PR是需要注意的情况。

然后,统计那些落地了窗口内已有变更的提交数量,因为通过发布分支发布的仓库会携带同一变更的原始版本、精选版本以及发布或同步的汇总版本,而下面的每个计数都会将每个副本视为一次独立的修订:

git log --since="$SINCE" --no-merges --reverse -p --format='commit %H' HEAD -- . "${NONDOMAIN[@]}" </dev/null \
  | git patch-id --stable | awk 'seen[$(1)]++ { print $(2) }' > "$WORK/dups.txt"
wc -l < "$WORK/dups.txt" | tr -d ' '

dups.txt 列出了每个其补丁ID(git-patch-id)已被窗口内更早的提交所拥有的提交,因此最旧的副本不在列表中。它读取与步骤2中共享日志相同的窗口和路径规范,因此在排名读取的提交中对副本进行计数;其变更已在主线上的合并分支会被git log的历史简化在两者中都跳过。计数会进入覆盖范围块,而步骤3将在此板块中且在排除这些提交后重新排名。这些提交被计数,而非排除:重新落地的变更仍然是某人完成的工作,汇总可能是它所携带的变更的唯一记录,并且后续的每个块都通过其自己的git log或git rev-list读取历史,因此只应用于共享日志的过滤器将导致各步骤不一致。在范围关卡处,指出你在主题中看到的任何发布或同步汇总;它们也不会被排除。

探测gh auth status以及远程仓库是否为GitHub;记录gh: yes或gh: no。使用bash "$SC" path research解析档案目录,其中SC是该技能捆绑的解析器references/sidecar.sh的绝对安装路径;切勿自行计算辅助程序路径。如果返回SIDECAR MISS,解析器会退出并返回1,并打印一个init命令:向用户展示该命令,并在用户运行它后继续,因为创建辅助程序是一个人类行为。在该目录中查找先前的excavation-*.md以及现有的docs/solutions/;重新运行时会更新条目而非重复添加,并根据新窗口评估先前档案的persistent标签(有多少保持热点),以便覆盖范围块为其自己的预测携带命中率。

如果仓库是浅克隆,请说明缺失了多少历史记录,并提供git fetch --unshallow;但切勿运行它,因为它会重写.git。

1. 范围关卡 (人工介入)

精确打印将作为档案标题的覆盖范围块:

窗口:        <START> → 今天 (<SINCE>)
提交数:       <N> 非合并 (<M> 个因批量 > MAXFILES 文件而被排除)
浅克隆:       yes | no
挤压比例:     <s>/<t>
重复数:       <d> 个提交重复了更早提交的补丁ID(已计数,未排除)
gh:            yes(已获取 <M> 个已合并PR中的 <N> 个;已关闭 <k> 个未合并的) | no
修复标签:     <k> of <N> 个提交匹配修复模式(下界;在步骤3中填充)
排除项:       <NONDOMAIN 列表,每行一个>
不可见项:     已关闭未合并的PR、强制推送或挤压的历史、已删除的文件、已离开的贡献者

不可见项行不是固定模板。以下的每项排名都依赖于……

...(内容被截断)

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

chrislacey89/closeout

Primary pipeline tail step after /pre-merge, when a reviewed PR is ready to land and you want the workspace back to a clean base. Use to merge, switch off the worktree before removing it, prune the merged branch, pull base, and verify a clean end state. Triggers on 'close out', 'merge and clean up', 'get back to a clean main/base', 'tear down the worktree'. Not for capturing lessons (that's /compound), or closing the PRD and any other open slices and research-artifact hygiene (that's the cleanup prose in SYSTEM-OVERVIEW Step 9).

chrislacey89/compound

Primary pipeline knowledge-capture step that closes the compounding loop. Capture a durable lesson in docs/solutions/ onto the open PR before /closeout merges (the default), or post-merge when the lesson only surfaces during/after merge. Use so future /research and /write-a-prd runs improve. Not for trivial edits with no reusable project-level learning, and not for the merge/teardown itself (that's /closeout).

chrislacey89/execute

Primary pipeline execution step after /prd-to-issues or for clearly scoped implementation work. Use to build, verify, and commit a concrete slice, delegating to /tdd for backend work and behavior-heavy frontend logic when red-green-refactor will reduce risk. Not for shaping or pre-merge review.

chrislacey89/pre-merge

Primary pipeline review step after verified implementation. Use to create a PR with lineage and run architectural review before merge. Not for QA intake, planning, or implementation work.

相关技能