console-ui:把「線上跑的是不是當代的」變成機械判準,並接進部署鏈
leo 2026-08-08:「已經發生過一次這個錯誤,把舊版界面上到 prod, 你要確定不可再犯。」 實測(repo 對線上,純文字資產比對): repo portal/index.html 343,969 bytes 線上 mira.uncle6.me 82,911 bytes(Songti 12 處,舊金色 serif 品牌) 線上 pages.dev 82,911 bytes(同上) 而e730b3f那版 verify-live 對這兩站**三項檢查全過**——因為它驗的是 組態(apiBase、profile 的 views/home),不是世代。 ⇒ 一個網址可以組態完全正確、卻對外展示一套早就被淘汰的介面, 而所有機械檢查都說它是綠的。這就是要消滅的狀態。 本次落地: 一、世代指紋(targets.mjs) 逐一取線上/產物的資產(index / portal / console / favicon.svg), 遮掉本來就該隨部署目標不同的那兩行(VIEWS/HOME),其餘按位元組比對。 刻意不用關鍵字清單——清單要人維護,而舊世代能無聲上線正是因為沒人記得維護它。 誠實 trade-off 寫在檔內:repo 改了沒部署就會判紅,那是正確的(那時線上確實不當代)。 二、宣告值真的寫進產物(收掉e730b3f標的 WIP) deploy.mjs 改為由 targets.mjs 產出 .staging/<目標> 再推: config.js 由宣告值即時產生、console 的 VIEWS/HOME 依 profile 覆寫, **覆寫沒命中就中止部署**;推之前回頭讀磁碟上那份驗一次(不看腳本印了什麼)。 public/config.js 刪除——它是產物不是原始碼。 三、修好一道從 08-03 起就在誤判的閘 t160 的世代閘比對 portal 全文含「登記新庫」即拒部,而 66f1b59(08-03) 加了一則**說明「已經把它拿掉了」的 HTML 註解** ⇒ 該閘自那天起每次誤判, npm run deploy:personal 連續五天推不出去。改成剝掉註解後只看可見內容, 並降級為輔助(主判準是指紋)。這正是「手工關鍵字閘會腐爛」的實例。 四、讓它在該跑的時候真的被跑到(不再生出沒人記得執行的腳本) · deploy.mjs 推完自動回頭驗線上,不過就算本次部署失敗 · .deploy-state.json 只在線上實測通過後才寫,且不進版控 (新 checkout 沒紀錄=狀態未知=該被提醒,而不是繼承別人的綠燈) · Stop hook 每回合離線比對「手上這一代 vs 最後一次驗過的部署」, 在要說「做完了」的那一刻出聲(實測 0.096s,不連網) 五、uncle6 邊界寫進工具本身(leo 08-08:「要看範例只在 youlin 網站,不要去碰 uncle6」) deploy.targets.json 的 enterprise 標 frozen:deploy 拒絕部署、verify 連抓都不抓。 目標本身保留不刪——刪掉就變成下一個 AI 眼中「從來沒有過這個站」的失憶。 同源清掉兩處還活著的舊記錄:README 的線上 demo 連結、public/index.html 的註解。 驗收證據見 commit 後的實測輸出(舊世代樣本取自 git 歷史 ad367e4,本機起站餵判準, 未碰任何線上資源)。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -512,6 +512,41 @@ Workers Secret 也還在)。正解=刪除鈕標「即將開通」等 T9,**
|
||||
|
||||
---
|
||||
|
||||
## 25. 組態全綠,介面卻是舊世代——「驗了組態」被當成「驗了線上」(2026-08-08)
|
||||
|
||||
**leo 原話**:「已經發生過一次這個錯誤,**把舊版界面上到 prod,你要確定不可再犯**。」
|
||||
|
||||
**現場**:實測三個對外網址,`apiBase` / `profile.views` / `profile.home` **三項全過**,
|
||||
而它們跑的是 07-22 那一代的 portal(82,911 bytes、舊金色 serif 品牌、`Songti` 12 處);
|
||||
repo 早已是 343,969 bytes 的新品牌世代,`Songti` 一處不剩。
|
||||
⇒ **一個網址可以組態完全正確、同時對外展示一套早就被淘汰的介面,而所有機械檢查都說它綠。**
|
||||
|
||||
**兩個根因,分開記**:
|
||||
|
||||
1. **驗證的維度少了一個**。組態(連去哪、開哪幾頁)與世代(跑的是哪一版前端)是**兩件事**,
|
||||
只驗前者會得到有害的綠燈——它讓人以為驗過了。
|
||||
解:`console-ui/scripts/verify-live.mjs` 加第二層「世代指紋」=逐一抓線上資產、
|
||||
遮掉本來就該隨部署目標不同的那兩行(VIEWS/HOME),**其餘按位元組比對 repo `public/`**。
|
||||
位元組比對是刻意的:**不用關鍵字清單**——清單要人維護,而舊世代能無聲上線,
|
||||
正是因為沒有人記得維護它。
|
||||
|
||||
2. **手工維護的關鍵字閘會腐爛,而且會反過來咬你**。t160 那道世代閘寫的是
|
||||
「portal 全文含『登記新庫』就拒部」。08-03(`66f1b59`)有人在 portal 加了一則
|
||||
**說明「已經把登記新庫拿掉了」的 HTML 註解** ⇒ 這道閘從那天起每次都誤判,
|
||||
`npm run deploy:personal` 連續五天推不出去,而錯誤訊息說的是「你的 UI 是舊代」。
|
||||
解:文字閘比對前先剝掉 HTML 註解(只看使用者看得到的內容),並降級成輔助——主判準是指紋。
|
||||
|
||||
**判準(下次照用)**:問「線上這一份**是不是我們手上這一份**」,
|
||||
不要問「線上這幾個設定值對不對」。前者一句話涵蓋後者答不出來的東西。
|
||||
|
||||
**還有一半是「有沒有人記得跑」**。再好的檢查放在沒人執行的腳本裡等於不存在(這個 repo 已有數支那種)。
|
||||
故三處接死:① `deploy.mjs` 推完自動回頭驗線上,不過就算本次部署失敗;
|
||||
② `.deploy-state.json` **只在線上實測通過後**才寫(不是跑過指令就寫);
|
||||
③ Stop hook(`stop-check-sync.sh`)每回合離線比對「手上這一代 vs 最後一次驗過的部署」,
|
||||
在 CC 要說「做完了」的那一刻出聲。
|
||||
|
||||
---
|
||||
|
||||
## 快速檢查清單(做新功能前)
|
||||
|
||||
- [ ] 這是工作流還是零件?問「有必要嗎?」
|
||||
@@ -531,3 +566,5 @@ Workers Secret 也還在)。正解=刪除鈕標「即將開通」等 T9,**
|
||||
- [ ] 退役/降級某零件?同步清「AI 搜尋零件的三個源」=示例 yaml + parts.ts 硬編碼清單 + (validate 跳過是設計);別只改一處宣布完成(#22)
|
||||
- [ ] 沒對應 recipe?誠實留 TODO + 發 issue 補 seed,別硬塞語意不符的 canonical_id 充數(假綠,#22)
|
||||
- [ ] 本地/Gitea 改完 code 想 `acr update` 部署?先確認:它抓的是 GitHub codeload tarball,不是你剛改的目錄(#23)
|
||||
- [ ] 改完前端說「做完了」?先問**線上跑的是不是這一份**(`cd console-ui && npm run verify`)——組態綠不代表世代對(#25)
|
||||
- [ ] 要寫「含某關鍵字就擋」的閘?先想「有人寫一則說明它已被移除的註解時會怎樣」——關鍵字閘會腐爛,優先用指紋(#25)
|
||||
|
||||
Reference in New Issue
Block a user