<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Code Review | Francis Du</title>
    <link>https://francisdu.com/tags/code-review/</link>
      <atom:link href="https://francisdu.com/tags/code-review/index.xml" rel="self" type="application/rss+xml" />
    <description>💻Data Engineer | 🦀 Rustacean | 📷 Photographer | 🤖Vibe Coder</description>
    <generator>Hugo 0.166.0</generator><language>zh-CN</language><copyright>© Francis Du</copyright><lastBuildDate>Wed, 26 Aug 2026 03:13:00 +0800</lastBuildDate>
    <item>
      <title>wcode：Git Diff 之外，我还想知道什么</title>
      <link>https://francisdu.com/blog/wcode-traceability/</link>
      <pubDate>Wed, 26 Aug 2026 03:13:00 +0800</pubDate>
      <guid>https://francisdu.com/blog/wcode-traceability/</guid>
      <description>&lt;p&gt;我做 Code Review 时很少只看 Diff。&lt;/p&gt;
&lt;p&gt;Diff 只是入口。&lt;/p&gt;
&lt;p&gt;看到一个函数被改，我脑子里会自动继续问：谁在调用它？这个模块原来为什么这么写？有没有对应测试？它是不是安全边界？这次只是重构，还是已经改变了设计？&lt;/p&gt;
&lt;p&gt;这些问题以前都靠人自己补。&lt;/p&gt;
&lt;p&gt;Agent 也一样，只不过它能补多少，很看这一次上下文有没有给够。&lt;/p&gt;
&lt;p&gt;所以做完 Design State 和 Software Graph 以后，我开始把其中一部分变成 wcode 可以直接算的东西。&lt;/p&gt;
&lt;h2 id=&#34;traceability-先回答最笨的问题&#34;&gt;Traceability 先回答最笨的问题&lt;a class=&#34;heading-anchor&#34; href=&#34;#traceability-%e5%85%88%e5%9b%9e%e7%ad%94%e6%9c%80%e7%ac%a8%e7%9a%84%e9%97%ae%e9%a2%98&#34; aria-label=&#34;章节链接：Traceability 先回答最笨的问题&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;traceability_status&lt;/code&gt; 主要看几条链有没有断：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Requirement → Component
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Component → Implementation
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Acceptance Criterion → Verification
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;我一开始考虑过做一个总 Coverage。&lt;/p&gt;
&lt;p&gt;比如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;87%
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;后来觉得没什么用。&lt;/p&gt;
&lt;p&gt;如果丢的是一个低优先级页面的 Acceptance，和丢的是 Workspace Root Isolation 的测试，显然不是同一件事。把它们平均成一个百分比，信息反而少了。&lt;/p&gt;
&lt;p&gt;所以现在直接分开报。&lt;/p&gt;
&lt;p&gt;我更想看到这种东西：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Requirement 还在
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Component 还在
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;但原来映射的 Symbol 已经搬走了
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;或者：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Acceptance 还指着一个已经改名的 test
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这种错误没有多高级，但特别常见。&lt;/p&gt;
&lt;h2 id=&#34;product-scope-解决别把整个仓库都拖进来&#34;&gt;Product Scope 解决“别把整个仓库都拖进来”&lt;a class=&#34;heading-anchor&#34; href=&#34;#product-scope-%e8%a7%a3%e5%86%b3%e5%88%ab%e6%8a%8a%e6%95%b4%e4%b8%aa%e4%bb%93%e5%ba%93%e9%83%bd%e6%8b%96%e8%bf%9b%e6%9d%a5&#34; aria-label=&#34;章节链接：Product Scope 解决“别把整个仓库都拖进来”&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;wcode 后来又加了 Product Scope，因为只靠 Requirement 还不够。&lt;/p&gt;
&lt;p&gt;项目一大，Context 很容易横跨一堆不相关目录。&lt;/p&gt;
&lt;p&gt;现在我通常先跑 &lt;code&gt;scope_status&lt;/code&gt;，看看源码是怎么落在各个 Scope 里的，还有没有没归类的文件。真正做任务时，&lt;code&gt;software_context(scopes=...)&lt;/code&gt; 会把源码导航收窄到指定范围。&lt;/p&gt;
&lt;p&gt;例如我只在 &lt;code&gt;workspace&lt;/code&gt; / &lt;code&gt;risk&lt;/code&gt; 一类 Scope 里查，就不会顺手把 UI、Connector、Release 相关东西一起塞进来。&lt;/p&gt;
&lt;p&gt;这个功能对模型没有那么“惊艳”，但对长期项目很实用。Context 少一点，误判也少一点。&lt;/p&gt;
&lt;h2 id=&#34;drift-不是报错更像提醒&#34;&gt;Drift 不是报错，更像提醒&lt;a class=&#34;heading-anchor&#34; href=&#34;#drift-%e4%b8%8d%e6%98%af%e6%8a%a5%e9%94%99%e6%9b%b4%e5%83%8f%e6%8f%90%e9%86%92&#34; aria-label=&#34;章节链接：Drift 不是报错，更像提醒&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Traceability 看的是“关系还通不通”，Drift 看的是“变化之后，两边是不是开始不一致”。&lt;/p&gt;
&lt;p&gt;现在大致有两类。&lt;/p&gt;
&lt;p&gt;一种是 Implementation Drift。&lt;/p&gt;
&lt;p&gt;Design 变了，代码没跟；或者原来声明的实现、验证链现在断了。&lt;/p&gt;
&lt;p&gt;另一种是 Design Drift。&lt;/p&gt;
&lt;p&gt;某个已经有 Design 身份的实现被改了，但这次 Design State 完全没动。&lt;/p&gt;
&lt;p&gt;第二种不能理解成“改代码必须改 YAML”。&lt;/p&gt;
&lt;p&gt;很多重构当然不需要改设计。&lt;/p&gt;
&lt;p&gt;所以它更像一句提醒：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;这个地方在 Design State 里是有名字的，现在代码变了，确认一下原来的描述还成立。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;我不想把这种 heuristic 叫 formal verification。它没那么聪明。&lt;/p&gt;
&lt;h2 id=&#34;impact-是我真正天天想看的东西&#34;&gt;Impact 是我真正天天想看的东西&lt;a class=&#34;heading-anchor&#34; href=&#34;#impact-%e6%98%af%e6%88%91%e7%9c%9f%e6%ad%a3%e5%a4%a9%e5%a4%a9%e6%83%b3%e7%9c%8b%e7%9a%84%e4%b8%9c%e8%a5%bf&#34; aria-label=&#34;章节链接：Impact 是我真正天天想看的东西&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Git 能给 Changed Paths，但 Review 时我通常还想看：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;碰到了哪些 Component
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;关联哪些 Requirement
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;哪些 Acceptance 需要重新验证
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;调用方有哪些
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;有没有 Public API 信号
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;有没有 Security Boundary
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;impact_analysis&lt;/code&gt; 会从 Working Tree 开始，再沿 Composite Software Graph 往调用方扩。&lt;/p&gt;
&lt;p&gt;现在主要看 &lt;code&gt;Calls&lt;/code&gt; / &lt;code&gt;RuntimeCalls&lt;/code&gt; 这类关系。&lt;/p&gt;
&lt;p&gt;有 fresh LSP / Runtime Provider 就用更高精度的关系；没有就退到 Tree-sitter Syntax Edge。结果里会保留 Provider 和 Precision，不把不同来源混成一句“确定会影响”。&lt;/p&gt;
&lt;p&gt;这也是为什么前面 Software Graph 那篇我一直强调 provenance。&lt;/p&gt;
&lt;p&gt;没有 provenance，Impact 最后只剩一个很自信的列表，但没人知道它为什么这么判断。&lt;/p&gt;
&lt;h2 id=&#34;transitive-analysis-一定得有刹车&#34;&gt;Transitive Analysis 一定得有刹车&lt;a class=&#34;heading-anchor&#34; href=&#34;#transitive-analysis-%e4%b8%80%e5%ae%9a%e5%be%97%e6%9c%89%e5%88%b9%e8%bd%a6&#34; aria-label=&#34;章节链接：Transitive Analysis 一定得有刹车&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;调用图特别容易爆。&lt;/p&gt;
&lt;p&gt;一个底层 helper 可能被几百个地方用。如果“所有调用方的调用方再递归展开”没有上限，最后返回的 Context 比直接把仓库读一遍还离谱。&lt;/p&gt;
&lt;p&gt;所以 wcode 这类 Query 都是 bounded 的。&lt;/p&gt;
&lt;p&gt;到上限就明确返回：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;truncated = true
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;我宁愿看到一个“这里没展开完”，也不要看到一份看起来完整、其实只是因为上下文被截断而少东西的结果。&lt;/p&gt;
&lt;h2 id=&#34;review-里现在还会看代码是不是开始长歪&#34;&gt;Review 里现在还会看代码是不是开始长歪&lt;a class=&#34;heading-anchor&#34; href=&#34;#review-%e9%87%8c%e7%8e%b0%e5%9c%a8%e8%bf%98%e4%bc%9a%e7%9c%8b%e4%bb%a3%e7%a0%81%e6%98%af%e4%b8%8d%e6%98%af%e5%bc%80%e5%a7%8b%e9%95%bf%e6%ad%aa&#34; aria-label=&#34;章节链接：Review 里现在还会看代码是不是开始长歪&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;最近 &lt;code&gt;review_changes&lt;/code&gt; 又加了一些结构信号。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;一个源码文件从 1,000 行以下跨到 1,000 行以上
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;大量净新增集中在一个文件
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;一次大改横跨多个 Product Scope
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这些不会直接判“代码质量差”。&lt;/p&gt;
&lt;p&gt;它们只是进入 Risk，让后面的 Verification 决定是不是要增加 Maintainability Review。&lt;/p&gt;
&lt;p&gt;这个区别我觉得挺重要。&lt;/p&gt;
&lt;p&gt;工具可以很容易数行数，但“抽象是不是多余”“是不是出现了重复的 canonical helper”“是不是为了兼容又堆了一层 wrapper”，这些还是要 Review。&lt;/p&gt;
&lt;p&gt;所以确定性信号负责发现值得看一眼的地方，Reviewer 再判断是不是问题。&lt;/p&gt;
&lt;p&gt;现在 Project Observatory 也会把 Requirement、实现、Verification、Git Change 和依赖关系放在一起。我平时打开它，基本就是为了回答这篇文章标题那个问题：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Diff 之外，这次到底动了什么。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Impact 算出来只是知道该看哪里，最后还是要落到“怎么证明这次改动真的可以”。Verification 和 Evidence 我放在 &lt;a href=&#34;https://francisdu.com/blog/wcode-verification/&#34;&gt;测试通过以后，我还想留下什么&lt;/a&gt; 里。&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>