AI 逆向工程協作:Source Inventory 協議讓一比一重建不再落東掉西

重點摘要

  • AI 協作做逆向工程,最大的坑不是技術,而是 AI 「選擇性閱讀」原始碼
  • 根治方法:強制 Source Inventory 協議 — 動手前先列清單、附行號、用戶確認邏輯後才寫程式
  • 用戶不需要知道原版長什麼樣,清單上的每一項都要有原始碼行號出處
  • 這套協議已寫入 CLAUDE.md,適用於任何 legacy code 逆向重建專案

最近在做一個系統重建專案:把一套已上線多年的 Ionic + PHP 系統,逐頁逐模組一比一重建為 Flutter 應用。聽起來直白,實際做起來卻踩了一個讓人很沮喪的坑——不是技術難度的問題,而是 AI 協作流程設計的問題

這篇文章記錄我如何診斷這個問題,並建立一套可複用的 AI 逆向工程協作協議。

問題:一比一複製,卻一直落東掉西

我明確告訴 AI:「這是舊版原始碼,你幫我一比一複製到 Flutter。」但每次交付,都會發現缺少功能。最典型的例子:登入後的登出功能不見了

登出不是什麼複雜功能,但它不在主流程頁面——它藏在 header component 的某個角落。AI 在讀原始碼的時候,只讀了主頁面,沒讀共用元件,自然就沒看到登出按鈕的存在。

更麻煩的是:我自己也不知道原版長什麼樣(這是別人開發的系統),所以我也沒辦法直接指出「你少了這個」。每次都要在用起來的時候才發現缺少什麼,然後重來。

根本原因:AI 的「選擇性閱讀」

深入想了一下,問題的根源在於 AI 讀原始碼的方式:

錯誤的讀法 正確的讀法
找「我預期會有的東西」 逐行掃描,列出「所有看到的東西」
只讀主要頁面檔案 讀所有相關檔案(service、routing、共用元件)
憑印象補齊功能 每一項都有原始碼出處(檔案 + 行號)
「讀完」就開始寫 產出清單、確認後才開始寫

用一句話說:AI 是在「確認自己的預期」,不是在「完整盤點原始碼」。這種差距在簡單頁面感覺不出來,在有大量共用邏輯的真實系統裡,每個模組都會漏東西。

解法:Source Inventory 協議

我和 AI 一起設計了一套強制執行的協議,並寫入專案的 CLAUDE.md,讓每個接手這個專案的 AI session 都必須遵守。

Step 0 — 列出所有要讀的檔案(動手前)

在讀任何內容之前,先列出這個模組涉及的所有檔案,包含:

  • 頁面本體(template + logic)
  • 所有被引用的 service
  • 共用元件(header、footer、tab-bar、nav)
  • 路由設定
  • 後端 handler

每個檔案讀完打勾,沒打勾的不算讀過。這一步強迫 AI 在開始之前就意識到「這個模組牽涉哪些檔案」,避免只讀主檔就動手。

Step 1 — 產出 Source Inventory(每項附行號)

讀完所有檔案後,產出功能清單。格式固定:

- [ ] 登出按鈕
      來源:home.page.html:142 <ion-button (click)="logout()">

- [ ] 下拉刷新
      來源:ticket.page.html:38 <ion-refresher (ionRefresh)="doRefresh($event)">

- [ ] 空狀態提示
      來源:ticket.page.html:91 <div *ngIf="tickets.length === 0">目前沒有票券</div>

關鍵點:每一項都必須有原始碼的檔案和行號

這解決了「用戶不知道原版長什麼樣,所以沒辦法驗證清單正確性」的問題。用戶不需要看過原版,只需要問:「這一項你是從哪行讀到的?」答不出來,就代表是 AI 憑印象補的,不是真的在原始碼裡。

Step 2 — 逐項實作,逐項打勾

對照清單一項一項做,每完成一項就打勾。不允許「大概實作了」或「之後再補」。

Step 3 — Self-Verify 後才交付

交付前,AI 自己對照清單跑一遍,確認每項都存在於程式碼中。如果 Step 3 發現漏項,必須補完再說「完成」。漏項不能留給用戶發現。

一條關鍵規則:禁止在原始碼存在的情況下向用戶索取截圖

另一個常見的壞模式是:AI 讀不懂某個行為,就跟用戶要截圖或圖片。

這在逆向工程的情境下尤其荒謬。用戶拿到舊系統原始碼,通常自己也沒有截圖,甚至從來沒用過那個系統。要求用戶提供截圖,是把 AI 本來應該做的工作(讀原始碼)轉嫁給用戶。

正確的做法是:原始碼讀不懂的地方,標記 [?],說明不確定的點,讓用戶確認業務邏輯——而不是要求視覺確認。

這套協議適用於任何逆向升級工程

雖然這次的情境是 Ionic → Flutter,但這套協議的核心邏輯對任何 legacy 重建都適用:

  • jQuery / AngularJS → React / Vue
  • PHP monolith → 現代後端(Go、Node、Python)
  • 原生 Android/iOS → Flutter / React Native
  • 桌面應用 → Web 應用

只要是「拿到舊系統 code,重寫到新技術棧」,用戶通常都不知道原版的全貌,也無法驗證 AI 是否讀完了所有東西。Source Inventory + 行號出處 是讓這個過程可稽核的最低門檻。

如何在你的專案裡執行這套協議

把以下內容加入你的專案 CLAUDE.md(或任何 AI 工作指引文件):

## 一比一複製協議(MANDATORY)

> 原始碼是唯一的 ground truth。用戶不應該被要求提供截圖。

### Step 0 — 列出所有要讀的檔案
(所有頁面、service、共用元件、routing、後端 handler)
每個檔案讀完打勾,沒打勾不算讀過。

### Step 1 — Source Inventory(每項附檔案:行號)
格式:
- [ ] 功能描述
      來源:filename.html:LINE_NUMBER <原始碼片段>

### Step 2 — 逐項實作,逐項打勾

### Step 3 — Self-Verify 後才交付

### 禁止行為
- 在原始碼存在的情況下向用戶索取截圖
- 沒有產出 Source Inventory 就開始寫程式
- 只讀主頁面,不讀 service / routing / 共用元件

結語

逆向升級工程的難點不在技術轉換,而在於如何保證「沒有遺漏」。AI 的天性是預測下一個 token,這讓它容易「補全期望的樣子」,而不是「如實記錄看到的東西」。

Source Inventory 協議的作用,就是把 AI 的工作模式從「自由發揮」強制切換成「逐行比對」。這不是在限制 AI,而是在讓 AI 的輸出變得可以被信任。

如果你也在做類似的逆向重建專案,歡迎把這套協議複製進你的 CLAUDE.md,看看效果如何。

留言

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *