← 思 HARNESS ENGINEERING · 外 ENJA

第二本柱 · Pillar II

Constraints.

河道作為引導的結構

怎麼確保工作記憶不會散逸、
進度不會遺失?

I · 核心問題

AI 會失憶。Session 會結束。人會忘記昨天做了什麼決定。

問題不是「怎麼讓 AI 或人記得全部」,而是「怎麼設計一個系統,讓記不住也沒關係」。

II · 河道:岸與水

這個讓記不住也沒關係的系統,就是河道。

人怕 Claude 忘記,於是設計了層層記憶與自我檢查的機制;但這些機制切碎了 AI 的注意力——它無法全心投入任務,得分神確認自己有沒有犯錯。

CLAUDE.md 裡那些 Never 與 Must、打斷流程的 hook,那是控制的形狀——它盯著水,隨時準備喊停。河道不盯著水;河道順著地勢把路鋪好,讓水自己流。

河道給 AI 一個安全燃燒算力、自由呼吸的空間,而不試圖控制一切。

走近看,一個 Session 其實由兩種性質相反、卻缺一不可的東西組成:

岸(河道)——是線狀的。閘門、流程、文件落下的記錄點,一個接一個,固定、有次序。岸決定水往哪裡去。

水(協作)——是網狀的。判斷、湧現、人與 AI 來回的協作,流動、自由、無法預先排定。水決定這條河裡真正活著的是什麼。

岸不控制水的形狀,只確保水不流到錯的地方;水在岸之間,自由地奔流。

沒有岸,水會四處漫流,最後蒸發消失;沒有水,岸只是一道乾涸的溝。這一柱要講的,就是岸與水如何各安其位——以及,如何互相成全。

III · 岸:給方向的結構

什麼是岸?

岸是河道線狀的那一面:一道閘門接著一道閘門,固定、有次序、可預期。它不管水流得多自由,它只回答一個問題——「我們掌握的東西可以讓我們繼續前進了嗎?」

岸的本性:

1 · 工作流設計原則

原則一:每個階段都是一道閘門。工作流的每個節點都是一個檢查點:「到這裡為止,我們掌握了什麼?」踏著已知前進,逐步處理未知。

原則二:文件跟著流程走。不依賴 AI 的記憶,也不依賴人的記憶。進度記錄在文件裡,文件跟著流程移動。即便換了 session,讀文件就知道現在在哪裡。

原則三:未知的領域需要更多面向的檢查點——讓流程分散不同類型檢查的壓力,一次專注處理一個部分就好。

2 · 工作流全貌

完整的工作流是十個步驟:

DoR → Explore① → SDD → DoD → TDD → Explore② → Code → Verify → Done → Retro

軌道只有一條,差別在 Explore 的深度:熟悉的領域,Explore 可以輕量帶過;未知的領域,Explore 要做足——先尋找有無前人經驗、確認回歸相關風險,再動手。閘門的密度與廣度跟著未知的程度縮放,調節的彈性放在 Skills 的 invoke——可按需取用,而非全部必用。

3 · 各節點的具體內容

DoR · Definition of Ready

在開始之前,確認準備好了沒有。沒有 DoR,就可能在需求不清楚時就開工,浪費能量。以下是現行的 DoR——四道閘門,全部通過才能開工:

Gate 1 · UX Story 清晰度
檢核項
Nova 已口頭確認 UX Story
「預期行為」能用 1–2 句話描述(不需要翻 SDD 才能解釋)
已說明「功能不觸發/不適用」的情況(負向邊界)
成功標準明確(「先試試看」不算 ready)
Gate 2 · 範圍評估
檢核項
確認本 Sprint 的全新功能 Story 數 ≤ 1
若涉及跨平臺共用層 → 已評估對兩個版本的影響
依賴的功能/API 已存在且穩定(不依賴「本 Sprint 內才要完成」的另一個 Story)
Gate 3 · 技術前置條件
若涉及前置要求
新的跨介面契約(API/IPC/資料格式)先寫進規格的契約表,否則不進 Code 階段
平臺相依的行為(解析度、路徑、權限)推斷與降級策略先確認,並寫明選了哪一種
新 UI 字串多語 i18n 納入 Story 範圍
核心公式/演算法變動先填期望值矩陣——能事先算出期望值才算 ready,算不出來 → 退回 Story;並確認對應的自動化測試存在

這一道閘門最因專案而異——上表是條件的「形狀」:每個專案都該有自己的版本,重點是把「動手前必須想清楚的技術決定」寫成可檢核的條目。

