---
name: s2arm-rootfix
description: S2Arm 通用根修方法论：修任何缺陷、做任何会改行为的改动之前先读本 skill。规定从「这件事要证明什么」出发，先量再猜、找到给错值的机制、对齐 Ryujinx 上游真值、先写会红的单测、做负对照、报射程，最后按 PR 模板交付。具体症状的定位走 gfx-triage / native-triage 和 docs/排查/ 下的手册。
---

# 通用根修（s2arm-rootfix）

你在为 S2Arm 修一个问题或做一处会改变行为的改动。本 skill 只管**方法和交付格式**；症状怎么定位见下面的「去哪查」。维护方审 PR 时就按这里逐条核。

## 0. 先回到本质

动手前用一两句话写下：**这次改动要证明什么、要让哪个读数从什么变成什么**。例如「让动森进局后帧率 ≥ 29.7 Hz（现在 24 Hz）」，而不是「优化一下渲染」。写不出来就是还没弄清问题，先去量。

## 1. 先量再猜

- 只信读数：`host.log` 的具体行、`frames.tsv`、功耗采样、工具报告（`docs/贡献者开发测试套件.md` 第 1 步的自查报告）。凭印象下的结论不算数。
- 一次只变一个量；A/B 两边只差你要验证的那一个改动。
- 偶发问题先复现到可重复（循环跑 N 次，记下 N 次里出现几次），再谈根因。

## 2. 找到给错值的机制，修机制不修症状

- 一直往上追，直到找到**第一个算错 / 给错值的地方**，在那里修。在下游加判断、吞异常、改阈值、加重试，都是改症状，不收。
- 服务、系统调用、着色器语义有疑问时，**以 Ryujinx 上游为真值**：先读上游同一处怎么做。我方偏离上游必须有理由，并写进 `compat/改动清单.md`；改 `compat/tree/` 要走 `compat/patches/` 新补丁（`bash compat/verify.sh` 一致）。
- 通用层零专用配置：不写死游戏地址，不按游戏名 / 程序号分支，未实现的服务报红、不返回成功兜底。

## 3. 先红后绿

1. 先写一条**在当前 main 上会红**的单测或判据，并把红日志原样存下（PR 里要贴）。
2. 期望值必须**不跑被测实现就能算出来**：手算、规格、上游行为。用被测代码自己的输出当期望，等于没测。
3. 再改代码，直到它变绿；原有单测全部照绿。
4. 能用规则或代码判定的，就不要用 LLM 判。

## 4. 负对照

把你的修复**回退**（或换成典型的错误写法），新单测必须重新变红；PR 里写明你做了哪种回退、红在哪一行。负对照不红，说明单测「绿着失效」，没有守住任何东西。

## 5. 报射程

任何「全绿 / 0 不符」都要同时写**分母**：扫了几个文件、跑了几局、多少帧、几款游戏、哪几种设备。例如「接线扫描 232 支，未接线 0」「3 款各 1 局，到 MARK，0 崩」。只写「通过」的读数，维护方按没跑处理。

## 6. 外科手术式改动

每一行改动都能追溯到这次要解决的问题。不顺手重构、不改无关文件、不重写整文件；发现别的问题写进 PR 的「限制 / 后续」，另开 issue。

## 7. 交付

- 跑 `bash tools/contrib_check.sh`，摘要原样贴进 PR 的「一级自检」栏。
- PR 模板四栏必填：**修前 → 修后读数表**（期望 → 实测）、**负对照**、**射程**、**一级自检摘要**。
- 踩到新坑、得到新结论，按 `AGENTS.md` 的规矩追加到 `docs/坑记录.md` 或 `docs/性能与开发测试经验.md`：现象 → 根因 → 读数（期望 → 实测，注明设备 / 提交号 / 局数）→ 做法。
- 不提交游戏文件、密钥、存档、资源包、游戏截图；日志里的本机路径、设备号、账号先用 `tools/diagnostic_report.py` 脱敏。

## 去哪查（按症状）

| 症状 | 先读 |
|---|---|
| 花屏、贴图错、闪烁；不满屏、宽屏异常；没走直连、直连异常 | `skills/gfx-triage/` 及 `docs/排查/` 下对应三份手册 |
| 崩溃；进不去、停在 Break；服务回答不对 | `skills/native-triage/` 及 `docs/排查/` 下对应三份手册 |
| 帧率低、耗电高 | `skills/fps-power-triage/` 及 `docs/排查/帧率低与耗电高.md`、`docs/性能与开发测试经验.md` |
| 自动玩家卡住、没到 MARK | `docs/排查/自动玩家没到MARK.md` |
| 修直连前端时查 NVN 语义和教训 | `skills/nvn-wire/`（语义参照，不是施工流程） |
| 宽屏第三层视觉判定 | `skills/widen-judge/` |

## 读数表样例（PR 里照这个格式）

| 项 | 期望 → 实测 |
|---|---|
| 新单测在 main 上 | 红 → 红（`<一行红日志>`） |
| 新单测在本 PR 上 | 绿 → 绿 |
| 负对照：回退 `<哪一处>` | 红 → 红（`<红在哪>`） |
| 原有单测（`gate_route` 列出的） | 全绿 → 23/23 |
| 射程 | `<扫了什么 / 多少个>` |
