关于 refactor-research-code
refactor-research-code 帮助研究者整理研究代码仓库以便发布,同时保持论文结果对应的数值行为不变。静态审计会按风险分类清理项,可能影响行为的修改须经作者确认。
主要功能
- 01只读静态发布审计
- 02区分安全与高风险修改
- 03整理仓库结构与文件
- 04检测双盲审稿身份线索
- 05生成重构计划和变更记录
适用场景
- 01准备公开发布实验代码
- 02整理脚本并记录运行入口
- 03双盲投稿前检查身份泄露
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ shaishavmaisuria/ research-paper-lifecycle-skills --skill refactor-research-code安装后在 Claude Code 中输入/refactor-research-code确认已加载。
附带文件references/release-refactor-catalog.mdscripts/release_audit.py
详细介绍
重构研究代码
将研究仓库从“在我的机器上能运行”转变为整洁、有文档记录、可重复运行的公开发布版本——且不改变论文报告的任何一个数字。研究代码会逐渐堆积废弃的实验分支、硬编码路径、神秘超参数、没有文档的“先运行这个文件,再运行那个文件”的操作流程,以及暴露身份的蛛丝马迹。本技能会清理这些冗余,让仓库布局更合理,但将保留结果视为首要原则:它会将每项拟议的更改归类为安全(机械性、保持行为不变)或先征求同意(可能导致数字发生变化),未经作者明确同意,绝不会动任何需要先征求同意的项目。
这不是通用重构(不进行性能改写、不“现代化 API”,也不为重构而调整结构)。唯一目标是在行为完全一致的前提下做好发布准备。如果某项“清理”会改变代码的计算结果,正确做法是标记出来并征求同意,而不是为了让仓库更整洁而牺牲论文的结论。
适用场景
- “清理 / 重构我的研究代码,为发布做准备。” / “代码一团糟——帮我整理到可以发表的程度。”
- “删除废弃的实验分支和注释掉的代码。”
- “将配置与代码分开。” / “这些超参数到处都是硬编码的。”
- “让我的运行具有确定性 / 可以重复运行。” / “为入口点编写文档。”
- “让仓库布局清晰明了。” / “为了双盲审稿,去掉我的身份信息。”
- 在使用
test-research-code(添加测试 / 随机种子 / 环境配置)和prepare-artifacts(打包并托管,以获取徽章)之前——本技能负责首先进行 结构性清理。
本技能不做什么(请转用其他技能)
| 你的需求…… | 请改用 |
|---|---|
| 添加冒烟测试、固定随机种子、记录环境 | test-research-code |
| 打包 + 归档 DOI/SWHID + 徽章分类 + 附录 | prepare-artifacts |
| 对论文进行彻底的双盲审查并可逆地去匿名化 | anonymize-paper |
| 确认生成的数字与论文中的表格一致 | verify-results |
| 重新组织论文的章节 / 论证 | refactor-structure |
本技能会标记随机种子 / 环境配置方面的缺漏和身份信息泄露问题,并将其交由其他技能处理;结构性清理则由本技能完成。
输入
- 研究代码目录(仓库本身,或存放实验脚本的子文件夹)。本技能只读取本地文件,不会克隆仓库。
- 审稿采用双盲 / 单盲 / 非盲中的哪种方式(决定身份信息扫描方式),以及需要扫描的任何身份标识词(作者姓名、机构、内部代号)。
- 可选的
.paper-memory/profile.yml(贡献类型——如果是system或dataset论文,对代码质量的要求会更高,更倾向于发布可复用版本)。 - 如果清理工作是为了某个目标会议,可选提供其工件评审轨道——不过徽章规则会由
prepare-artifacts实时获取,本技能不会获取。
首要原则:保留精确的数值行为
此技能采取的每项操作都属于以下三个类别之一。请将它们之间的界限视为不可逾越。
- SAFE — 可自由应用(需作者认可): 添加 README / LICENSE /
.gitignore;将文件移入src//包布局(随后修正导入);删除纯粹的垃圾文件(__pycache__、*.pyc、.DS_Store、编辑器交换文件);记录现有入口点;仅重新格式化空白字符/注释。这些操作不会改变代码的计算结果。 - ASK-FIRST — 未经明确确认,绝不触碰: 删除代码路径(备份文件、注释掉的代码块、
if False:分支——它可能是一个切换式实验,也可能会悄悄遮蔽当前生效的版本);将硬编码的超参数或路径提取到配置中(必须原样保留其值);更改任何涉及随机种子、随机数生成器、线程/工作进程数量、数据类型/精度或评估顺序的内容(这些因素定义了数值)。对于每一项,说明发现的问题、拟议的更改以及为什么这可能改变结果,然后等待确认。 - IDENTITY — 盲审上传前先清理: 电子邮件、用户主目录路径、作者姓名、
.git历史记录。请在此处列出;深入清查交由anonymize-paper处理。
如果无法判断某项更改是否安全,默认归为 ASK-FIRST。一个更漂亮但报告出不同数值的仓库不是成功,而是失败。
流程
遵循「计划 → 确认 → 应用安全项 → 询问风险项」的流程,计划应基于外部、可测量的信号——静态审计,而不是模型觉得仓库「看起来很干净」。明确假设,展示不同解读,并让作者掌握主动权。
-
先阅读记忆。 阅读
.paper-memory/lessons.md(如果存在,也阅读profile.yml),以便跳过作者已修复的问题,并优先指出其recurring习惯(例如「你经常提交.git和硬编码的/home路径」)。参见paper-memory-convention.md。 -
确认范围和盲审级别。 询问评审是否为双盲,以及此次发布的用途(公开发布到 GitHub、盲审补充材料,还是 artifact track)。不要对单盲/非盲发布进行匿名化——这会破坏一个完善的仓库。如果是盲审,询问需要扫描哪些标识信息。
-
运行静态发布重构审计(确定性)。 不要手动使用 grep:
python3 scripts/release_audit.py <code-dir> \ --blind <none|single|double> --names "Jane Doe,Example University" # machine-readable: python3 scripts/release_audit.py <code-dir> --blind double --json该审计会遍历仓库(只读、不执行、不联网、不写入),并按类别(死代码、配置、入口点、布局、确定性、身份信息、卫生)标注发现结果;更重要的是,还会按风险标注:
SAFE、ASK-FIRST(行为风险)或IDENTITY。标志:--strict(任何发现都会导致失败)、--max-files N、--max-bytes N(仓库内 blob 阈值)。退出代码:0 表示没有 ask-first/身份信息发现,1 表示存在 ask-first 或身份信息发现,2 表示用法错误。这是制定计划所依据的信号(外部检查,而非自我判断);审计会指出可改进之处——但不能证明仓库可以复现。 -
先提交重构计划,获作者批准后再进行任何编辑。 按 SAFE → ASK-FIRST → IDENTITY 的顺序,将发现归入这三个类别。对于每个 ask-first 项,说明更改内容及其结果风险(「删除这个
if False:代码块,只有在它在所有配置下都不可达时才安全——请确认?」)。作者逐项批准或否决。类别和安全重构方案见 references/release-refactor-catalog.md。 -
应用 SAFE 重构(须获得作者同意),按以下顺序进行——每项对应一个审计类别:
- 布局 — 添加 README(入口点、每项结果对应的精确复现命令、依赖项、目录结构图)、LICENSE、
.gitignore;将散落的脚本整理成src//包结构,并修正导入。 - 入口点 — 说明(或接入)一个明确的命令,用于端到端运行整个流程(
make reproduce/run.sh/python -m pkg)。 - 整洁 — 从发布副本中移除
__pycache__、*.pyc、.DS_Store、编辑器交换文件;将项目内的大型数据/模型文件移至下载脚本/存档主机(最后一项须先询问——确认运行时不需要该文件)。
- 布局 — 添加 README(入口点、每项结果对应的精确复现命令、依赖项、目录结构图)、LICENSE、
-
逐项处理 ASK-FIRST 项,绝不批量处理。 每项变更获批后:进行最小限度的修改,然后通过外部检查验证行为未变——重新运行整个流程(或冒烟测试)并比较输出,而不是只凭肉眼检查差异。通过重新运行确认行为保持不变属于
test-research-code/verify-results的职责范围;此技能负责标记并协调,若变更确有风险,则停下并征求确认。升级处理是此流程的一部分。具体而言:- 死代码 — 仅在确认没有任何内容导入或调用该代码后处理。
- 配置 — 将字面值提取到配置/CLI 中,并保持完全相同的值;这里的拼写错误会悄然改变结果。
- 确定性 — 与作者协调后设置/记录种子并固定顺序,然后重新运行以再次确认论文中的数值。添加种子会改变未设种子的运行结果——这是风险最高的修改。将种子/env 的机制交由
test-research-code处理。
-
处理盲审中的身份泄露。 标记电子邮件、主目录路径、姓名和
.git历史;将深度检查(提交历史、笔记本元数据、自我引用措辞、匿名镜像)交由anonymize-paper处理。盲审上传时,绝不要通过代码仓库暴露作者身份。 -
重新运行审计,直到达到 SAFE-clean,并明确停止条件。 循环执行审计 → 修复 → 审计,直到不再存在 SAFE/布局/整洁问题,且每项 ask-first 问题均已解决或有意识地延期——不能无限期继续。最多约 3 轮;如果审计仍标记同一项 ask-first 问题,应酌情升级处理,而不是继续修改。
-
将重构计划和变更日志写入
paper-workspace/submission/refactor-research-code-plan.md,并在paper-workspace/INDEX.md中追加一行。先写已完成的内容(安全项),再写 ask-first 决策(已应用/否决/延期,并注明各自对结果的风险),最后写身份信息交接。引用每项对应的审计发现。
输出
- 一份重构计划(SAFE / ASK-FIRST / IDENTITY 分类,每项发现包含
category+risk+file[:line]),以及一份记录已应用、否决或延期事项的变更日志——写入paper-workspace/submission/。 - 已编辑的代码仓库文件(仅限逐项获批的内容):README / LICENSE /
.gitignore、src//包结构、已说明的入口点、已清理的杂项,以及作者确认的任何 ask-first 修改。 - 清晰的交接清单:种子/env/测试 →
test-research-code;打包/DOI/ 徽章 →prepare-artifacts;深度匿名化 →anonymize-paper; 数值与论文核对 →verify-results。
适配你的学科
审计读取的是目录,而非学科,因此布局/死代码/身份检查适用于多种场景。对于非 Python 技术栈,确定性和配置模式有所不同(R 的 set.seed、Julia 的 Random.seed!、用于环境的 renv.lock/Manifest.toml)——脚本已支持其中若干种;请在 scripts/release_audit.py 中为你的语言扩展模式表。结果保持不变的约定具有普遍性:清理代码仓库,保留数值。
守则
- 保留精确的数值行为——这正是全部意义所在。 未经作者明确批准,绝不进行需要先询问的改动(删除代码、提取常量、改动随机种子/线程/数据类型/顺序);并且必须通过重新运行来验证行为是否保留,绝不能通过阅读差异来验证(自我反思会验证自身的错误——验证必须来自外部)。
- 如果不确定某项改动是否安全,就必须先询问。 仓库看起来更漂亮,却报告不同的数值,这就是失败。
- 不要运行任何破坏性或不可信的内容。
release_audit.py是静态、只读且不联网的。重新运行流水线以验证行为由作者决定,且可能需要沙盒/GPU。 - **注意匿名化:**进行匿名评审时,绝不要通过仓库或
.git历史泄露身份;将深入检查交给anonymize-paper。 - 各司其职。 不要添加测试/随机种子/环境配置(这属于
test-research-code),不要创建 DOI 或打包制品(这属于prepare-artifacts),也不要声称结果可复现(这属于verify-results;而且“复现”从来不代表位精确,也不由此技能决定)。 - **Copilot,而非 Pilot:**它会规划、询问,并在获得批准后编辑;绝不会代作者提交、存档或推送。
references/文件保持一层目录深度;此文件不得超过 500 行。
记忆
使用共享的 .paper-memory/ 约定(完整规范:
paper-memory-convention.md)。
- **开始时:**阅读
lessons.md,跳过已修复的清理事项,并优先关注反复出现的发布习惯(例如“你每个仓库都会提交硬编码的/home/<you>路径”);阅读profile.yml以了解贡献类型。 - **结束时:**针对每个反复出现的习惯,按规范格式追加一条带日期的记录,并通过
reflect-and-improve的reflect_log.py执行:python3 ../reflect-and-improve/scripts/reflect_log.py append \ --memory .paper-memory --skill refactor-research-code --scope recurring \ --issue "hyperparameters hardcoded across scripts, no config file" \ --rec "extract to config.yaml/CLI with identical values every release" - 按需创建
.paper-memory/,并提出将其添加到.gitignore;仅保存在本地,绝不上传,也绝不复制到此仓库。