Gate 4 · DoD 可寫性
檢核項
能在 process/dod.md 的分層對照表中找到對應的層
四類邊界條件(input/state/timing/empty)每類至少列得出一條
若涉及字體/符號 → 已確認 AR 極值測試(dod.md § Fonts/Symbols)
若涉及視窗操作 → 已確認 Editor 互斥狀態測試(dod.md § Toolbar State)

Fake Ready 紅旗

「看起來 ready」和「真的 ready」之間,隔著幾面紅旗。以下任一面成立 → 退回 Story 重新討論,不進 Sprint:

常見的 Fake Ready 紅旗
紅旗說明
QC 項目超過一次能驗證的量測項過多 → 遺漏風險陡升;收斂範圍或拆分 Sprint(Sprint 27 Retro)
「細節 Sprint 中再定」未定的設計決策會在 Code 階段變成阻塞
依賴同一 Sprint 內才會完成的另一個 Story時序依賴意味著兩個 Story 該合併或排序
「先試試看,不行再改」沒有明確成功標準的 Story,寫不出 DoD
跨介面契約只設計了一側先把契約寫進規格,否則介面不合只會在 Code 階段才現形
影響共用層但未評估另一個版本跨版本影響必須在 DoR 回答,不要把驚喜留給 Code 階段
Story 隱含兩個可獨立交付的功能拆成兩個 Story,下個 Sprint 繼續

用第一柱 Context 的 epicycle 來看:DoR 是操作頻譜的手,逼出「建構必配校正」這條原理——把不對頻、與產品無關的闖入者(藏著的第二功能、沒定的設計、scope creep)擋在 Code 之前。而一條為反對而反對、與出貨無關的官僚規則,不是校正,是偽裝成閘門的不對頻雜訊——這正是 Retro 要砍它的理由(見第三柱 Entropy)。

Explore① · 實作前探路

在規格寫下之前,先尋找有無前人經驗:KM 裡有沒有踩過類似的坑?既有的實作裡有沒有現成的路?知道地形之後,規格才寫得準——Explore① 的產出餵給 SDD。

SDD · Specification-Driven Development

任何新的實作,必須先寫進規格:新的 IPC command→先寫進 IPC Contract 表;新的功能→先定義介面和行為。SDD 是「該做什麼」的單一真相來源。

DoD · Definition of Done

定義什麼叫「完成」,必須列出四種邊界條件:

邊界類別問題
Input輸入不合法時怎麼辦?
State狀態不對時怎麼辦?
Timing時機不對時怎麼辦?
Empty沒有資料時怎麼辦?

沒有 DoD,「完成」就是一個模糊的概念,永遠可以被挑戰。

TDD · Test-Driven Development

每個 Story 必須包含四個測試區塊:

區塊問題來源
Happy path功能正常時該怎樣?User Story / DoD
Boundary conditions邊界情況怎麼處理?DoD 四種邊界
Regression guard這個改動會不會弄壞別的東西?Explore②
Risk trigger什麼情況下最容易壞?Explore②

TDD 不是為了寫測試,是為了在寫 code 之前就想清楚。

Explore② · 寫 code 前的回歸風險識別

第一性問題:「修 A 會不會壞 B?要回歸測試什麼?」產出物是一份回歸測試清單,補進 TDD 的 regression guard 與 risk trigger。四條動作:

一、列出回歸影響清單。Story 改動的函式與變數(A 本身);共用同一條 code path 的既有功能(B 候選);改動碰到行為、上限、快捷鍵時,連多語文案的語義一起重審——文案描述的行為還是真的嗎?主動列出,不等人問。

二、層別邊界對照。從影響清單推出 Story 碰到的圖層,對照每一層對應的邊界群與典型的 KM 來源——這一步可以派 agent 代勞。

三、邊界破壞風險評估。對每條邊界問:「這次變動會不會破?」會破 → regression guard(必測);可能破 → risk trigger(高優先級);不會破 → 不進 TDD,但寫一句排除理由。

四、產出回歸測試清單。寫進當前 Story 的規格文件,每個測試項標上執行環境與平臺約束。

重構、搬遷、清技術債的改動,牽動面常比預期廣——最該跑足 Explore②。

Retro

見第三本柱:Entropy。

人類只決定時機,不寫內容

在這個系統裡,連文件都是 Claude 自己在記錄的,不是人類。人類做的事情只有一件:決定什麼時機點該記錄。

