這個檔只追加,寫完的 block 永不修改。 發現舊 block 有誤 → 在新 block 的 「推翻了什麼」欄寫明更正,不要回頭改。
現況看
fr107-STATE.md;本檔是決策軌跡與教訓的來源。
從決策者對 FR-030 Drive 版分類線的盤點討論開始,寫討論稿、拿到 D1–D12 裁示、落成 design.md、開母子卡(29 張連號),並跟到 .1 前三張(T-1.1/T-1.2/T-1.3)驗收通過。
見 STATE 表 B。
jedi-evidence-classification, 不開新套件;主專案只留宿主 adapter 與前端。理由:批次的狀態機、歸檔演算法是引擎自己 的知識,開第二支套件等於兩處各長一半;被排除方案是新開 jedi-evidence-batch(違反插件 互不相依)與主專案自己做(重蹈 FR-069 之前「一半在主專案」的病)。STORAGE_CONFIG) 而非只放環境變數——落地版客戶不會自己改伺服器 .env,改了也要重啟,無法自助切換供應商。classification_profiles 不建 FK;profile CRUD 只給平台管理員;job_evidences 既存 重複列先查不合併;舊 route/FE 常數並存期可接受、.6 一起清。無(本棒為新案起點,尚無被推翻的判斷;.1 三張 runner 對卡面規格有三處更正,見下)。
教訓 1|開卡時寫的檔案落點會撞 .gitignore,三張卡同一個錯。 T-1.1/T-1.2 卡上都寫 migration 落 scripts/sql/packages/<套件>/,但那個目錄是 build 時 從套件攤出來的產生物、在 .gitignore 內,放進去 commit 不了。正本該放套件自己的 migrations/,且不自帶 INSERT schema_migrations(build 腳本統一登記)。開卡引用 既有卡當範本時,範本本身如果錯,會被原樣複製三次——T-1.1 runner 第一個查出來, T-1.2/T-1.3 開卡時首腦已知道要改但沒有回頭巡一次已開好的卡面文字,是 runner 自己在 「已完成修正」段裡各自更正一次。
教訓 2|grep SQL 關鍵字判「零寫入/零影響」是盲區,本案在派工 prompt 就先寫明。 上一個 arc(FR-104/FR-105)已踩過 ORM session.flush() 不會被 SQL 關鍵字 grep 抓到, 本案 T-1.1 卡面「怎麼做②」已預先要求同時 grep session.add/merge/flush,算是把 教訓直接內化進卡片而非等 runner 撞到。
教訓 3|「剩下的孤兒歸 ROOT」字面執行會傷到真實使用者。 卡上 D10 寫「查不到歸屬的孤兒歸 ROOT」,T-1.1 runner 若照字面只做參照鏈回填,會有 1804 筆被掃進 ROOT——這些檔案的真正擁有者從此看不到自己的檔(RLS 擋掉)且無錯誤訊息。 runner 多加一層「退回上傳者所屬公司」並與參照鏈結果交叉比對(711 筆一致、0 衝突)驗證 後才用,孤兒降到 21 筆。寫回填規則時,「找不到就歸預設值」這句話本身要包含「先窮舉所有 可能的間接判定依據」,不能只給一條鏈路就當作規則完整。
localhost:5432/guidant_ai_dev):套了 T-1.1(套件 jedi-file-upload 004-upload-files-tenant-owner-rls.sql)、T-1.2(套件 jedi-evidence-classification 003-evidence-batches.sql)兩支 migration。復查 T-1.1 回填的兩項待修正、對 .2 三張(T-2.1/T-2.2/T-2.3)做夜跑核驗,並處理決策者 對 T-1.4(CM-1853)前端 UI 的驗收——整頁不接受,開新卡 T-1.4m 先出 HTML mockup 過目再 重做。
見 STATE 表 B(本棒未新增 commit,僅驗收與開卡)。
guidant-design-system skill 明寫的「新頁面先出 HTML mockup 過目再實作」規定,直接刻 Vue,落成畫面後才被全盤打回。已定案:兩頁結構(歷史清單頁+四步流程頁)、第③步重用 既有審閱頁(換資料來源屬 T-3.4)、命名「自動分類證據」路由 auto-classify。開 T-1.4m(CM-1878)先出 mockup,過目後才重派 T-1.4。+08 時區、API 回的是 GMT,是同一個 時刻的兩種表示法。runner 原本的復查是對的,首腦第一次判斷錯誤,重新核對後撤回。guidant-design-system skill 的明文規定,是本棒 被推翻的實作方向,見上「關鍵決策」。教訓 1|新頁面必須先出 mockup 過目,開實作卡時要把「mockup 已過目」列為前置條件。 T-1.4 卡面沒有把「先出 mockup 給決策者看過」寫成前置步驟,只當作 skill 背景知識期待 runner 自己記得,結果整頁做完才被打回,浪費一次實作與一次驗收的成本。之後開任何新頁面 實作卡,前置條件要明寫「mockup 已過目通過」而不是假設 runner 會自己觸發那個 skill。
教訓 2|runner 驗收打折要當場講明,.2 的 AI 401 標得好。 .2 三張夜跑核驗時,其中一張的驗收條件因為外部 AI 服務 401(金鑰過期或額度問題)沒辦法 用真實呼叫驗證,runner 在回報裡把「這一項用模擬/替代方式驗證」寫得很清楚,讓首腦知道 這是打折的驗收而不是無條件通過,符合「驗收環境打折要當場講明」的規則,值得延續。
無(本棒只做驗收復查與 Notion/文件作業,未動 DB、未動程式碼)。
驗收 T-3.2、T-5.1、T-5.4 三張卡;T-5.4 抓到三處需修正、退回重做;就「AI 金鑰在落地版怎麼 發給客戶」跟決策者討論,拿到 D13 裁示並落成 design.md、開 T-5.5(CM-1879)。
見 STATE 表 B(本棒為驗收與文件/開卡作業,無新增程式碼 commit)。
原廠給客戶一組 AI 金鑰,放進 ROOT 租戶(tenant_id=1)的 AI_PROVIDER_CONFIG(加密存 DB,不寫 guidant.env);AI 小幫手/AI Dashboard/證據分類三功能統一改成「租戶自己的設定 → ROOT 原廠鑰 → 環境變數」三層解析;第一版不開放租戶自填(畫面鎖 ROOT 平台管理員); install.sh 裝機時把原廠鑰寫進 ROOT,--upgrade 不覆寫既有值。被排除:明文存 DB、加密鑰 與密文放同位置、「原廠代理」完全藏鑰(列為獨立 FR 候選,未裁)。風險天花板與 Drive OAuth token 同級——防意外與 DB 外洩,不防客戶自己的 root 有心人(解密鑰仍在同一台機器上)。
教訓 1|「給過 prompt」不等於「已派工」,回報前先查卡片狀態。 首腦手上有派工 prompt 草稿不代表工作已經發出去,只有 Notion 卡片狀態真的挪動了才算派出; 下一棒接手看到「進行中」字樣,要先去卡片核對而不是照單全收。
教訓 2|「誰能設定什麼」屬商業決策,不能用技術合理性推論,要在設計時直接問決策者。 T-5.4 金鑰頁該不該開放租戶自填,從純技術角度兩種做法都說得通,但答案其實是決策者的商業 判斷(第一版鎖定原廠統一供應、避免客戶到處填錯或洩漏)。遇到這類「權限開放範圍」的題目, 不要自己推理出一個「看起來合理」的答案就往下做,要先問。
無(本棒只做驗收復查、design.md/STATE/LOG 文件更新、開 Notion 卡,未動 DB、未動程式碼)。
T-5.2(catalog/報表)三輪修正後驗收、T-5.4(金鑰頁)驗收退回後重做三輪過關、T-5.5 (D13 三功能統一金鑰+install.sh)開卡直接做完;接手一個中斷的 session(T-3.3+T-5.3a 併做),拆成兩支獨立 commit 落地;新派三張卡(T-3.4/T-4.1/T-5.3b);本 block 收尾時 重新逐張核對 Notion 卡片真實狀態與四個 repo 實際 git log,據此重寫 STATE 表 A/表 B。
見 STATE §4/§5(表 A 逐卡 commit、表 B 統整)。
延續 D13;T-5.5 落地細節:AI_PROVIDER_CONFIG 三功能(AI 小幫手/AI Dashboard/證據 分類)共用同一支解析器,install.sh 在裝機階段寫入 ROOT 原廠鑰、--upgrade 路徑不覆寫 既有值(避免升級洗掉客戶已設定的租戶鑰或已輪替的原廠鑰)。
git log/git status,發現交接指令裡 當作「已實查」的下列事實其實是舊資訊,未反映最新進度: ①「T-3.4/T-4.1/T-5.3b 派出中」——正確,但需標明是同一天下午晚些才派、尚未有任何 runner 回報;②「T-1.4 待決策者手測」——已經是 Done,不需要再排驗收;③「T-5.2/T-5.4/ T-5.5 待派或退回中」——三張其實都已經 Done;④「T-1.1/T-1.2/T-1.3 標『✅ 驗收通過』」 ——Notion 實際狀態是「修正待驗證」,比「Done」低一階,尚未真正蓋章。「派工 prompt 裡 的『已實查』事實」本身也需要被下一棒當作「聲稱」而非「保證」來對待——這是 Block 3 教訓 1(「給過 prompt 不等於已派工」)的鏡像版本:這次踩到的是「首腦盤點過的事實,寫進 prompt 後也會在傳遞過程中變舊」。教訓 1|「已實查」的事實會在交接鏈路上變舊,接手方仍要自己重驗一次高頻變動欄位 (卡片狀態、commit hash 清單),不能把「盤點過」直接當「當下為真」。 本案的教訓 3(Block 3)講的是「給過 prompt 不等於已派工」,這次是同一顆藥丸的另一面: 「盤點過」也不等於「維持到你讀到這份文件的當下還是真的」——尤其是卡片狀態與 commit 清單 這種每小時都可能變的欄位。寫交接文件的規則要更新為:卡片狀態與 commit 清單這兩類欄位, 永遠在動筆前用即時查詢重新核對一次,不可以沿用上一份文件裡抄來的版本,即使那份文件 自稱「皆已實查」。
教訓 2|表 B commits 清單這種會員爆炸成長的內容,不該逐條抄進 STATE,改成「去對應 卡片查」的索引式寫法。 本案 commits 數量已經到 BE 33 筆/套件 14 筆/FE 9 筆,且還在持續增加,逐條列在 STATE 會讓這個「≤200 行」的檔案被 commits 清單吃掉大半篇幅,且每棒都要重新核對每一條 hash 是否 還對得上(容易出現複製貼上時的手誤)。改成「commit 清單以 Notion 卡片『已完成修正』段 為準,STATE 表 B 只給逐卡一行 hash」大幅降低維護成本與出錯面。
jedi-evidence-classification 004/005(T-5.1/T-5.2 對應 migration)與主線 scripts/sql/2026-09-17-fr107-ai-service-config-menu.sql(T-5.5, 新增 main-line 選單項)。ROOT 租戶(tenant_id=1)的 AI_PROVIDER_CONFIG 已寫入三家 供應商加密金鑰(Anthropic 可用,OpenAI/Google 額度或金鑰無效,見 STATE §6)。冷接後驗三張跑中卡(T-3.4/T-4.1/T-5.3b);開七張新卡(CM-1883 升級路徑補原廠鑰、CM-1884 批次詳情補欄、CM-1885 碼表換代+思考深度、CM-1886 e2e 拆出、CM-1887 小幫手/Dashboard 換代、CM-1888 手測第一批八項+五追加、CM-1889 基線重產);依序派出並驗收 T-4.2、CM-1884、T-4.3、T-6.1、T-6.2(發 1.2.0)、T-6.3(拆卡)、CM-1885、CM-1887、CM-1888、CM-1889 共十四張改 Done;決策者親手測整條線;三 repo push;決策者裁「先不發版」,出貨兩卡暫停。
見 STATE §4/§5。
gpt-5.6-terra、可選 gpt-5.6-luna(不放 sol/astra);小幫手 Haiku 4.5;Dashboard 三檔皆 Sonnet 5;新增「思考深度」三檔預設 medium。.env,鑰在 DB;首腦解密實查三把都在。evidences 欄位,手動上傳與 Drive 同步從以前就沒算過。resolve_api_key,不讀 env」省一輪。content[0].text 會炸、max_tokens 要放大、budget_tokens 回 400;每次換代把「回應形狀變了沒」當必查項。gemini-3.5-flash 型號 id 存在(runner 查官方文件,DEV Google 鑰無效未實打)。docker run 分類容器——compose 沒掛 docker.sock,高度懷疑不能,T-6.4 要補。evidence-classifier:dev 重 build 含 --effort。guidant_ai(決策者放行):CM-1889 套五支主線 migration,備份 ~/backup/guidant_ai_baseline_20260917_1836_before_CM-1889.dump。origin/feature/review。STG/POC 零碰。