兩個「只查不改」的 Subagent:欄位影響範圍 finder 與多檔一致性 checker


Claude Code 的 subagent 不一定要「做事」——也可以「只查」。

在 Legacy 多檔架構裡,最花時間的不是寫程式,是搞清楚改動的影響範圍:這個欄位用在哪幾個檔案?改了編輯頁,列印版和匯出版有沒有跟著改?這些查詢需要掃大量檔案、讀很多內容——丟給主 session 做會吃光 context。

我做了兩個「只查不改」的 subagent 來分擔這件事:field-finder(欄位影響範圍)和 consistency-checker(多檔一致性)。這篇拆解它們的設計,以及為什麼「查詢型 subagent」是 Legacy 維護的利器。


為什麼查詢要獨立成 subagent

掃「某欄位用在哪 30 個檔案」這種查詢,會讀進大量檔案內容。如果在主 session 做:

  1. 吃光 context:30 個檔案的內容塞進主對話,後面的工作沒空間了
  2. 污染對話:一堆 grep 結果夾在對話裡,主線思路被打斷

Subagent 解決這個——它在獨立的 context 跑查詢,只把「結論」回報給主 session。30 個檔案的雜訊留在 subagent 裡,主 session 只拿到一份乾淨的影響範圍報告。

這是 subagent 最被低估的用法:不是平行做事,是隔離 context


Subagent 一:field-finder(欄位影響範圍)

它回答什麼

Q108 這個欄位用在哪些檔案?」「改 HospNo 會影響哪些頁面?」

frontmatter:

---
name: AppSystem-field-finder
description: 欄位影響範圍 finder。給一個欄位名(Q108、HospNo、service_type_flag、mOrgGroup),
  找出它在 form / print / export / 申報 / ajax / class / sql / DB validation_setting
  哪些檔案出現,回報路徑 + 行號 + 上下文。不改檔,只報告。
  Use PROACTIVELY when 用戶問「XX 欄位用在哪?」「改 Q108 會影響哪些頁面?」
tools: Read, Glob, Grep, Bash
model: sonnet
---

description 寫滿觸發詞 + PROACTIVELY,讓主 session 在使用者問「這欄位用在哪」時自動派它出馬。

設計亮點 1:防呆優先

### 1. 防呆(先做)

- 若欄位名 < 3 字元(id、pw)或極通用(name、type、date):
  → 警告會大量 false positive,建議加 prefix 縮限(Q_id、->name)後再執行

id 會 grep 出幾千個結果,毫無意義。先擋掉會爆量的查詢,要求使用者縮限——這比跑完吐出 3000 行結果有用。

設計亮點 2:欄位有多種「長相」

同一個欄位 Q108,在程式碼裡有很多寫法。Skill 要求準備所有變形:

### 2. 準備 grep pattern(多種變形)

針對欄位 X,至少準備:
- 純名:\bX\b
- 字串字面值:'X'、"X"
- 物件屬性:->X、['X']
- PHP 變數:\$X\b
- SQL backtick:`X`
- POST/GET:_POST['X']
- Session:_SESSION['X']

只 grep Q108 會漏掉 $_POST['Q108']$row->Q108`Q108`列出所有變形一次抓,才不會漏。

設計亮點 3:分類搜尋 + 查 DB

### 3. 分類搜尋(每類至少跑一次)
| 類別 | Glob 範圍 |
| 編輯版 | module_a/module/**/form*.php |
| 列印版 | module_a/print/**/*.php |
| 匯出 | module_a/export/**/*.php |
| AJAX/Class | module_a/ajax/**、module_a/class/** |
| 申報三層 | module_a/module/mod_service_a/**、module_b/form11_* |
| 客製檔 | *_N0*.php、*_ORG-T1*.php、*_G0*.php |
| SQL migration | sql/**/*.sql |

### 4. 查 DB(看欄位類型)
- 表單欄位(Q\d+)→ 查 validation_setting 找驗證規則
- table column → 查 information_schema 找哪些表有此欄位

不只掃程式碼,連 DB 的驗證規則validation_setting 表)和 schema(哪些表有這欄位)都查。因為改一個表單欄位,往往連帶要改它的驗證規則——這個關聯只有查 DB 才看得到。

輸出:路徑 + 行號 + 上下文

🔍 欄位 Q108 影響範圍

## 編輯版(3 處)
- module_a/module/case/form1.php:142
    $row['Q108']
- module_a/module/module_b/hcevaluation05.php:88
    name="Q108"

## 列印版(1 處)
- module_a/print/case/form1.php:201

## DB validation_setting(demo-org-1)
| field | function        | value | msg            |
| Q108  | check_Q5_option | 2     | 聽力部位為必填 |

## 建議
- 編輯 form1.php 時注意同步 print/case/form1.php
- 此欄位有 validation 規則,改名/移除前需先改 DB validation_setting

path:line 格式可點擊跳轉,每處附上下文,最後給「改的時候要注意什麼」的建議。


Subagent 二:consistency-checker(多檔一致性)

它回答什麼

「我改完編輯版 form1.php 了,列印版/匯出版有沒有跟上?」

這跟 /commit 的一致性檢查是同個概念,但 consistency-checker獨立可呼叫的 subagent——可以在改完當下立刻查,不用等到 commit。frontmatter 明確說它「被 /commit 流程呼叫做 pre-commit 同步檢查」,所以兩者是搭配的:subagent 是引擎,/commit 是其中一個呼叫點。

