PR经历(Understand-Anything)

我给 Understand-Anything 提了第一个 PR:为 /understand 加上 --exclude 参数

一个开源项目的 "good first issue",17 个测试变 22 个,5 个文件,107 行增改。记录一下这次从看 issue 到提 PR 的完整过程。


起因:一个被置顶的 issue

Understand-Anything 是一个用 LLM + 静态分析把代码库变成交互式知识图谱的工具。我用了之后觉得效果很好------运行 /understand 之后,/understand-chat/understand-explain 的返回质量比裸用 Claude Code 高很多。

但它有一个明显的痛点:首次运行 /understand 太慢了,token 消耗也很大。

这个问题被 @Antoliny0919 提在了 issue #76,标题是 "How to make /understand run faster ?"。

这个 issue 热度很高------10 个 reaction、16 条评论、被项目作者 Lum1104 置顶 ,还被标记为 good first issue。评论区里 Lum1104 把改进方向拆得非常清楚:

  1. .understandignore 文件 --- 类似 .gitignore,让用户自定义排除规则 ✅(已实现)
  2. .understandinclude 文件 --- 强制包含被默认规则过滤掉的文件
  3. CLI 参数 --- /understand --exclude "tests/*,docs/*"我要做的
  4. 非 git 项目的 .gitignore 支持

四个方向互不冲突,我选了第 3 个------CLI 参数。改动范围清晰,技术难度适中,非常适合第一次贡献。


动手之前:先读懂现有代码

在写任何代码之前,我把相关文件通读了一遍:

文件 作用
packages/core/src/ignore-filter.ts 核心的忽略过滤器,加载默认规则 + .understandignore 文件
packages/core/src/__tests__/ignore-filter.test.ts 已有 17 个测试,覆盖默认规则和用户文件
skills/understand/scan-project.mjs 项目扫描脚本,枚举文件 → 过滤 → 语言检测 → 分类
agents/project-scanner.md Agent 定义,告诉 LLM 怎么调用扫描脚本
skills/understand/SKILL.md Skill 定义,/understand 命令的完整工作流

读完发现,项目已经有一套成熟的 ignore 机制:

复制代码
优先级(低 → 高):
  1. 内置默认规则(node_modules/, dist/, *.lock, ...)
  2. .understand-anything/.understandignore
  3. .understandignore

三层的 Ignore 实例通过 createIgnoreFilter() 统一管理,调用方只需 filter.isIgnored(path) 即可判断。我的任务是在这个基础上加第四层。


实现:加一层,改五处

最核心的改动只有一行------给 createIgnoreFilter 加一个可选参数:

typescript 复制代码
// Before
export function createIgnoreFilter(projectRoot: string): IgnoreFilter

// After
export function createIgnoreFilter(
  projectRoot: string,
  extraPatterns: string[] = []
): IgnoreFilter

用默认空数组保证向后兼容------不传第二个参数的所有旧调用方完全不受影响。

然后在这四个位置串联起来:

1. ignore-filter.ts --- 新增 Layer 4

typescript 复制代码
// Layer 4: CLI --exclude patterns (highest priority)
if (extraPatterns.length > 0) {
  ig.add(extraPatterns);
}

2. scan-project.mjs --- 解析 CLI 参数

原来脚本只接受两个位置参数。我加了 --exclude 的解析逻辑:

javascript 复制代码
// Parse: <projectRoot> <outputPath> [--exclude <patterns>]
for (let i = 2; i < process.argv.length; i++) {
  if (arg === '--exclude' && i + 1 < process.argv.length) {
    excludePatterns = process.argv[++i]
      .split(',')
      .map(p => p.trim())
      .filter(Boolean);
  }
}

然后在过滤阶段把 excludePatterns 传给 createIgnoreFilter

javascript 复制代码
const combined = createIgnoreFilter(projectRoot, excludePatterns);

3. project-scanner.md --- Agent 文档

告诉 LLM agent 如果有 exclude patterns 要在调用脚本时加上 --exclude 参数:

bash 复制代码
node scan-project.mjs "$PROJECT_ROOT" "$OUTPUT_PATH" --exclude "tests/*,docs/*"

4. SKILL.md --- Skill 文档

  • 更新 argument-hint:加入 --exclude <patterns>
  • Phase 0 新增 3.7 节:解析 $ARGUMENTS 中的 --exclude
  • Phase 1 把 $EXCLUDE_PATTERNS 传给 project-scanner agent

测试:5 个新用例,22/22 全绿

测试文件原来有 17 个用例。我加了 5 个,覆盖所有关键路径:

