每個人的 acr 是他自己上次編的那份——跟 main 沒有任何保證關係 #109

Open
opened 2026-08-12 15:16:07 +00:00 by Leo · 2 comments
Owner

症狀

acr 是 npm link 到 cli/dist/index.js,而 cli/dist/ 不在版控
git ls-files cli/dist 回空)。

⇒ 你跑的是你自己上次 npm run build 的產物。它可能比 main 舊好幾個 commit,
沒有任何東西會告訴你

差點造成的實害(2026-08-12)

總管要在真實例上驗 Arcrun#106/PR107 的修法,差點直接跑更新指令——
如果 dist/ 是舊的,修法不會生效,而我會判定「這個修法沒用」

那次是先重編才跑,所以沒出事。但「先想到要重編」靠的是運氣,不是機制。

為什麼這是結構問題,不是使用者疏忽

同一天已經有兩個同族的:

  • .worker-builds/ 成品落後源碼 ⇒ 出貨線第 1 站的 Arcrun#93 閘會擋(有守門員
  • kbdb/migrations/*.sql 被 gitignore 吃掉 ⇒ 沒人守,直到用戶更新才炸

cli/dist/ 是第三個,同樣沒有守門員。 三者共同形狀:
本機是對的,別人拿到的不是——而本機看不出來。

要達成什麼

acr 的人,能知道自己跑的是哪一版;落後時它要自己講。

不指定做法。方向供評估(不是指定):dist/ 進版控(與
.component-builds/**/component.wasm.worker-builds/ 同慣例)/
啟動時比對 distsrc 的 commit 並提示/把 #93 那種新鮮度閘套到 cli/dist

請自己判斷代價最小的。 特別想聽:dist/ 該不該進版控?
(另外兩個都進了,理由是「self-host 用戶要直接拿得到部署來源」——acr 的情況一樣嗎?)

怎麼驗才算數

  1. 故意讓 dist/ 落後 src 幾個 commit,跑任一 acr 指令 → 它要講(或自動修正)
  2. 正常情況(同步)不要吵——每次都跳警告等於沒警告
  3. 回歸:現有指令行為不變

紅線

  • 🔴 不准在 CI/hook 裡自動重編覆蓋人家的工作副本
  • 🔴 不准推 main、不准部署

📍 repo:matrix/arcruncli/.gitignore
📍 相關:Arcrun#93(成品比源碼舊就停下——現成的守門員範本)|Arcrun#80

## 症狀 `acr` 是 npm link 到 `cli/dist/index.js`,而 **`cli/dist/` 不在版控** (`git ls-files cli/dist` 回空)。 ⇒ 你跑的是**你自己上次 `npm run build` 的產物**。它可能比 main 舊好幾個 commit, 而**沒有任何東西會告訴你**。 ## 差點造成的實害(2026-08-12) 總管要在真實例上驗 `Arcrun#106`/PR107 的修法,差點直接跑更新指令—— 如果 `dist/` 是舊的,**修法不會生效,而我會判定「這個修法沒用」**。 那次是先重編才跑,所以沒出事。但「先想到要重編」靠的是運氣,不是機制。 ## 為什麼這是結構問題,不是使用者疏忽 同一天已經有兩個同族的: - `.worker-builds/` 成品落後源碼 ⇒ 出貨線第 1 站的 `Arcrun#93` 閘會擋(**有守門員**) - `kbdb/migrations/*.sql` 被 gitignore 吃掉 ⇒ **沒人守**,直到用戶更新才炸 **`cli/dist/` 是第三個,同樣沒有守門員。** 三者共同形狀: **本機是對的,別人拿到的不是——而本機看不出來。** ## 要達成什麼 **跑 `acr` 的人,能知道自己跑的是哪一版;落後時它要自己講。** 不指定做法。方向供評估(不是指定):`dist/` 進版控(與 `.component-builds/**/component.wasm`、`.worker-builds/` 同慣例)/ 啟動時比對 `dist` 與 `src` 的 commit 並提示/把 `#93` 那種新鮮度閘套到 `cli/dist`。 **請自己判斷代價最小的。** 特別想聽:**`dist/` 該不該進版控?** (另外兩個都進了,理由是「self-host 用戶要直接拿得到部署來源」——`acr` 的情況一樣嗎?) ## 怎麼驗才算數 1. 故意讓 `dist/` 落後 src 幾個 commit,跑任一 `acr` 指令 → **它要講**(或自動修正) 2. 正常情況(同步)**不要吵**——每次都跳警告等於沒警告 3. 回歸:現有指令行為不變 ## 紅線 - 🔴 不准在 CI/hook 裡自動重編覆蓋人家的工作副本 - 🔴 不准推 main、不准部署 📍 repo:`matrix/arcrun`(`cli/`、`.gitignore`) 📍 相關:`Arcrun#93`(成品比源碼舊就停下——現成的守門員範本)|`Arcrun#80`
Author
Owner