設計亮點 1:必須讀檔,不能看檔名猜

### 3. 必須 Read 每個候選檔

form4_5 ≠ form4_a、form24_1 不一定對應 form24_2。
同名前綴不算對應,必須讀檔內容確認處理的是同一資料/邏輯。讀完標明:
- ✅ 確認對應(同一 form、同一表)
- ⚠️ 名稱相似但無關

跟 field-finder 一樣的原則——檔名像不代表相關。subagent 被要求真的讀檔內容判斷,不是看名字配對。

設計亮點 2:追到 SQL 哪張表哪個欄位

### 5. 比對差異
| 比對項 | 警示條件 |
| 主表 | 不同 → ⚠️ |
| 編輯版新增 input 欄位 | 列印版 SELECT 未含 → ⚠️ |
| draw_option("X","A;B;C") 字串 | 列印版 option_result 不同 → ⚠️ |
| ID 型欄位 | 兩邊查的不是同一張表同一欄位 → ⚠️(這條最重要) |

最重要的一條:ID 型欄位不能只比畫面,要追到 SQL 哪張表哪個欄位。因為 Legacy 多租戶系統的經典陷阱是「同一個欄位,不同機構/不同版本存在不同表」——只比畫面看不出來,要追到 SQL 才知道編輯版和列印版讀的是不是同一個來源。

設計亮點 3:客製版的 backport 風險

| 客製版距主版 commit 數 | git log {主版} {客製版} --oneline | wc -l ≥ 5 → 提醒 backport 風險 |

Legacy 系統常有「主版」+「某機構客製版」(form1.php vs form1_ORG-N1.php)。當主版改了很多次、客製版沒跟上,兩者就會漂移。subagent 用 git log 算兩者差幾個 commit,超過 5 個就警告「客製版可能落後主版太多」

輸出:固定格式 + 不硬塞

📋 一致性比對:module_a/module/case/form1.php

對應檔(讀檔確認):
✅ 主版列印:module_a/print/case/form1.php
⚠️ 客製列印:module_a/print/case/form1_ORG-N1.php(距主版 8 commit)
⚠️ 對應匯出:未找到 — 確認是否需要

差異清單:
- ⚠️ form1.php:142 新增 Q108 input
  ↳ print/case/form1.php SELECT 未含 Q108
  ↳ 建議:列印版 SQL 加上 Q108(不要自動改,列出來給人決定)

關鍵原則寫在規則裡:

- 「未找到對應 X」是合法答案 — 不要硬塞「無」假裝沒問題。
  明確說「未找到,請確認本次邏輯是否影響 X」。

找不到對應檔不等於沒問題——可能是該有匯出但漏做了。subagent 被要求誠實說「找不到,你確認一下」,而不是填個「無」讓人以為安全。


兩個 subagent 的共同設計哲學

原則field-finderconsistency-checker
只查不改不改檔、不產 patch不改檔、不自動 commit
同名 ≠ 對應必讀檔內容判斷
追到 SQL查 validation_setting / schemaID 欄位追到表/欄位
誠實零結果零結果標「(無)」「未找到」不硬塞「無」
可點擊輸出path:linepath:line
不塞 AI 署名規則明確禁止規則明確禁止

只查不改」是這兩個 agent 的靈魂。它們是偵察兵,不是工兵——負責把戰場看清楚、回報,由人(或主 session)決定怎麼動。


為什麼「查詢型 subagent」是 Legacy 利器

通用 subagent 模板大多是「做事型」(debugger 修 bug、refactor 重構)。但 Legacy 維護最花時間的是「搞清楚現況」:

  • 改這個會影響什麼?(field-finder)
  • 改完有沒有漏同步?(consistency-checker)

這兩件事的特徵:要讀大量檔案、但產出只是一份報告。完美符合 subagent「隔離 context、回報結論」的特性。

把它們獨立出來後:

  1. 主 session 的 context 不被 grep 雜訊吃掉
  2. 查詢邏輯(哪些 Glob 範圍、哪些變形、查哪個 DB 表)沉澱在 agent 裡,每次查都一致
  3. 可被 /commit 之類的流程複用

給其他人的借鑑

如果你維護 Legacy 多檔系統,這兩個 subagent 的 pattern 可以抄:

  1. 找出你的「影響範圍查詢」:改一個欄位/函式要查哪些地方?寫成 field-finder 的分類 Glob 表
  2. 找出你的「對應檔關係」:你的編輯/顯示/匯出對應關係是什麼?寫成 consistency-checker 的同族檔 Glob
  3. 強制讀檔確認:同名 ≠ 對應,要求讀內容判斷
  4. 只查不改:查詢型 agent 絕不動檔案,只報告
  5. 誠實零結果:找不到就說找不到,不要填「無」假裝安全

結語

Subagent 不是只能拿來「平行做事」。對 Legacy 維護來說,「隔離 context 的查詢」反而是更高頻、更實用的用法。

field-finder 和 consistency-checker 都只做一件事——把現況看清楚、回報,不碰程式碼。它們是維護舊系統時最需要的能力:在動手之前,先知道「動了會影響什麼」「動完有沒有漏」。

這兩個 agent 加上 /commit 一致性檢查vibe-research 調查 skill,組成我維護 Legacy 系統的「偵察層」——先看清楚,再動手。