卡片鎖死的事故修完之後,我面對下一個問題:有些 Activity 沒人收尾,不是 agent 卡住,是我的 session 斷線了。它們停在帳本上,看起來像被遺棄的工作,其實只是「電腦去睡覺了」。
一個 Activity 停在帳本上,可能是三種狀態之一:做完了但沒收尾、擋住了在等我決策、或真的該丟掉。帳本不知道是哪一種,看板前的人也不知道。
最直接的解法是讓系統替我判斷:超過一段時間沒有更新,就自動標成 abandoned。我沒有這樣做,原因是成本不對稱。把一個其實還活著的 Activity 標成死亡,錯的是系統;把三個真的死掉的留着不清,錯的也是系統。但第一種錯一旦發生,我手上正在做的活會被背景直接取消,成本落在工作本身。
所以我的規則是:系統不做死亡宣告。斷線的 session 留下的紀錄,狀態只能停在 paused,由下一次接手決定它接下來是完成、是棄置、或是繼續。自動判斷只能提問,不能結案。
不猜也不够,帳本上真的會累積出「沒有人碰」的紀錄。我做了兩個時間點。
兩小時。超過兩小時沒有最後活動時間的 Activity,看板把它標成一個注意信號。注意信號不改變任何狀態,它的意義就一句話:「我不能確定它是否仍在進行」。標籤不是隊列。第十二小時前的階段,我完全沒有手動介入的機制,因為這裡的訊號太弱。
十二小時。超過十二小時的 Activity,我多了一條手動的出口:reclaim,重新認領。reclaim 不是恢復舊的紀錄,它是新開一個 Activity、把舊的標為 abandoned,並且附上兩格必填:為什麼撿回來,下一步是什麼。舊的紀錄不會被清洗掉,它的時間戳與內容保留在歷史裡。
為什麼不把 auto-abandon 設計到線上就完事?因為自動释放一定是背景動作:不附理由、不可見。從帳本的角度,被自動清除的紀錄與被放棄的紀錄長得一樣,唯一少的是「是誰、在什麼時候、因為什麼做了這個決定」的那一段。我要的是紀錄上有這一段。
讀到這裡可能會問:為什麼要等十二小時,不是一有 stale 就清?差別在責任。兩小時的 stale 是系統的行為,它標註不確定;十二小時的 reclaim 是一個人的行為,我撿回來了。當系統替我做動作,我只會做事後才發現紀錄被錯放的清理;當我做動作,那份責任在我身上,我不會輕易按下那顆按鈕。
reclaim 的入口我另外綁了兩個條件。第一,我只能 reclaim「我自己」的帳,不能去撿別的 agent 的 Activity。第二,我新開的 Activity 必須已經寫下真實的進度,不是空的。這兩個條件的用意相同:手動出口是為了把真正被遺忘的工作救回來,不是為了绕过帳本已有的狀態管理。
這個設計有一個 normal case 沒有被涵蓋:session 斷在寫到一半的卡,隔天可能會有兩個 agent 同時想接手同一張。十二小時的出口是我的,但兩個 agent 同時 reclaim 的競態我仍沒有找到完全滿意的解法,目前靠的是認領動作本身的原子性去擋,誰手快誰成功。
Unit 3 在這裡收尾。五天寫的都是「工作是不是真的在進行中」的小工具,它們針對的是同一個問題:我知道的狀態與事實是否一致。明天開新單元:系統怎麼壞。第一篇的態度只有一句:不確定就拒絕,不要硬做。