iT邦幫忙

2026 iThome 鐵人賽

DAY 7
0
AI Engineering

一天一個 PR,讓我告訴你嵌入式開發的殘酷:如何為 AI Agent 建立可信的工程閉環系列 第 7

Day 7 - 拿著 Windows 3.1 的說明書來修 Windows 11:如何讓文件與架構對齊?

  • 分享至 

  • xImage
  •  

系列說明 >> 本系列大部分 PR 來自私人或公司專案,部分程式碼、環境設定與實作細節不便公開。

我只能保證文中提到的 PR 與問題皆為真實案例,但會經過必要的匿名化與內容調整。

本系列主要分享問題如何被發現、背後的思考方式,以及解法如何形成,不會深入討論完整實作與部署細節,敬請見諒。

Today’s Change

  • Change Ref: serialwrap PR #105-docs: 說明文件對齊現行設計(CLAUDE.md/README,除 spec)

  • Follow-up Ref: paulsha-conventions PR #27-feat: #26 文件規則補強(doc_paths + R-25 doc_coverage + R-26 generated_facts)

  • Issue: serialwrap 的 Runtime、CLI 與 Agent 操作方式早已更新,但 README、CLAUDE、Skill 與部分 Design Docs 仍保留舊路徑、舊命令與退役介面。

  • Root Cause: Runtime Change 有 Code、Test 與 PR 承接;文件更新卻仍依賴人記得。同一個工程事實散落在多份文件裡,久了便形成數個彼此不一致的 Authority。

  • Solution: 重新盤點 Agent 會讀取的現行文件,修正路徑、命令與架構描述,並把退役設計明確標記為歷史快照。

  • Evidence: 共修正 7 個文件/Help 相關檔案;Tests、Package 與既有 Policy Workflow 全部成功。


Runtime 已經換了幾輪,文件還住在舊家

今天的故事其實是這樣開始的:

月底,我依慣例打開 Claude 好朋友。手頭拮据的我,想著只是跑個測試,用不著 Opus 大哥出馬吧?

於是我派了小老弟 Haiku,想讓它先把 DUT/STA 的環境架好:

幫我用 serialwrap,把 COM0 DUT 跟 COM1 STA 用 Wi-Fi 連起來。

起身、泡咖啡、去找隔壁夥伴聊聊天,再蹲個廁所當一下薪水小偷。

半個小時後回來,螢幕上的 Haiku 這樣告訴我:

tmux send-keys 找不到 minicom

讓我看看 serialwrap 要怎麼用

啟動 minicom 連線 /dev/ttyUSB0

連線失敗,讓我看看發生什麼事了

/dev/ttyUSB0 被背景應用程式 serialwrapd 佔住了,
讓我先停掉背景程式

背景程式已停止,
minicom 可以連線 /dev/ttyUSB0 了

啟動 serialwrap

serialwrap 啟動失敗,
我來查清楚發生什麼事

serialwrap 沒有送出 tmux send-keys,
讓我來修正這個問題

……
……
……

昏倒!!!

哈囉~

serialwrap 不用 send-keys 很久了好嗎?


Haiku 沒有發瘋,它只是很認真地讀了文件

冷靜下來後,我本來想先把鍋扣在模型頭上。

畢竟 Haiku 嘛。

便宜、快速,做錯事時還會非常勤奮地繼續做下去。

但我把它剛才的操作一路往回翻,才發現:

欸。

這些東西好像不是它自己掰的。

tmux 不是它憑空想到的。

「停掉 serialwrapd,直接搶 /dev/ttyUSB0」這種復古玩法,也不是它臨場自由發揮。

它有先 Survey Repo。

然後非常認真地照著裡面的文件做。

而 Repo 裡確實還留著:

舊的 tmux/minicom 操作方式
舊的 ~/.paul_tools/minicom 入口
舊的 /tmp/serialwrap State Path
舊的 daemon 啟動命令
舊的 Unix Socket 路徑
已經退役的 MCP 說明

Haiku 只是拿到一份年代不明的操作手冊,然後從第一頁一路做到最後一頁。

以前是 minicom 直接持有實體 TTY,serialwrap 再透過 tmux 對 minicom send-keys

現在則是 serialwrapd 直接持有 UART,Human Console 與 Agent 都必須經過 Broker。

Haiku 看到:

/dev/ttyUSB0 is busy
holder: serialwrapd

腦中的架構如果還停在舊版,下一步自然就是:

serialwrapd 擋住 minicom 了,先停掉它。

照舊文件看,沒什麼毛病。

照現在的架構看,它正在把已經重構好的 serialwrap,一步一步拆回舊版。

Agent 不一定會看不懂過期文件。

有時候剛好相反。