typescript 复制代码
describe("createIgnoreFilter with CLI --exclude patterns", () => {

  // 1. 基本排除
  it("applies CLI exclude patterns alongside defaults", () => {
    const filter = createIgnoreFilter(testDir, ["tests/", "e2e/"]);
    expect(filter.isIgnored("tests/foo.test.ts")).toBe(true);
    expect(filter.isIgnored("src/index.ts")).toBe(false);  // 不排除源码
  });

  // 2. CLI 优先级高于 .understandignore 的取反
  it("CLI patterns have highest priority over .understandignore files", () => {
    // .understandignore 写的是 !docs/(取反,要包含 docs/)
    // CLI 传的是 docs/(要排除 docs/)
    // → CLI 赢,docs/ 被排除
  });

  // 3. ! 取反可以重新包含被默认排除的文件
  it("CLI ! negation can re-include files excluded by defaults", () => {
    const filter = createIgnoreFilter(testDir, ["!dist/"]);
    expect(filter.isIgnored("dist/bundle.js")).toBe(false);  // 被取反了
    expect(filter.isIgnored("node_modules/foo.js")).toBe(true);  // 默认规则依然生效
  });

  // 4. CLI + .understandignore 同时生效
  // 5. 空数组无副作用
});

跑测试:

bash 复制代码
pnpm --filter @understand-anything/core test
复制代码
✓ 33 test files passed (33)
✓ 675 tests passed (675)  ← 含 ignore-filter.test.ts 的 22 个

提交 & Push

bash 复制代码
git checkout -b feat/add-exclude-flag
git add [5个文件]
git commit -m "feat: add --exclude CLI flag to /understand for user-defined ignore patterns"
git push myfork feat/add-exclude-flag
复制代码
5 files changed, 107 insertions(+), 10 deletions(-)

回过头来看

为什么这个 issue 适合新手

  1. 改动范围明确:Lum1104 在评论里把要做的事情列得清清楚楚,不需要自己猜测
  2. 代码隔离性好:改动集中在 ignore 模块,不涉及分析引擎、图组装、dashboard 等复杂部分
  3. 有现成的测试可以参考:对着已有测试的结构写新用例,不会跑偏
  4. 向后兼容:加的是可选参数,不会破坏任何现有功能

学到了什么

  • 读代码比写代码花的时间更长------但绝对值。理解现有架构后再下手,改动会很小很精准
  • 开源项目的 good first issue 真的是为新贡献者设计的,别怕点进去
  • 一个高质量的 issue 描述 + 作者清晰的拆解 = 降低一半的贡献门槛

和 #76 的其他 PR 是什么关系

同一个 issue 下还有其他贡献者在做不同方向的优化:

PR 作者 方向
#314 parkerault file-analyzer 用便宜模型降成本
#321 KennyUMN 修正 bin/ 排除的注释
#346, #353 tirth8205 I/O 并行化加速
我的 PR yiziff --exclude CLI 参数

方向互不冲突,各做一个维度------这也是开源协作的魅力。


附:改动文件一览

复制代码
understand-anything-plugin/
├── agents/
│   └── project-scanner.md          (+11 lines, 文档)
├── packages/core/src/
│   ├── ignore-filter.ts            (+10 lines, 核心逻辑)
│   └── __tests__/
│       └── ignore-filter.test.ts   (+52 lines, 5 个新测试)
└── skills/understand/
    ├── SKILL.md                    (+13 lines, skill 定义)
    └── scan-project.mjs            (+31 lines, CLI 解析)
  • Commit: 5afdbc6
  • Tests: 22 passed (17 + 5 new)
  • Build: ✅ core + skill
  • Linked issue: #76
相关推荐
猎奇不再看4 小时前
MAF的Agent详解:连接LLM的IChatClient对象
github
_Evan_Yao4 小时前
一文搞懂:Git分支管理与团队协作规范——从GitFlow到GitHub Flow,从rebase到merge,打造高效协作流
java·git·后端·github
lxw18449125146 小时前
github 提示双因素认证
github
逛逛GitHub6 小时前
你的 AI Agent 每次请求都在干嘛?这个开源项目帮你扒个底朝天。
github
用户480261584706 小时前
Remeda:data-first 和 data-last,它全都要
github
花椒技术7 小时前
AI 代码评审落地实践:GitLab 接入、项目规则与反馈闭环
后端·github·agent
袋子(PJ)8 小时前
2026最新GitHub发布项目全过程
git·github
拓研C8 小时前
EM-Core-Agent:AI Agent 具身认知核心系统——架构白皮书 V1.0
人工智能·架构·车载系统·机器人·github
在逃花果山的小松10 小时前
ChatClient中间件LoggingChatClient——在调用LLM前后输出
github