mcpField
I
indexion-refactor

indexion-refactor

github.com/trkbt10开发24.9k 次安装5 周前更新
代码仓库

关于 indexion-refactor

indexion-refactor 是用于分析和减少代码重复的技能,面向重构代码库的开发者。它覆盖文本、结构和概念层面的重复,并提供提取共享代码、清理包装函数及验证 SoT 的流程。

主要功能

  1. 01检测文本级重复代码
  2. 02发现跨目录共享候选
  3. 03识别简单委托包装函数
  4. 04分析概念层面的重复
  5. 05指导集中实现到 SoT

适用场景

  1. 01重构前检查重复实现
  2. 02从多个包提取共享代码
  3. 03清理重构后多余的包装函数
  4. 04检查概念逻辑是否分散

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/trkbt10/indexion-skills --skill indexion-refactor

安装后在 Claude Code 中输入/indexion-refactor确认已加载。

详细介绍

indexion 重构 — 代码库重构

使用 indexion 的分析命令检测并消除三个层面的重复——文本、结构和概念—— 然后验证 SoT 是否得到强制执行。

适用场景

  • 添加新的抽象(类型、模块、API 层)后
  • 引入新的文件格式或 I/O 边界后
  • 同一原因导致需要修改 3 个以上文件时
  • 添加“守卫”或“跳过”逻辑来规避结构性问题时
  • 意外路径出现 opendir、ENOENT 或类似文件系统错误时
  • 在软件包之间提取共享代码时
  • 重构后清理代码时(移除简单的包装函数)
  • 定期检查代码库的 SoT 健康状况

三个层面的重复

层面含义工具示例
文本复制粘贴的代码块、相同的函数plan refactor在 5 个模块中复制了 is_whitespace
结构逻辑结构相同但名称不同plan solid、plan unwrap跨软件包提取候选项、简单的包装函数
概念同一领域概念由不同实现独立实现explore + 手动分析三个模块分别判断“这个文件是否为归档文件?”

文本重复易于发现和修复。概念重复最难处理,也最危险——它不会产生任何复制粘贴匹配项,但意味着修改一个概念时,需要更新所有分散的实现。

工作流

阶段 1:清除文本重复(plan refactor)

从高置信度匹配项开始,逐步处理。

# Step 1: Find 90%+ duplicates (high confidence)
indexion plan refactor --threshold=0.9 \
  --include='*.mbt' --exclude='*_wbtest.mbt' \
  --exclude='*moon.pkg*' --exclude='*pkg.generated*' \
  cmd/indexion/

indexion plan refactor --threshold=0.9 \
  --include='*.mbt' --exclude='*_wbtest.mbt' \
  --exclude='*moon.pkg*' --exclude='*pkg.generated*' \
  src/

分三个部分阅读输出:

部分检测内容操作
相似文件整体相似度较高的文件检查是否可以进行结构整合
重复代码块文件之间逐行相同的代码提取到 @common 或共享模块
函数级重复结构相似的函数(对函数体使用 TF-IDF)统一为单个 SoT 函数

同一文件内的重复项(相似度达到 90% 以上的函数)是最有价值的目标——最容易修复,收益也最明确。例如:get_global_data_dir 和 get_global_cache_dir 的结构有 95% 相同,因此提取到 resolve_os_dir。

# Step 2: Use grep to trace references before consolidating
indexion grep "TypeIdent:TfidfEmbeddingProvider" src/
indexion grep --semantic=name:is_whitespace src/

# Step 3: Fix, then re-run to confirm duplicates are gone
indexion plan refactor --threshold=0.9 --include='*.mbt' ...

# Step 4: Lower threshold and iterate
indexion plan refactor --threshold=0.85 --include='*.mbt' ...

plan refactor 选项:

选项默认值说明
--threshold=FLOAT0.7最低相似度阈值
--strategy=NAMEhybrid相似度算法:hybrid、tfidf、bm25、jsd、ncd
--fdr=FLOAT0FDR 校正(0=禁用)
--style=STYLEraw输出:raw、structured
--format=FORMATmd输出:md、json、text、github-issue
--name=NAME--项目名称(用于 structured 样式)
--include=PATTERN--包含模式(可重复指定)
--exclude=PATTERN--排除模式(可重复指定)
-o, --output=FILEstdout输出文件路径
--specs-dir=DIRkgfsKGF 规范目录

清理后的保留项(停止信号):

  • 平台桩代码(native.mbt / stub.mbt)——有意进行的平台分支
  • 类型方法相似性(不同类型上的 to_string)——类型不同,模式相同
  • CLI 命令样板代码(command() 函数)——@argparse API 模式,不属于重复
  • 语义相似但功能不同的函数(is_disqualifying_keyword 与 is_skip_token)——用途不同