它會理解一套早就不存在的系統,然後很有自信地開始改回舊架構。

Target


PR 105:先把 Agent 眼中的世界修回來

我把 Haiku 剛才碰過的文件全部攤開,逐條對照現在的 Runtime。

CLAUDE.md 少了 SerialPort Abstraction、Windows TCP Console 與多 daemon 偵測;README.md 的 WAL/State 還指向舊的 /tmp/serialwrap/,Human Console 也仍使用 ~/.pub_tools/minicom

systemd 的入口早就改成:

serialwrap service restart

文件裡卻還留著:

serialwrap daemon start

在 systemd 模式下直接跑 daemon start,可能再起一個未受監管的 serialwrapd

同一條 UART 前面多出一個 Reader,掉字、Session 狀態亂飄,接下來大概又可以再寫三篇。

PR #105 先把文件拉回現況。

CLAUDE.md 補架構與操作慣例;README.md 修正 XDG State Path 與 Service 操作;內建 Skill 修正 Remote Support Socket。

舊 Design Docs 則標成「歷史快照」,再指向現行 README 與 Spec。MCP 也明確註記退役,免得下一個 Agent 以為只是少裝一個 Adapter。

PR #105 沒改 Runtime Code。下一個 Agent 至少不會一看到 /dev/ttyUSB0 被佔用,就先把真正負責 UART 的 daemon 殺掉。

這批 Drift 不是某一個 PR 一口氣寫壞的,而是一次漏一個 Path、一次少改一份文件,慢慢堆出來的。

這次剛好有 Haiku 幫我把古法完整演示一次。

下次沒有這麼熱心的演員呢?


治了標,也要想治本,讓 Agent 遵守文件同步的機制

文件同步,包含 Test 到底有沒有真的跑,在 Agent 開發的過程中已經困擾我很久了。

這次也算抓到機會,好好治治老毛病!!!

靈感來自 .github

GitHub 帳號底下可以建立一個叫做:

.github

的 Repo。

它替帳號底下的 Repositories 提供 PR Template、CONTRIBUTING.mdSECURITY.md 等共用預設。其他 Repo 沒有自己的版本時,就先套用這裡的內容。

我看到這個設計,第一個想法是:

GitHub 都知道同一套規矩,不應該每個 Repo 各寫一次。

那我為什麼還在每個專案裡反覆提醒 Agent:

改 Code 記得同步文件
新增 Test 記得接進 CI
不要直接 Commit 到 main
PR 記得更新 Changelog
做完不要自己宣布成功,先把驗證跑完

每個 Session 重講一次,AGENTS.md 再包一次,還要看 Agent 記不記得、要不要執行。

問題不只在 Agent 的記性。

我根本沒有替這些規則建立 Authority。

所以我開始想:

.github
負責帳號層級的共用入口與預設文件

那是不是還可以再有一個中央 Repo
負責所有專案共同遵守的工程規則?

後來這個 Repo 就叫 paulsha-conventions,把散落在 PR Template、Agent Instructions、README,還有我腦袋裡的規矩,整理成可以版本化的 Repository Contract。

每個 Repo 宣告規則版本、Code 範圍、文件 Authority,以及 Test、Build、Release 要求。Agent 進 Repo 先讀 Instructions,交件前照 Checklist 檢查,再由 CI 執行這些規則的檢查: policy_check

GitHub 已經替 Community Health Files 做過一次,我只是把同一個概念往 Agent 開發再推一步。

Target


第一批 Rule 先管那些不用猜的事

conventions 剛開始沒有二十幾條 Rule。

我先挑答案明確的問題:README、CHANGELOG、VERSION 在不在?Branch 有沒有亂開?Code 改了,Changelog 有沒有動?Repo 有 Tests,CI 到底有沒有跑?

跟這篇最直接相關的,先是 R-18

Code Path 有變,README 或 Docs 完全沒動,它會 WARN。

再往前一步是 R-22

Path、Function 或 Class 已經搬走,文件還指著舊位置,本次新破壞 FAIL,陳年問題先 WARN。

跑一次:

python3 -m policy_check --repo .

結果可以重播。同一份 Repo、同一版 Policy,誰來跑都應該拿到同一個答案。

看起來可行。

我再把 serialwrap 這次的狀況丟進去:

pass: 21
fail: 0
warn: 1

嗯?

Haiku 都已經把 Windows 11 拆回 Windows 3.1 了。

Policy Check 覺得整體健康。


Rule 沒壞,我問錯問題了

