Muhtasham/decomp-goal-harness
GitHub: Muhtasham/decomp-goal-harness
面向 Codex 风格 Agent 的匹配反编译工作流编排工具,通过「编译-比对-编辑」循环驱动 AI 产出与原始二进制字节一致的源码。
Stars: 3 | Forks: 0
# decomp-goal-harness
## 关于
`decomp-goal-harness` 是一个轻量级的命令行工具,用于运行 Agent 驱动的匹配反编译目标。它有助于发现未完成的反编译目标,生成限定范围的 Codex 目标提示词,运行本地构建/diff 神谕工具,存储结构化的进度记录,并渲染一个小型进度仪表盘。
它专为硬核模式匹配项目设计,其目标是编写出能够编译回与原始二进制文件完全相同的 C/C++ 源代码。该工具不包含游戏资产,不修补二进制文件,也不自行进行反编译。它为 Codex 风格的 Agent 提供了一个紧凑、可重复的“编译-比对-编辑”循环。
预期的工作流与专注的 Codex `/goal` 运行形态相同,其灵感来自
[banteg](https://x.com/banteg) 公开的《风之杖》 匹配反编译实验。
1. 选择一个翻译单元 或函数,
2. 配置/构建本地反编译项目,
3. 运行项目神谕工具(`objdiff`、进度报告或自定义评分命令),
4. 进行小幅源代码编辑,
5. 仅提交可衡量的改进。
## 本地安装
```
uv sync
```
或者,不安装直接运行:
```
uv run decomp-goal --help
```
源码检出的玩具演示还需要本地 C 编译器可用作 `cc`。
## 开发检查
代码仓库使用 Ruff 进行代码检查/格式化,ty 进行类型检查,以及 pre-commit 进行本地钩子管理。
```
uv sync --dev
uv run ruff check .
uv run ruff format --check .
uv run ty check .
uv run pre-commit run --all-files
```
安装本地 git 钩子:
```
uv run pre-commit install
```
## 命令
从 decomp.dev 发现活跃项目:
```
decomp-goal projects --platform gc --query "Wind Waker"
```
查找候选的 GitHub 任务议题:
```
decomp-goal issues --github zeldaret/tww --label "easy object" --unclaimed
```
检查工作树:
```
decomp-goal inspect --repo /path/to/project
```
列出 DTK/ZeldaRET 风格项目中的非匹配候选目标:
```
decomp-goal targets --repo /path/to/tww --limit 20
decomp-goal targets --repo /path/to/tww --rank --limit 20
```
筛选特定模块:
```
decomp-goal targets --repo /path/to/tww --query d_a_obj_mmrr
```
渲染限定范围的 `/goal` 提示词:
```
decomp-goal goal \
--repo /path/to/tww \
--unit src/d/actor/d_a_obj_mmrr.cpp \
--name "Mirror object" \
--issue https://github.com/zeldaret/tww/issues/423
```
运行一次配置/构建/评分过程并写入 JSON 运行记录:
```
decomp-goal run --repo /path/to/project --unit attempt.c
```
运行记录默认写入仓库的 Git 元数据路径下,例如 `.git/decomp-goal/runs/`,因此该工具不会弄脏反编译工作树。
本代码仓库包含一个连接到玩具神谕的根 `decomp-goal.toml`,因此该工具可以审计自身:
```
uv run decomp-goal gaps --repo .
uv run decomp-goal run --repo . --unit attempt.c
```
查看运行历史:
```
decomp-goal history --repo /path/to/project
```
以最新的神谕记录作为进度提交的门控条件:
```
decomp-goal checkpoint --repo /path/to/project
decomp-goal checkpoint --repo /path/to/project --commit
```
`--commit` 仅在最新保存的运行记录优于以往历史时,才暂存并提交当前未提交的工作树。请在执行一次新的 `decomp-goal run` 之后使用它,而不是将其作为神谕的替代品。
检查点还会验证当前的工作树指纹是否与最新的神谕记录匹配,因此过期的成功运行无法授权不相关的编辑。
询问该工具 Agent 是否陷入停滞以及下一步该怎么做:
```
decomp-goal coach --repo /path/to/project
```
分类当前的 diff 并生成下一个线索:
```
decomp-goal lead --repo /path/to/project --unit attempt.start.c
decomp-goal lead --repo /path/to/project --unit attempt.start.c --diff-json objdiff-export.json --diff-format objdiff
```
编写一个有界限的最后冲刺实验队列:
```
decomp-goal experiments --repo /path/to/project --unit src/d/actor/d_a_obj_mmrr.cpp
```
批量测试源代码补丁变体并恢复失败的变体:
```
decomp-goal variants \
--repo /path/to/project \
--unit src/d/actor/d_a_obj_mmrr.cpp \
--patch-dir .git/decomp-goal/variants
```
仅当您希望在批处理后保留应用的最佳改进补丁时,才使用 `--keep-best`。
记录来自人类、Ghidra、IDA、Binja、GPT-Pro 或 objdiff 的外部引导线索:
```
decomp-goal steer \
--repo /path/to/project \
--unit src/d/actor/d_a_obj_mmrr.cpp \
--source ida \
--text "Decompiler agrees on the if/else shape; remaining delta looks like temp lifetime before the call."
```
记录结构化的反编译器输出,并比较不同工具间的一致性:
```
decomp-goal decompilers \
--repo /path/to/project \
--unit src/d/actor/d_a_obj_mmrr.cpp \
--function create__6daPz_cFv \
--source ghidra \
--file ghidra-create.c \
--notes "IDA and Binja agree on branch shape; remaining delta smells like stack temp lifetime."
decomp-goal decompilers --repo /path/to/project --unit src/d/actor/d_a_obj_mmrr.cpp
```
针对 banteg 风格的循环审计当前工作流的不足:
```
decomp-goal gaps --repo /path/to/project
```
在长时间的 tmux/Codex 会话旁运行一个轻量级监控器:
```
decomp-goal monitor \
--repo /path/to/project \
--unit src/d/actor/d_a_obj_mmrr.cpp \
--dashboard-out .git/decomp-goal/dashboard.html \
--interval 300 \
--max-ticks 999
```
使用 `--json` 参数,监控器将输出一个包含所有记录的有效 JSON 数组。
生成本地的 banteg 风格进度仪表盘:
```
decomp-goal dashboard --repo /path/to/project --title "Princess Zelda TU Progress"
```
仪表盘会跟踪确切的函数、匹配的代码、模糊分数、阻碍因素,以及来自存储运行记录的提交/HEAD 更改标记。
编写目标提示词并打印 Codex CLI 运行器命令:
```
decomp-goal codex \
--repo /path/to/tww \
--unit src/d/actor/d_a_obj_mmrr.cpp \
--name "Mirror object" \
--issue https://github.com/zeldaret/tww/issues/423 \
--reasoning-effort xhigh \
--mode tmux \
--session tww-mmrr
```
## 适配器
### 通用 TOML 适配器
如果代码仓库中存在 `decomp-goal.toml`,该工具会从中读取 shell 命令:
```
[project]
name = "toy-match"
adapter = "generic"
default_unit = "attempt.c"
[commands]
build = "uv run --project ../.. python3 score.py --candidate {unit} --build-only"
score = "uv run --project ../.. python3 score.py --candidate {unit} --json"
diff = "uv run --project ../.. python3 score.py --candidate {unit} --diff"
```
评分命令应打印出至少包含以下内容的 JSON:
```
{
"matched": true,
"score": 1.0
}
```
### DTK / ZeldaRET 适配器
对于包含 `configure.py` 和 `tools/project.py` 的项目,该工具会检测出 DTK 风格的项目并运行:
```
python3 configure.py
ninja -v
python3 configure.py progress
```
它还会解析 `configure.py` 中的 `Object(NonMatching, "...")`、`Object(Equivalent, "...")` 以及 ZeldaRET 风格的 `ActorRel(NonMatching, "...")` 条目,以生成候选目标。
该工具不会获取或创建原始游戏输入。如果项目需要合法获取的游戏镜像或提取的文件,运行记录将报告 `missing_original_input`,而不是掩盖这一事实。
## 玩具演示
`examples/toy_match` 是一个无版权问题的微型匹配项目,用于本代码仓库的源码检出。它使用固定标志编译 `original.c` 和候选 C 文件,比较生成的目标字节,并报告精确/模糊分数。
完全匹配:
```
uv run decomp-goal run --repo examples/toy_match --unit attempt.c
```
已知的不匹配:
```
uv run decomp-goal run --repo examples/toy_match --unit attempt.start.c
```
此测试夹具证明该工具的循环无需商业游戏镜像。真正的 ZeldaRET 项目仍使用项目神谕,通常是 `objdiff`。
生成玩具仪表盘:
```
uv run decomp-goal dashboard --repo examples/toy_match --title "Toy Match Progress"
```
## 运行器模型
该工具不需要拥有 Codex。它创建任务数据包并记录神谕结果;Codex 只是其中一个运行器。
使用 `codex exec` 进行有界限的非交互式运行:
```
uv run decomp-goal codex --repo /path/to/tww --unit src/d/actor/d_a_obj_mmrr.cpp --mode exec
```
使用 `tmux` 加上交互式 Codex 进行需要引导的长匹配会话:
```
uv run decomp-goal codex --repo /path/to/tww --unit src/d/actor/d_a_obj_mmrr.cpp --mode tmux --session tww-mmrr --launch
```
tmux 路径更接近 banteg 的工作流:让 Agent 运行,检查仪表盘/历史,并在其于近乎匹配或布局级联之后陷入停滞时注入引导。生成的提示词写在仓库的 Git 元数据路径下,以便在不创建未跟踪文件的情况下对其进行审查或重用。
对于常规的深度运行使用 `--reasoning-effort high`,对于更强的假设比成本/延迟更重要的最后冲刺阶段,使用 `--reasoning-effort xhigh`。
## Banteg 启发的循环
该工具围绕 banteg 在《风之杖》 `d_a_pz` 运行中展示的工作流进行设计:
- 一次设定一个翻译单元目标,
- 不使用伪造匹配或禁止的反编译技巧,
- 每次有意义的编辑后进行编译/diff/评分,
- 仅提交确切的改进、模糊分数的改进或结构布局的解锁,
- 在 Agent 卡住时注入外部线索:人类笔记、GPT-Pro 笔记、Ghidra、IDA、Binja、objdiff、调试映射,
- 将突然出现的精确函数匹配跳跃视为可能的布局级联,直到被证明,
- 在卡住时记录剩余的未匹配类别:字符串池、重定位、分支形状、寄存器分配、弱符号/模板排序、内联、缺失类型或缺失原始输入。
该工具从设计上是一个神谕包装器,而不是一个自主的源代码修改器。`/goal` Agent 可以消费其目标列表、目标数据包、JSON 运行记录和仪表盘,同时在项目工作树中进行实际的源代码编辑。
## 减少最后冲刺的痛苦
痛苦的部分始于翻译单元 (TU) 几乎正确,但仍有少数一两个函数拒绝匹配之时。该工具试图通过强制推行更机械的循环来减轻这种痛苦:
1. `decomp-goal lead` 将 diff 分类为未匹配类别,如字符串池、分支形状、寄存器分配、重定位/调用目标、栈帧、常量/类型或未知类别。
2. 当项目可以导出时,`decomp-goal lead --diff-json` 会提取结构化的 objdiff/asm-differ 风格 JSON。
3. `decomp-goal experiments` 在仓库的 Git 元数据路径下编写一份每次只测试一个假设的变体清单。
4. `decomp-goal variants` 逐个应用补丁文件,运行神谕,记录指标,并恢复未保留的变体。
5. `decomp-goal coach` 监视运行历史以寻找高分瓶颈期,并在 Agent 陷入停滞时告诉其停止大范围重写。
6. `decomp-goal monitor` 在 tmux 会话期间定期运行该指导循环,并在需要干预时写入引导提示词。
7. `decomp-goal steer` 和 `decomp-goal decompilers` 存储外部线索,并将最新的线索注入到下一次生成的 `/goal` 提示词中。
8. `decomp-goal checkpoint` 使“提交每一项改进”变得机械化:它将最新运行与以往历史进行比较,仅当神谕有所改进时才允许提交。
这并不能消除困难的部分,但它可以防止 Agent 在达到 99% 之后随机游走。预期的行为是:首先分类,尝试有界限的变体,恢复失败,仅保留神谕改进的成果,并在相同的未匹配类别经历数次变体后,请求人类/反编译器/调试映射的线索。
剩余的非代码边界是原始游戏输入。该工具会特意报告 `missing_original_input`;它不会获取、生成或绕过受版权保护的游戏素材。
## 致谢
核心概念和工作流灵感来自:[banteg on X](https://x.com/banteg) / [banteg on GitHub](https://github.com/banteg),尤其是公开的《风之杖》 匹配反编译运行,展示了限定范围的 `/goal` Agent 在此问题上的契合度之高。
## TWW 目标数据包示例
```
Get `src/d/actor/d_a_obj_mmrr.cpp` / Mirror object to 100% matching without fakematching or forbidden decomp tricks, with validation in the local worktree.
Rules:
- Use source-level decompilation changes; do not patch generated/original binaries.
- Prefer the project’s existing macros, typedefs, headers, and naming style.
- Make small commits only for measurable improvements.
- Do not mark a function or TU matching unless the local diff/build oracle proves it.
- When stuck, classify the mismatch: layout, string pool, branch shape, regalloc, weak/template ordering, relocation, inline, missing type, or missing original input.
```
## 当前预期的首个真正目标
对于《风之杖》,一个干净的首个目标是:
- 上游代码仓库:`zeldaret/tww`
- Fork:`Muhtasham/tww`
- 目标议题:https://github.com/zeldaret/tww/issues/423
- 单元:`src/d/actor/d_a_obj_mmrr.cpp`
在真正的 TWW 匹配循环运行之前,本地的 TWW 工作树需要在 `orig/GZLE01/` 下提供用户自备的原始输入,正如上游 README 中所述。
标签:C/C++, CLI, Codex, Decompilation, diff oracle, objdiff, Python, Python安全, Ruff, URL提取, uv, WiFi技术, Wind Waker, ZeldaRET, 事务性I/O, 二进制分析, 二进制发布, 云安全监控, 云安全运维, 云资产清单, 代码对比, 任务自动化, 匹配反编译, 反编译, 安全可观测性, 开源工具, 无后门, 游戏逆向, 源码还原, 版本控制, 网络安全研究, 自动化构建, 逆向工具, 逆向工程, 静态分析