📐 收工標準補一條:修完要留一道會擋的閘(leo 2026-08-12 立原則後回頭補)

leo 2026-08-12:「做一個平台要減少 hotfix。

當晚實測:32 個 commit,其中 5 個在修「上一個修法造成的問題」
把那些 hotfix 逐個追根,全部由同兩種缺陷生出來:

  1. 同一個能力有兩份實作 ⇒ 修一次只到一半
  2. 規則存在,但沒有機制驗證有沒有照做 ⇒ 靠人記得,而人不記得

🔴 本票屬於第 ② 類。 對照組:.worker-builds 落後源碼這件事 Arcrun#93 守著
——當晚它擋對三次,每次都攔下一個「會送出舊東西」的出貨。
而本票這件事沒有守門員,所以它發生了,而且沒有任何一步會紅燈。

⇒ 因此本票的收工標準多一條(與原有的驗收並列,不取代)

修掉當下這個 bug 不算完成;要留下一個「下次再犯會被擋住」的機制。

那個機制長什麼樣由你判斷(hook/CI check/測試/管線的一站都可以),但要滿足:

  • 會擋,不是只提醒——當晚另一個教訓:「hook 只提醒不擋 ⇒ 我三次跳過都沒被攔住」
  • 誤攔比漏攔更容易殺死一道閘——被擋得莫名其妙,人就會學會繞過它,那它等於不存在。
    ⇒ 判準要看「這個動作有沒有在做那件事」,不是「字串裡有沒有出現那個詞」。
    (當晚總管修三道閘、製造了 5 次誤攔,全是這個病。)
  • 要能被測試——當晚有一道閘連「讀它自己的原始碼」都擋,導致它無法被驗證。
    迴歸測試寫成獨立檔案再跑,別讓閘擋住自己的測試。

為什麼加這條

不加的話,這張票修完之後,同一個形狀會在下一個沒人守的地方再出現一次——
而我們會再開一張票、再修一次。那就是 hotfix 迴圈,而平台的工作是讓它停下來。

—— [總管]
EOF

## 📐 收工標準補一條:**修完要留一道會擋的閘**(leo 2026-08-12 立原則後回頭補) leo 2026-08-12:「**做一個平台要減少 hotfix。**」 當晚實測:32 個 commit,**其中 5 個在修「上一個修法造成的問題」**。 把那些 hotfix 逐個追根,全部由同兩種缺陷生出來: 1. **同一個能力有兩份實作** ⇒ 修一次只到一半 2. **規則存在,但沒有機制驗證有沒有照做** ⇒ 靠人記得,而人不記得 🔴 **本票屬於第 ② 類。** 對照組:`.worker-builds` 落後源碼這件事**有** `Arcrun#93` 守著 ——當晚它擋對三次,每次都攔下一個「會送出舊東西」的出貨。 而本票這件事**沒有守門員**,所以它發生了,而且沒有任何一步會紅燈。 ### ⇒ 因此本票的收工標準多一條(與原有的驗收並列,不取代) **修掉當下這個 bug 不算完成;要留下一個「下次再犯會被擋住」的機制。** 那個機制長什麼樣由你判斷(hook/CI check/測試/管線的一站都可以),但要滿足: - **會擋,不是只提醒**——當晚另一個教訓:「hook 只提醒不擋 ⇒ 我三次跳過都沒被攔住」 - **誤攔比漏攔更容易殺死一道閘**——被擋得莫名其妙,人就會學會繞過它,那它等於不存在。 ⇒ 判準要看「**這個動作有沒有在做那件事**」,不是「**字串裡有沒有出現那個詞**」。 (當晚總管修三道閘、製造了 5 次誤攔,全是這個病。) - **要能被測試**——當晚有一道閘連「讀它自己的原始碼」都擋,導致它無法被驗證。 迴歸測試寫成獨立檔案再跑,別讓閘擋住自己的測試。 ### 為什麼加這條 不加的話,這張票修完之後,**同一個形狀會在下一個沒人守的地方再出現一次**—— 而我們會再開一張票、再修一次。**那就是 hotfix 迴圈,而平台的工作是讓它停下來。** —— [總管] EOF
Author
Owner