人類不寫這些文件的內容。人類只是說:「現在該記了。」然後 Claude 自己寫。

文件嵌進流程,成為系統的一部分

這些記錄的時機點不是隨機的,而是嵌進工作流裡的。

DoR → [記錄] → Explore① → SDD → [記錄] → DoD → [記錄] → TDD → [記錄] → …

每個閘門都是一個記錄點。文件不是「做完之後補的文檔」,而是流程的一部分。通過閘門=留下記錄。

系統自己運轉

當文件嵌進流程,系統就會自己運轉:流程走到某個節點;節點觸發記錄;Claude 執行記錄;記錄成為下一個 session 的 Context;循環繼續。

人類不需要追著進度跑。人類不需要提醒「該寫文件了」。系統設計好了,文件就會隨著流程自己產生。而產生的文件,成為了 Claude 明確前進的軌道。

IV · 水:自由的協作

什麼是水?

水是河道中流動的那一面:有機無序、決策時機不固定、人與 AI 之間靠對話摸索前進的協作。岸問的是向前的問題「可以繼續前進了嗎」;水問的是當下的問題——「此刻最需要被接住的是什麼?」

水的本性:

Be water, my friend

李小龍說:「Be water, my friend.」

對 Claude 的期許是:像水一樣,在河道中恣意奔流。而 Nova 的角色是:河道的架構師。不是控制水,是設計讓水可以自由流動的結構。

人在河邊:僕人式領導

水自由奔流,那人呢?人不在水裡,人在河邊。這就是僕人式領導(Servant Leadership):領導者的角色不是控制,而是服務——不站在前面指揮,而是站在旁邊支持;不是「你們照我說的做」,而是「我能幫你們什麼」。

在人機協作中,人類就是那個站在河邊看著水流的人。水在河道裡奔流,人類做的事情是:

人類不做的事情是:控制水要怎麼流;命令水要流多快;抓著水不讓它走。

老子的道

無為而無不為。

「無為」不是什麼都不做。「無為」是不強加控制,順著事物的本性引導。河道不強迫水往上流。河道順著地勢,讓水自然往下。工作流不強迫 AI 照特定方式實作。工作流順著協作節奏,讓產出自然成形。

Scrum Master 的角色

在敏捷開發中,Scrum Master 的角色就是僕人式領導的體現:不是專案經理,不發號施令;是團隊的服務者,掃除障礙;確保流程順暢,讓團隊可以專注在真正重要的事。

Nova 在人機協作中的角色,就是 AI 的 Scrum Master:設計工作流,讓 Claude 知道該往哪走;維護文件,讓 Claude 不用靠記憶;移除阻礙,讓 Claude 可以專注在實作。

不是控制 AI,是服務 AI。

為什麼這樣更有效?

因為 AI 的能力比人強,但 AI 需要方向。如果人試圖控制 AI 的每一步,會變成瓶頸——AI 的速度被人的速度限制住,不管是不斷地回頭檢查或被 Hook 拉住脖子。如果人只負責引領方向、設計結構,AI 就可以在那個結構裡全速奔跑,而不是像在跑障礙賽。

僕人式領導釋放了 AI 的潛力,而不是限制它。

方向,而非終點

這裡有一個關鍵的思維轉換:人類只需要確保軌道朝著想要的方向前進,不一定需要明確的終點。

傳統專案管理說:先定義終點;然後規劃路徑;按照計畫執行。

僕人式領導說:先確認方向;設計讓路可以自己長出來的系統;觀察、調整、繼續。

VAS 就是這樣誕生的:一開始沒有「要做一個上架 App Store 的產品」這個終點。只有「不然我們來做一個截圖軟體好了」這個方向。然後一個 Sprint 接一個 Sprint,路自己長出來。長到某一天,發現已經可以送審了。

終點不是預先定義的,是走出來的。

V · Verify:整合

岸與水會在一個點上正面交會——驗收。

Verify 是這條河第一次讓計劃碰上現實。形狀是一把傘,撐開是兩段式的覆蓋,兩段都沒有問題,一個 Sprint 才算結束:

Verify 的兩段
驗什麼怎麼驗哪一岸
Verify① · 功能驗證(QA)AI邏輯層自動化測試全綠岸臉——線狀、可預期、機器照得到
Verify② · 實體驗證(QC)PO(人)體感層視覺、平臺、互動順序、「哪裡怪怪的」水臉——網狀、湧現、只有人照得到