阶段 2:提取跨包共享代码(plan solid)

清理完各个目录后,找出应在多个包之间共享的代码。

# Find overlap between two packages
indexion plan solid --from=src/a,src/b

# Specify extraction target
indexion plan solid --from=src/a,src/b --to=src/common

# Use tree edit distance for precise function-level matching
indexion plan solid --from=src/a,src/b --strategy=apted

# Higher threshold for stricter matching
indexion plan solid --from=src/a,src/b --threshold=0.95

# Filter files
indexion plan solid --from=src/a,src/b --include='*.mbt' --exclude='*_test.mbt'

plan solid 与 plan refactor 不同:

plan refactorplan solid
范围目录内部的重复代码跨目录的重叠代码
目标在代码库内部整合将共享代码提取到新包中
输入<path>--from=dirA,dirB

plan solid 选项:

选项默认值说明
--from=DIRS(必需)源目录(逗号分隔或可重复指定)
--to=DIR--提取目标目录
--rules=FILE--规则文件(.solidrc)
--rule=RULE--内联规则(可重复指定)
--threshold=FLOAT0.9最低相似度阈值
--strategy=NAMEtfidf相似度算法:tfidf、apted、tsed
--include=PATTERN--包含模式(可重复指定)
--exclude=PATTERN--排除模式(可重复指定)
--format=FORMATmd输出格式:md、json、github-issue
-o, --output=FILEstdout输出文件路径
--specs-dir=DIRkgfsKGF 规范目录

工作流:

  1. 先对每个目录单独运行 plan refactor,清理内部重复代码
  2. 运行 plan solid --from=dirA,dirB,查找跨目录提取候选项
  3. 根据计划建议提取共享代码
  4. 使用 indexion grep "TypeIdent:SharedType" 验证所有引用均已更新
阶段 3:移除不必要的包装器(plan unwrap)

整合完成后,清理那些只会增加间接调用、没有实际价值的简单委托函数。

# Step 1: Quick check
indexion grep --semantic=proxy src/

# Step 2: Detailed report
indexion plan unwrap --include='*.mbt' --exclude='*_wbtest.mbt' \
  --exclude='*moon.pkg*' --exclude='*pkg.generated*' src/

# Step 3: Preview changes (safe — no files modified)
indexion plan unwrap --dry-run --include='*.mbt' --exclude='*_wbtest.mbt' \
  --exclude='*moon.pkg*' --exclude='*pkg.generated*' src/

# Step 4: Apply fixes
indexion plan unwrap --fix --include='*.mbt' --exclude='*_wbtest.mbt' \
  --exclude='*moon.pkg*' --exclude='*pkg.generated*' src/

# Step 5: Run tests
moon test --target native

检测内容: 函数体只有一次函数调用,且所有参数都以简单标识符的形式原样传递——不包含控制流或转换。

// Detected (default) — trivial delegation
fn matches_pattern(text : String, pat : String) -> Bool {
  @glob.glob_match(text, pat)
}

// Excluded by default (use --all to include)
fn length(self : MyList) -> Int {
  self.items.length()    // self-delegation (encapsulation)
}
fn emit(value : String) -> Action {
  Emit(value)            // bare constructor
}

plan unwrap 模式:

模式标志说明
报告(默认)列出找到的包装器
预览--dry-run显示所有编辑内容,但不修改文件
修复--fix应用对文件的编辑

plan unwrap 选项:

选项默认值说明
--dry-run--预览编辑内容
--fix--应用编辑
--all--包含自委托和裸构造函数包装器
--include-self--包含 self.field.method 模式
--include-bare--包含裸构造函数包装器
--include=PATTERN--包含模式(可重复指定)
--exclude=PATTERN--排除模式(可重复指定)
--format=FORMATmd输出格式:md、json、text
-o, --output=FILEstdout输出文件路径
--specs-dir=DIRkgfsKGF 规范目录

移除前请先审查:

  • 平台包装器(FFI、@osenv_path)是抽象层,并非无意增加的间接调用
  • 公共 API 包装器供外部包使用——移除会造成破坏性变更
  • 务必先运行 --dry-run
阶段 4:检测概念层面的重复(explore + 分析)

这是最难的一层。文本和结构工具找不到这类重复,因为代码不同——但概念相同。

# Find which files share vocabulary (= work in the same concept domain)
indexion explore --threshold=0.4 \
  --include='*.mbt' --exclude='*_wbtest.mbt' \
  --exclude='*moon.pkg*' --exclude='*pkg.generated*' \
  src/ cmd/

