文章目录
- 1. 四个场景先分清问题
- 2. 场景一:核对本人的发布包
- 3. 场景二:许可允许时记录接口行为
- 4. 场景三:比较两个有权分析的版本
- 5. 场景四:把缺陷收成可复核记录
- 6. 四个场景不要混在一条结论里
- 7. 这些情况不要进入调查场景
- 8. 用一条虚构记录走完验收
- 9. 落地时按这个顺序选
- 10. 四个场景各填一条完整记录
- 10.1 发布包核对
- 10.2 接口行为
- 10.3 版本差异
- 10.4 缺陷记录
- 10.5 一次跑完这些记录
- 11. 小结
这篇只讲 REA(Reverse Engineer Anything)该用在什么问题上。不排星数,也不拿别的模型比谁更强。
REA 是跑在本机的调查接口,仓库是 morluto/rea,npm 包名是 rea-agents。它把编程智能体和本机分析能力接在一起,用来查看你有权分析的已发布制品,并要求结论带上证据和局限。它自己不是大模型,也不把闭源程序还原成原来的源码。
动手之前先做三步判断。任何一步不成立,就不要进入后面的场景。
- 对象是不是已经发布的制品。仓库里的源码已经能解释时,直接读源码。
- 要回答的是行为问题,而不是一个分类、打分或是否继续的选项。
- 你是否有权分析这个对象。许可不允许,场景表不适用。
1. 四个场景先分清问题
四个场景问的不是同一句话。选错行,后面的记录会把观察、猜测和实现方案写进同一段。
| 场景 | 你手里有什么 | 要回答的问题 | 合格记录 | 不能当成结果 |
|---|---|---|---|---|
| 核对发布包 | 自己构建并持有的包,以及仓库说明 | 制品里的行为和说明是否一致 | 一致点、差异点、证据编号 | 别人复制了这段实现 |
| 接口行为 | 许可允许分析的程序或调用端点 | 调用前后外面看见了什么 | 输入、可见结果、失败表现、未知项 | 可以对外发布的协议原文 |
| 版本差异 | 两个你有权分析的版本 | 哪一段可见行为变了 | 逐条差异,每条带证据和未知项 | 升级指南或补丁 |
| 缺陷记录 | 现象和复现条件 | 现有证据能把现象支持到哪 | claim、limitation、unknown 分开 | 可以直接粘贴的修复代码 |
图 1:先选定场景,再写记录。四类问题不能混在同一条结论里。
2. 场景一:核对本人的发布包
适合构建和发布都由你完成的情况。仓库说明写了期望行为,运行起来却对不上,你要先确认制品里实际发生了什么。
触发条件有三条。
- 包是你构建的,或者授权明确允许你分析这份制品。
- 仓库说明已经写了期望行为,但运行现象不一致。
- 你要的是差异清单,不是一份新的实现。
这个场景只回答一句:已发布制品里的该行为,和仓库说明是不是同一条路径。
合格记录分成三项。
- 一致的部分写进 claim,并给出 evidenceId。
- 对不上的部分单独列出,不要写成“所以实现应该改成某某”。
- 还没看到的路径写进 unknown,例如持久化、失败回退。
常见误用是把差异写成“外部程序抄了仓库”。核对发布包只能说明这份制品和这份说明是否一致,不能推出另一份程序的来源。
3. 场景二:许可允许时记录接口行为
适合要对接一个没有完整文档的接口,并且许可或授权明确允许观察调用前后的可见行为。
触发条件有三条。
- 你需要知道调用之后外面能观察到什么。
- 你没有得到、也不需要原始实现。
- 成功、失败、超时、重复调用都在要问的范围内。
记录固定四个槽位:调用前状态、发起了什么、外面看见了什么、哪一种失败这次没有覆盖。
合格记录回答的是行为。它不是协议规范,也不是一份可以替换对方实现的代码。交给后续编写的人时,要注明这是观察,不是对方的设计文档。
常见误用是观察了一次成功路径,就写成完整协议。成功路径只覆盖 limitation 以外的部分。没有 limitation 的记录不能进入对接设计。
4. 场景三:比较两个有权分析的版本
适合同一功能有两个版本、可见行为发生了变化的情况。先确认变的是哪一段结果,再谈要不要改自己的实现。
触发条件有三条。
- 两个制品你都有权分析。
- 比较的是同一功能的可见行为,不是整个产品的感觉。
- 每个版本都能指出对应的证据。
合格记录是一张差异表,不是一篇升级说明。每一行只放一件事。
| 差异 | 旧版本可见行为 | 新版本可见行为 | 证据 | 仍未知 |
|---|---|---|---|---|
| 点击后的计数 | 立即加 1 | 加 1,但文案下一帧才变 | 各自的证据编号 | 失败时是否回滚 |
没有“证据”和“仍未知”的行只是印象,不能算版本结论。
常见误用是把版本差异直接写成迁移步骤。迁移方案是后续设计,不是这个场景的产出。
5. 场景四:把缺陷收成可复核记录
适合只有现象、暂时没有可以改的源码、需要把现象交给下一个人复核的情况。
触发条件有三条。
- 现象能复述:做了什么,看见了什么。
- 你分得清已经看到的和还没看的。
- 目的是交接,不是当场给出修复代码。
这个场景最容易写脏。claim 里一旦出现“应该改成”,它就不再是缺陷记录。修复方案另写。
合格记录只放四项。
- claim:点击按钮后,计数没有增加,按钮文案仍是旧值。
- evidenceId:指向这次观察留下的记录。
- limitation:只看了连续点击一次的情况。
- unknown:是否与焦点丢失有关,本次没有验证。
常见误用是现象还不稳定,就写成根因。根因要等证据编号能被另一个人复核之后再讨论。
6. 四个场景不要混在一条结论里
同一次调查只选一个主场景。
- 发布包核对问的是和说明是否一致。
- 接口行为问的是外面看见了什么。
- 版本差异问的是两版之间变了什么。
- 缺陷记录问的是现象能复核到哪。
混用的典型样子,是一条 claim 里同时写了差异、猜测的根因和准备采用的实现。读的人无法知道哪半句是观察,哪半句是打算。
先选场景,再填字段。字段跟着场景走,而不是把四个问题答进同一段话。
7. 这些情况不要进入调查场景
下面几种需求,不该套用上面的四张表。
- 仓库源码已经能解释这个行为。直接读代码,不要再包一层调查。
- 你只有一个选项要选,例如分类、打分、是否继续。那是决策,不是对制品行为的记录。
- 对象不是你有权分析的制品。许可不允许,场景表就不适用。
- 你想要的产出是可发布的原实现或补丁。四个场景都不产出这个。
8. 用一条虚构记录走完验收
下面的例子是自己构建的计数器,用来演示记录怎么写。它不代表任何已发布产品,也不包含分析步骤。
typeScene="package"|"behavior"|"diff"|"defect";interfaceSceneRecord{scene:Scene;claim:string;evidenceId:string;limitation:string;unknown:string[];}constdefectRecord:SceneRecord={scene:"defect",claim:"点击一次后,计数值没有增加,按钮文案保持旧值",evidenceId:"demo-counter#click-once",limitation:"只观察了连续点击一次",unknown:["焦点丢失后是否仍然复现"]};functionacceptRecord(item:SceneRecord):string[]{consterrors:string[]=[];if(!item.claim.trim())errors.push("缺少观察到的行为");if(!item.evidenceId.trim())errors.push("缺少证据编号");if(!item.limitation.trim())errors.push("缺少本次没覆盖的范围");if(item.claim.includes("应该改成"))errors.push("claim 混入了实现方案");returnerrors;}acceptRecord返回空数组,只说明槽位齐全,并且 claim 没有混入实现方案。它不证明现象为真。证据编号对不上时,记录仍然不能交接。
四个场景都可以套这个结构。scene决定 claim 该写什么:发布包场景写是否与说明一致,接口场景写外面看见了什么,差异场景写哪一条可见行为变了,缺陷场景写现象是什么。
9. 落地时按这个顺序选
- 先把要回答的问题写成一句。写不出单句,就还没进入场景。
- 对照第 1 节的表,只选一行。
- 按那一行的合格记录填写 claim、evidenceId、limitation、unknown。
- 用第 8 节的检查看 claim 有没有混入“应该改成”。
- 检查不通过就停在记录,不进入实现讨论。
10. 四个场景各填一条完整记录
下面用同一个自建计数器把四个场景走完。它是本地示例,不代表任何已发布产品。每条记录先写现场,再填字段,最后给出验收结果。验收只检查记录槽位,不判断现象是否真实。
10.1 发布包核对
现场:仓库说明写着单击后计数立即加 1,按钮文案在同一次更新里刷新。你持有的 1.2.0 发布包里,计数立即加 1,文案要到下一帧才变。
要回答的一句:这份发布包和仓库说明是不是同一条路径。
constpackageRecord:SceneRecord={scene:"package",claim:"1.2.0 单击后计数立即加 1,按钮文案下一帧才更新,与说明中的同一次更新不一致",evidenceId:"demo-counter-1.2.0#click",limitation:"只核对了单击成功路径",unknown:["长按和失败回滚是否也与说明不一致"]};验收错误列表为空。下一步只能开差异说明。claim 里不能补上一句实现应该改成同一次更新,那是后续设计。
10.2 接口行为
现场:你有权观察的本地接口,请求体 n 为 0。成功时状态 200,响应体 n 为 1。超时和重复提交这次没有做。
不合格记录把方案写进了 claim。
constbehaviorBad:SceneRecord={scene:"behavior",claim:"接口应该改成返回旧值,而不是加 1 后的新值",evidenceId:"local-count#post",limitation:"未观察超时",unknown:["重复提交是否幂等"]};合格记录只写外面看见的事实。
constbehaviorOk:SceneRecord={scene:"behavior",claim:"请求体 n 为 0 时,成功响应状态为 200,响应体 n 为 1",evidenceId:"local-count#post-ok",limitation:"未观察超时和重复提交",unknown:["重复提交是否幂等"]};behaviorBad 会得到错误:claim 混入了实现方案。behaviorOk 的错误列表为空。只有后者能交给对接设计,并注明这是观察,不是协议原文。
10.3 版本差异
现场:1.1.0 单击后文案立即变化。1.2.0 单击后文案下一帧才变化。两个包都是你自己的构建。计数增加的时机没有变。
constdiffRecord:SceneRecord={scene:"diff",claim:"同一单击路径上,1.2.0 的按钮文案比 1.1.0 晚一帧,计数增加时机没有变",evidenceId:"demo-counter#1.1.0-vs-1.2.0",limitation:"没有比较长按",unknown:["失败时两个版本是否都会回滚计数"]};验收通过。这条记录回答变了什么,不回答要不要迁移。迁移步骤另写,不能回写进 claim。
10.4 缺陷记录
现场:单击一次后计数值没有增加,按钮文案保持旧值。只做了这一次,没有验证焦点丢失。
constdefectRecord:SceneRecord={scene:"defect",claim:"单击一次后计数值没有增加,按钮文案保持旧值",evidenceId:"demo-counter#click-once",limitation:"只观察了连续单击一次",unknown:["焦点丢失后是否仍然复现"]};验收通过。交接时只转交这四项。根因和修复代码都不在这条记录里。
10.5 一次跑完这些记录
constrecords=[packageRecord,behaviorBad,behaviorOk,diffRecord,defectRecord];constreport=records.map(function(item){return{scene:item.scene,evidenceId:item.evidenceId,errors:acceptRecord(item)};});预期输出:
demo-counter-1.2.0#click errors=[] local-count#post errors=[claim 混入了实现方案] local-count#post-ok errors=[] demo-counter#1.1.0-vs-1.2.0 errors=[] demo-counter#click-once errors=[]错误列表为空,只说明槽位齐全,且 claim 没有混入方案。错误列表非空,说明这条记录还不能交接。两种结果都不证明计数器行为已经核对为真,证据编号仍要对上同一次观察。
11. 小结
REA 能不能用,取决于场景有没有分开。发布包核对、接口行为、版本差异、缺陷记录,问的不是同一句话,合格产出也不同。
选错场景时,后文写得再长,也只是把观察、猜测和实现方案混在一起。先选表里的一行,再写一条带证据编号和局限的记录。