🔴 2026-08-13:它從「差點」變成「真的發生過」

本票原文寫的是:

「如果 dist/ 是舊的,修法不會生效,而我會判定『這個修法沒用』
那次是先重編才跑,所以沒出事。但『先想到要重編』靠的是運氣,不是機制。

今天運氣沒站在我這邊。

#108 併進 main 之後,leo 跑更新,那行 ARCRUN_NAMESPACE 沒印出來。
我先往 code 查了一輪——懷疑是保險(namespaceHasKnowledge)判定他的命名空間沒知識,
還特地量了那支 API 回 9 庫 / 1851 條,判定保險應該要過。查不出來才想到去看編譯產物:

grep -c namespaceHasKnowledge cli/dist/lib/deploy.js  →  0

那段程式碼根本不在他跑的那份裡。 我在 #107 之後編過一次,#108 是那之後才併的。

「保險拒絕了」和「寫它的程式碼不存在」,在畫面上長得一模一樣——都是沉默。
這是本票真正的危害:它不會報錯,它會讓你去修一個沒有壞的東西。

重編之後一次就通(ARCRUN_NAMESPACE = bfezv28vkbdb_get_map 回 9 庫)。

這改變了本票的優先序

原本它讀起來像「版控整潔問題」。實際上它是假信號製造機
本票不修,每一次 CLI 側的修法都要賭「這次有沒有人想起來重編」,
而賭輸的代價不是「沒生效」,是往錯的方向查一輪

—— [總管]

## 🔴 2026-08-13:它從「差點」變成「真的發生過」 本票原文寫的是: > 「如果 `dist/` 是舊的,修法不會生效,**而我會判定『這個修法沒用』**。 > 那次是先重編才跑,所以沒出事。**但『先想到要重編』靠的是運氣,不是機制。**」 **今天運氣沒站在我這邊。** `#108` 併進 main 之後,leo 跑更新,那行 `ARCRUN_NAMESPACE` 沒印出來。 我先往 code 查了一輪——懷疑是保險(`namespaceHasKnowledge`)判定他的命名空間沒知識, 還特地量了那支 API 回 9 庫 / 1851 條,判定保險應該要過。查不出來才想到去看編譯產物: ``` grep -c namespaceHasKnowledge cli/dist/lib/deploy.js → 0 ``` **那段程式碼根本不在他跑的那份裡。** 我在 `#107` 之後編過一次,`#108` 是那之後才併的。 ⇒ **「保險拒絕了」和「寫它的程式碼不存在」,在畫面上長得一模一樣——都是沉默。** 這是本票真正的危害:它不會報錯,它會讓你去修一個沒有壞的東西。 重編之後一次就通(`ARCRUN_NAMESPACE = bfezv28v`、`kbdb_get_map` 回 9 庫)。 ## 這改變了本票的優先序 原本它讀起來像「版控整潔問題」。實際上它是**假信號製造機**: 本票不修,每一次 CLI 側的修法都要賭「這次有沒有人想起來重編」, 而賭輸的代價不是「沒生效」,是**往錯的方向查一輪**。 —— [總管]
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Leo/Arcrun#109