相似度为 40-60% 且不存在结构重复的文件是概念邻居——它们使用相同的术语,因为它们处理的是同一个领域。

对于每一对高相似度文件,都要问:“它们共享什么概念?由谁负责?”

# Inspect shared vocabulary with tree structure comparison
indexion explore file_a.mbt file_b.mbt --threshold=0 --strategy=apted

概念泄漏的常见模式:

症状泄漏的概念修复方法
两个文件都调用 is_X(spec),然后调用 Y::from_spec(spec)“判断是否为 X 并配置 Y”将 try_do_X(path, spec) 提取到负责 X 的模块中
两个文件都在内容已加载时调用 @fs.read_file_to_string(path)“读取文件内容”将内容作为参数传递,不要重新读取
两个文件都先调用 parent_dir(path),然后调用 @fs.read_dir(dir)“列出同级文件”将目录遍历集中到流水线中
多处使用 if is_virtual_path(x) { skip } 守卫“真实路径与虚拟路径”让类型系统阻止虚拟路径到达此处
两个文件都调用 buf.write_string("\n"); buf.write_string(x)“拼接文本条目”将 join_text_entries() 提取到负责此概念的模块中
阶段 5:集中到 SoT

定义概念的模块应该是唯一一个实现逻辑的模块。

规则:

  1. 一个概念、一个模块、一个函数。 如果“从归档中提取文本”出现在 vfs.mbt、discover.mbt 和 args.mbt 中,它就只应属于 vfs.mbt。
  2. 调用方接收结果,而不是原料。 不要分别导出 is_archive_spec、ArchiveSpec::from_spec 和 expand_archive。应导出 try_extract_archive_text(path, spec) -> String?。
  3. 守卫是症状,不是修复。 if is_virtual_path(x) { skip } 意味着虚拟路径本不该到达此处。修复源头,而不是接收端。
  4. 重新读取已在内存中的磁盘内容是一种概念泄漏。 如果 SupportedFile.content 保存了文本,下游代码就不应调用 @fs.read_file_to_string(file.path)。
阶段 6:验证
# Confirm textual duplication is gone
indexion plan refactor --threshold=0.9 \
  --include='*.mbt' --exclude='*_wbtest.mbt' \
  --exclude='*moon.pkg*' --exclude='*pkg.generated*' \
  src/ cmd/indexion/

# Confirm concept similarity is reduced
indexion explore file_a.mbt file_b.mbt --threshold=0

# Confirm wrappers are cleaned up
indexion plan unwrap --include='*.mbt' --exclude='*_wbtest.mbt' \
  --exclude='*moon.pkg*' --exclude='*pkg.generated*' src/

# Run tests
moon test --target native

集中到 SoT 后:

  • 概念负责模块与其调用方之间的文本相似度会降低
  • 调用方会变得更短(一次 API 调用取代多步逻辑)
  • 概念负责模块可能会变大,但它是唯一需要修改的地方
阶段 7:通过测试证明问题不会复现

编写一个能在结构上阻止旧模式复现的测试:

test "SoT: SupportedFile.path is always a real filesystem path" {
  // Create an archive, run load_supported_file_info
  // Assert: no path contains "!/"
  // Assert: every path passes @fs.path_exists
}

该测试不检查行为——它检查的是 SoT 不变量。

危险信号

“我需要在这里加个守卫”

如果你正在一个不应接收特殊情况的函数中添加 if is_special_case(x) { skip },问题出在上游。该函数的调用方不应该传入这个值。

“它能正常运行,但会向 stderr 打印错误”

C 运行时向 stderr 输出的消息(opendir: No such file or directory)意味着无效数据到达了系统调用。catch 会捕获错误,但 perror() 已经打印了错误。 唯一的修复方法是阻止无效数据到达该调用。

“我会分别在每个命令中修复”

如果 explore、search、grep、reconcile、plan 文档等都需要相同的修复…… 那么修复就应该放在共享流水线中,而不是每个命令中。

“相似度只是因为用了相同的词汇,不是真正的重复”

如果本不应共享概念的模块之间 TF-IDF 相似度达到 40-60%,这就是警告。词汇匹配本身就是信号。

快速参考:何时使用哪个命令

问题命令
“哪些文件相似?”explore --format=list
“具体有哪些重复内容?”plan refactor --threshold=0.9
“软件包 A 和 B 之间有哪些代码重叠?”plan solid --from=A,B
“哪些函数是简单的包装器?”plan unwrap or grep --semantic=proxy
“这些文件有什么共同概念?”explore file_a file_b --threshold=0 --strategy=apted
“重复内容修复了吗?”使用相同阈值重新运行 plan refactor

评论

支持 Markdown