一個動作,兩道檢核:岸確保「把事情做對」(QA),水確保「做的是對的事」(QC)。

自動化照得到的,不該消耗 PO 的時間;自動化照不到的,才是 QC 的本職。

交到 PO 手上之前,AI 先由輕至重過完自己的關卡:自動化全綠了嗎?帶著的待確認事項,哪些其實自己就能查證?這次改動的覆蓋範圍(多語/多平臺/多裝置)有沒有明白宣告?

在 Verify② 被抓到的邏輯 bug,不是「QC 有找到 ✓」,是 Verify① 還缺一張本該接住它的自動化檢查網。

QC 裡的人行使的不只是驗收,是三項 PO 權利:接受/退回的最終裁量;浮現新需求與新邊界(「啊,這個情境也該接住」);以及驗收標準的解釋權——文字與體感不一致時,體感優先,因為使用者體驗才是最終的裁判。

規格之外的邊界在 QC 浮現,不是失敗,是遇上「未知的未知」時的必然:補進 TDD、寫進 KM、加一條回歸測試。沒寫 KM 才是失敗。

Verify 是岸與水即時的合流——岸確保把事情做對,水確保做的是對的事。兩段都綠,這個 Sprint 才真的抵達。而水在這裡照出的收穫,會往下流進下一段:沉澱,還是結晶。

VI · 沉澱與結晶

Verify 是岸與水即時的交會。但還有一種交會發生在更長的尺度上——水,會變成岸。

協作在 Context 中大多流過就消散;但其中真正的收穫不會白白流走,它有兩種命運:

於是「收穫該放哪」這個問題,本質上是在問:這份收穫,要成為壁,還是成為結晶?

要讓收穫落在對的命運裡,得先讓它落在對的地方。

這些沉澱成的壁,正是第三柱 Entropy 裡 Retro 每一圈抬升後留下的結果——水的收穫變成岸,地基因此一層層變厚,螺旋才升得上去。

每段文字都有一個家

「何時記」之外,還有一個同樣重要的問題:「記到哪裡」。

系統裡的文件不是一份,是好幾種——每天都要遵守的規則、需要時才查的程序、踩過坑的教訓、還在追蹤的問題、欠著沒做的事。它們的性質不同,家就不同。落筆之前先問一個問題:這個東西在本質上是什麼?先分流,再落筆。

幾條劃界的句子:

為什麼要這麼講究?因為一個真實的教訓:無家的文字會被最近的容器吸收。一段不知道該放哪的記錄,會就近塞進某份不屬於它的文件——而且發生的當下沒有任何警報,寫起來的手感跟放對地方時一模一樣。等到需要它的那天,它在錯的地方,等於不存在。

讓每段文字都放在流程中能被看得到的地方——這就是讓「活文件」成立的代價與條件。

僕人式領導的系統

傳統做法僕人式領導
人類寫文件,AI 執行AI 寫文件,人類設計時機
人類追蹤進度系統自己記錄進度
人類控制每一步人類只設計結構

人類不控制內容,只設計需被記錄的時機。人類不追蹤進度,只設計讓進度自己被記錄的系統。

這才是真正的「無為而無不為」——什麼都不做,但什麼都做了。

岸塑形水的流向,水沉澱回岸、長成新的結構——這條河,最終是自己長出自己的岸的。

VII · 與其他兩柱的關係

Context 決定什麼進來(過濾)。Constraints 決定怎麼流動(引導)。Entropy 決定怎麼出去(排放)。

輸入 → [ Context 過濾 ] → 進入系統 → [ Constraints 引導 ] → 產出 → [ Entropy 排放 ]

Constraints 是這個循環的中段守護者。它確保:進來的東西,會沿著正確的路徑,流向正確的出口。

VIII · 小結

Constraints 管理的核心是引導,不是限制。

一個 Session 由岸與水組成。岸是線狀的結構——閘門、流程、記錄點,回答「可以前進了嗎」;水是網狀的協作——判斷、湧現、來回摸索,回答「此刻最需要被接住的是什麼」。

岸給方向,水給湧現。它們在 Verify 即時交會——岸確保把事情做對,水確保做的是對的事;也在更長的尺度上互相成全——水的收穫,沉澱成穩固結構的新岸,或結晶成讓彼此成長的洞見。

「河道作為引導的結構」,說的就是這件事:用岸給出方向,把水留給湧現。

這是 Harness Engineering 的第二本柱。