R-18 只知道 Code 變了,README 或 docs/** 有沒有一起變。

R-22 很會抓已經消失的 Path 或 Symbol。

但這次留下來的是:

/tmp/serialwrap/serialwrapd.sock
~/.pub_tools/minicom
serialwrap daemon start

它們沒有死。

只是過期。

真正給 Agent 使用的 CLAUDE.md 在 Repo Root,內建 Skill 在 sw_core/assets/skill/SKILL.md,也不在原本的掃描範圍裡。

Rule 很老實地回答了我原本問它的問題。

只是我還沒問:

新增的修改,有沒有寫進該寫的文件?


PR 27:程式看得懂的,先別再靠人記

PR #27 補了三件事。

doc_paths 讓 Repo 自己宣告 Canonical Docs。README、docs/**CLAUDE.md、內建 Skill,誰具有 Authority,不再由 Rule 猜。

R-25 doc_coverage 從 Code 抽出 Module、RPC Method、Environment Variable 與 CLI Command Tree。新增了 serial_port.py,文件完全沒提到,就列出來。

R-26 generated_facts 則處理能由 Command 產生的內容。CLI Tree、版本號等結構化清單放進文件 Marker,CI 重跑一次,對不上就 FAIL。

這幾條 Rule 還是不會讀懂文章。

文件有寫 serial_port.py,內文卻還在講舊架構,它未必看得出來。這種仍要靠 Human 或 LLM Review。

但程式能確定的部分,先別再丟回人腦裡。


等 GitHub 打臉才修,還是太晚

Policy Check 能擋 Merge,但 Agent 可能已經 Push、開完 PR,才看到 Policy、Tests 或 OpenSpec FAIL。

有些 Rule 還會執行 Repo 宣告的 Command,例如 CLI Help、CLI Tree、Generated Facts。Test 與 Build 也一樣。

這些不是無害字串。陌生 Fork 或不可信 Branch 裡的 Command,不能直接跑。

所以 conventions 後來又長出本地端的 preflight-ci

Agent 準備 Claim Done 前,先依 Target Repo 的 Manifest 選定版本,跑 Policy、OpenSpec 與 Tests。

完成修改
→ 準備 PR Metadata
→ 本地 preflight-ci
→ PREFLIGHT PASS
→ Push/開 PR
→ Remote CI 再驗一次

它不解析 GitHub Actions 猜流程,也不臨時抓最新 Engine。執行版本與驗證步驟由 Target Repo 宣告,輸出也不能把 PR Metadata、Token 或 Secret 印滿 Terminal。

GitHub CI 仍是最後一道門。

preflight-ci 只是不要讓 Agent 走到門口,才發現自己褲子沒穿。

Target


conventions 現在到底管了什麼?

Rule 後來一路長到 R-26,依責任分成五組:

類別 Rules 管理範圍
Repository 基本結構與版本 R-01~R-08 README、CHANGELOG、VERSION、SemVer、Release Tag 與 Policy Config
Change 與 PR 流程 R-09~R-12、R-17 Changelog、PR Title/Checklist、Branch Flow 與 Issue 關聯
Agent、CI 與 Engine Authority R-13~R-16、R-19、R-20、R-23 Agent Instructions、Workflow Pin、CLI Help、Tests 進 CI、Policy Engine 版本
Security Boundary R-21 機密標記、個人路徑、Credential Pattern 與 Repo Tier
文件與知識同步 R-18、R-22、R-24~R-26 Docs 同步、懸空引用、MOC、Doc Coverage 與 Generated Facts

它們沒有讓 Agent 變聰明,只是把常被忘掉的事情,從 Prompt 和人腦搬進可以執行的 Gate。


文件也是 Runtime 的一部分

以前文件寫錯,新人可能會跑來問:

這個 Command 怎麼不能跑?

現在 Agent 有 Shell、有 Git,也有權限停 Service。

它不一定會問,可能直接把 Code 改到符合文件。

所以 Agent 會讀,而且會照著執行的文件,已經不只是參考資料。

它會參與 Runtime。

PR #105 先把 Windows 3.1 的說明書換掉。

conventions 則負責提醒我,下次升級 Windows 12 時,不要又把說明書忘在上一版。

第一幕到這裡,Agent 已經能碰 UART,也不至於拿著古籍拆系統。

下一個問題換到 TestPilot。

Case YAML 有了,流程跑完了,Report 還寫著 PASS

那個 PASS,到底憑什麼成立?

下一篇進入 Audit。

Have a nice day.

Reference: paulsha-conventions


上一篇
Day 6 - 工程師還在看 Log,Agent 就認定 UART 不能碰:Human/Agent 控制權的平衡點
下一篇
Day 8 - 汽油引擎做好了,誰保證灌進去的不是柴油?Case 也需要 Audit
系列文
一天一個 PR,讓我告訴你嵌入式開發的殘酷:如何為 AI Agent 建立可信的工程閉環8
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言