
在軟體工程的長征中,第 14 天通常是最令人興奮也最令人恐懼的。我們花了整整五天——從 Day 9 的原則制定、Day 10 的痛點剖析,一路走到 Day 13 的例外規則定義。今天,是「零件」入庫、正式進入「流程編排區 v0.1」組裝線的日子。
然而,組裝日有一條永恆的定律:「零件各自全綠,接縫處照樣出事。」 即便單體測試跑得再順暢,當我們試圖將這些分散的邏輯縫合在一起,讓案件真正從「進件」走到「結案」時,隱藏在架構縫隙裡的魔鬼就會現身。今天,我不僅帶回了全綠的測試燈號,更帶回了兩個能讓後端架構師驚出冷汗的現場筆記。

這是今天最震撼的失敗。我們建立這套系統的核心價值在於「留痕」與「合規」,但就在第一版組裝完成時,系統竟然在完全沒有報錯的情況下,無聲地湮滅了關鍵的稽核紀錄。
這場災難源於架構設計中的「兩不管地帶 (Two-No-Man's Land)」:
> AssertionError: 票券編號重複,第二張會覆寫第一張 E assert 'X-C-2026-0001-01' != 'X-C-2026-0001-01'
架構師的後門檢討: Day 13 設計的 open_ticket 函式帶有一個 seq 參數,預設值為 1,它理所當然地假設呼叫端會負責處理序號遞增;而 Day 14 的 run_ai_station 在呼叫時,又天真地以為票券生成器內部會自動處理唯一編號。
這兩個「合理」的假設在接縫處碰撞,導致同一個案件若觸發第二次例外(例如 AI 第一次分類失敗,人工重啟後又遇到服務中斷),產生的票券編號會與第一次完全相同。在持久化存檔時,第二次的紀錄會直接覆寫第一次。這對於稽核來說是致命的——系統「弄丟」了曾經發生過的錯誤紀錄。
修正方案: 我們不再依賴呼叫端的假設。在 run_ai_station 開票前,系統必須強制先盤點該案件既有的票券數量,確保 seq 依實際張數嚴格遞增。

在執行快樂路徑(Happy Path)測試時,我原本斷言整趟旅程應該留下 5 筆狀態轉換留痕,但測試結果卻鐵青地顯示:4 筆。
這是一個關於「架構師自尊」的有趣錯誤。經過排查,程式碼沒錯,錯的是我的測試期望值。我下意識地將「進件建案」這個動作算作一次狀態轉換。但回歸 Day 12 的狀態機設計,案件從「不存在」到「已收件 (Received)」屬於初始化 (Initialization),而非狀態轉換 (Transition)。
測試確實不會說謊,它只是精確地戳破了開發者在設計測試時,對自身架構邏輯的認知落差。我們最終修正了測試期望值,並在註解中深刻地補上一句:「進件不是轉換」。

為了防止「接縫失守」演變成整座架構的崩塌,flow_service 在實作上展現了近乎偏執的強制力。
我們在 flow_service 中定義了 start_processing、send_to_review、review 等核心函式,但這些函式的內部並非直接修改資料庫狀態,而是強制呼叫 Day 12 的 transition 狀態機。我們拒絕任何「把案件標成已結案」的捷徑,如果開發者試圖跳關,系統會毫不留情地拋出 TransitionError 並在畫面上噴出紅字。
此外,我們嚴格區分了操作者身分:
這種身分鎖定機制,確保了每一筆留痕的「權責歸屬」在架構層面就無法被篡改。

今天的另一個亮點是落實了 E4 精神:「Python 邏輯部分不依賴模型服務」。
在 AI 站(AI Station)的處理中,我們引入了「執行器 (Runner) 參數」的設計。這意味著 flow_service 根本不關心背後是哪個 Claude 模型。在測試與展示時,我們可以注入不同的虛擬執行器來模擬三種場景:
這種設計讓我們即便在沒有 API Key 的離線環境,依然能完整跑完所有例外路徑的壓力測試。

我們利用 Streamlit 將這些複雜的後端狀態具象化。它不再只是顯示一個案件清單,而是一個「透明化工具」,包含四大核心:
在修正了票號遞增邏輯與序列化問題(解決了 Day 5 遺留的 Datetime/Enum 序列化教訓)後,我們終於迎來了全綠燈。
| 驗收項 | 結果 | 關鍵說明 |
|---|---|---|
| 快樂路徑端到端 | ✅ 通過 | 進件至結案,確實記錄 4 筆狀態留痕 |
| 敏感攔截流程 | ✅ 通過 | 觸發例外正確開票,案件停留在 Processing 等待人工 |
| 服務中斷接管 | ✅ 通過 | 模擬服務崩潰後,由 HUMAN 成功接管並留痕 |
| 票號唯一性 | ✅ 通過 | 多次開票序號正確遞增,不再有無聲湮滅現象 |
| 持久化往返 | ✅ 通過 | 解決 Enum 與 Datetime 的序列化 Roundtrip 難題 |
| 狀態機跳關防禦 | ✅ 通過 | 任何試圖繞過流程的操作皆觸發 TransitionError |
今日,零件組完了,畫面也能動了。115 個 Passed 標誌著流程編排區 v0.1 的誕生。
但作為架構師,我們必須誠實面對當前的限制:目前的系統是一個單人、單執行緒的 PoC。我們沒有真正的使用者權限控管(名字是自填的),也沒有處理多人在線的併發衝突。
這引發了一個值得深思的問題:一個「能跑通的程式碼」與一個「強韌的系統」之間,究竟還有多遠的距離?
明日,我們將迎來最終的端到端驗收。當我們導入真實的模型呼叫,面對不可控的輸入與輸出的洪流時,這套精心設計的架構是會展現其應有的強韌,還是會像紙糊的房子一樣倒塌?