release(1.19.0): 掛上機械閘+出貨版號與 changelog(W2 Phase 4-5,收尾)

SDD: docs/3-specs/jdd-dual-profile — 33/33 編號 task 全數完成。

■ Phase 4 把閘掛上去
- scripts/check-all.sh:三道閘+腳本語法的總入口(一個習慣,不是三個要記得的步驟)
- .githooks/pre-commit + core.hooksPath:跑在人的機器上、commit 那一刻
  不掛雲端 workflow——本組織禁止 repo 掛自動化(歷史上那正是帳號被停權的原因)

■ Phase 5 出貨
- VERSION 1.18.0 → 1.19.0(兩處:template/.claude/ 與 template/system-dev/)
- CHANGELOG 1.19.0:用「你會多出什麼」的語言寫,不列檔名
- 🐛 順手補回 **1.18.0 完全沒有 changelog 紀錄**這件事——
  那一版發佈了、功能也出貨了,但更新跑完最後一行正是叫使用者「改了什麼看 CHANGELOG」,
  版號動了卻查不到動了什麼=等於沒交代。依實際 commit 內容補寫。

■ 七題驗收(全部附實測輸出)
-  G2 考生改考卷被攔(命門):engineer 改 journeys.md → exit 2;
     連「把考題藏進 status.md」也擋,6/6
-  G3 進度以站計量:起牀推「J-1 已點亮 n/m 站」,收工列未亮站並禁用任務數當理由
-  G4 憲法分流:總管版技術軌關鍵字 0、成員版上游指針 8,界標各 4/4
-  G6 實例改機制被攔:4/4(框架開發放行、使用者自訂插槽放行)
-  G7 框架混入實例名:指名 sdd-check.md:77,exit 1
- ◐ G1 PM 優先補接縫:機制齊了,但這是行為題,腳本證明不了 → 不標綠
- ◐ G5 政策包即插即用:插槽就位,政策包本體在 W3

■ 安裝實測:兩個乾淨環境各 1 秒、48/54 檔、版本 1.19.0、profile 正確
  (預測①「各 < 10 分鐘」達標;誠實註記:來源走本機檔案,比真實網路快)

🔴 狀態=**等發佈**,不是 :更新來源是公開 GitHub raw,
   只推 Gitea 的話外部實例抓不到 1.19.0。開閘由 leo 決定。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-06 00:34:23 +08:00
parent 2f5d9f3bb2
commit 593defceb1
6 changed files with 144 additions and 11 deletions
+18
View File
@@ -0,0 +1,18 @@
#!/bin/bash
# pre-commit — commit 前跑框架的機械閘
#
# 啟用(每個 clone 做一次,之後跟著 repo 走):
# git config core.hooksPath .githooks
#
# 為什麼版控在 .githooks/ 而不是 .git/hooks/
# .git/hooks/ 不會被 clone 帶走 ⇒ 換一台機器、換一個人,閘就悄悄消失了,
# 而且沒有任何跡象。放進版控,至少「有沒有啟用」是查得到的事實。
#
# 為什麼不掛雲端 workflow
# 本組織禁止在 repo 上掛自動化 workflow(歷史上「一個 push 觸發大量自動化」
# 正是帳號被停權的原因)。閘跑在人的機器上、commit 的那一刻。
#
# 真的要跳過(例如緊急修):git commit --no-verify
# ——留痕可審,不是不可能繞過。
exec bash scripts/check-all.sh
+61
View File
@@ -10,6 +10,67 @@
---
## 1.19.0 — 一套模板,兩種身分:總管版與成員版
**這一版你會多出什麼**
- **裝的時候可以選「這是什麼」**`--profile=repo`(實際寫程式的專案)或
`--profile=orchestrator`(管一群專案的上層資料夾)。不選就自動偵測、問你一次,
之後記住不再問。**兩種身分讀到的規則完全不同**——總管版看不到技術細節那一套,
成員版會帶一行指回上游。
- **CLAUDE.md 從此分成兩區**:上面是「模板維護的」、下面是「你自己寫的」,
中間有看不見的分隔標記。以前這兩者混在一起,導致更新**永遠不敢覆蓋**,
模板後來改的規則就送不到你手上。現在上面那區可以安全更新,下面那區永遠不動。
- **更新會告訴你「哪些檔被手改過」**:改過的**不覆蓋**,新版另存 `.new` 讓你自己比對。
(實測一個真實使用中的專案:6 支模板 hook 裡 **4 支已被手改**,而在這之前
沒有任何機制知道這件事——那 4 支從此收不到任何修正。)
- **PM 那一套工作方法有了現成範本**(總管版才裝):白話需求卡、使用者旅程與考題、
以站為單位的衝刺表、能力域分派表。填了之後更新永遠不會覆蓋你的內容。
- **多了六道自動攔截**,全部是「做錯的當下就擋」而不是事後提醒:
- 寫程式的人**改不了驗收考題**(改考題就能「通過」的漏洞堵住了)
- 當 PM 的**寫不了程式、改不了任務清單**
- 專案**改不了模板發下來的機制**(要改就回上游提案,一次修好所有人的)
- 需求卡如果是「賭注」卻沒寫對帳日 → 擋
- 新任務沒說它服務哪一站 → 擋
- 給人看的文件混進技術術語 → 擋
- 動了程式 → 主動告訴你要重驗哪幾題
- **收工的判準換了**:不再是「任務都關了」,而是「**指定的那幾站考題全綠**」。
**修掉的老問題(都是靜默失敗,你不會收到錯誤訊息的那種)**
- **新安裝的人拿不到最近三版的招牌功能**:安裝和更新各有一份手抄的檔案清單、
早就對不上——更新會裝的四個檔,安裝從來不裝。**先裝舊版再更新的人反而拿得比較多。**
現在兩邊讀同一份清單,這種漂移在結構上不可能再發生。
- **更新會被「找不到頁面」騙**:以前只檢查「下載回來的檔案不是空的」,
但錯誤頁面也不是空的 ⇒ **好檔案被無聲覆寫成一行垃圾**(曾經有份文件從 260 行變 1 行)。
- **更新遇到新資料夾會失敗,但版本號照升**(典型的假成功,半年前就被記下來、一直沒修)。
**給模板維護者**
- 安裝清單改成資料表(`template/manifest/*.tsv`),加產物 = 加一行,不必改腳本
- 兩道機械閘:範本混入特定專案名 → 擋;已發佈的檔案路徑被搬走 → 擋
(後者防的是「舊版使用者更新時整排失敗,而且不會有下一次更新來修它」)
- `git config core.hooksPath .githooks` 啟用 commit 前自動檢查
---
## 1.18.0 — 提醒你「改好的東西還沒發佈出去」
> 📌 補記於 2026-08-06:這一版當時發佈了(版號升了、功能也出貨了),
> **但漏了寫這則紀錄**。而更新跑完的最後一行正是叫你「改了什麼看 CHANGELOG.md」——
> 版號動了卻查不到動了什麼,等於沒交代。依實際 commit 內容補回。
**這一版你會多出什麼**
- **開啟工作階段時,會告訴你「公開版落後了」**:
草稿區與公開區是**手動同步**的,改完東西若沒人記得發佈,
外部使用者抓到的還是舊版——**而且不會有任何錯誤訊息,只是行為不對**,
所以自己人永遠測不出來。這個提醒就是來消滅「忘了發佈」這個失敗模式。
- 如果這批改動含編譯產物,會**額外標紅**(因為安裝器是直接去公開位址抓那個檔的)。
- **只提醒、不阻擋**——發不發佈是人的決定。
---
## 1.17.0 — 查詢一律從最強的查法開始(語意 → 關鍵字 → grep)
**leo 2026-07-21**:「它一定是用最好的搜尋,如果沒有才 fallback,
+11 -9
View File
@@ -4,8 +4,10 @@
> 規則:動手前標 [🔄],完成立刻標 [x],不批次更新。
> **每一項都標「服務哪條 Gherkin」**G1G7 定義見 `requirements.md` §四)。
> 🟢 **status: active2026-08-05 leo 回「開工」)**
> 進度:**防炸兩閘 + Phase 0~3 全數完成**,兩件舊債已還清
> **Phase 4(框架 CI 掛載)與 Phase 5(出貨/版號)尚未開工。**
> 進度:**33/33 編號 task 全數完成**2026-08-06)。版本 1.18.0 → **1.19.0**
> 七題驗收:**✅ 5 題(G2/G3/G4/G6/G7,皆附實測輸出)/◐ 2 題**——
> G1 是行為題(要真的派一次工才驗得到)、G5 的政策包本體在 W3。
> 🔴 **狀態=等發佈**:更新來源是公開 GitHub raw,需 leo 開閘才送得到外部實例。
---
@@ -217,20 +219,20 @@
> 前置條件:Phase 1manifest 定義了「範本區」)
- [ ] 4.1 `scripts/check-no-instance-names.sh` `scripts/instance-names.txt`
- [x] 4.1 `scripts/check-no-instance-names.sh` `scripts/instance-names.txt`
- 服務:**G7**
- 行為:掃 `template/`,命中黑名單 → exit 1 並印「檔案:行號:命中詞」;
支援逐行豁免標記(行尾 `# sdt-instance-name-ok`);policy pack 路徑不受檢
- 驗收:在範本檔新增一行含 "arcrun" → 檢查 fail 並指出檔案與行號(**這條就是 G7**),貼輸出
- [ ] 4.2 現況 20 行命中的分診處置(design §0.5)
- [x] 4.2 現況 20 行命中的分診處置(design §0.5)
- 服務:**G7**
- (a) 6 行註解/舉例 → 改寫成通用敘述
- (b) 3 行政策內容 (c) 13 行 L2 產物 → 標 `# sdt-instance-name-ok` 一行「W3 搬遷」註記
- 驗收:處置後 `check-no-instance-names.sh` 回 exit 0,且豁免行數 = 16(貼清單)
- 注意:**禁止假性清理**(把 arcrun 改寫成「某工作流引擎」=資訊消失、問題還在)
- [ ] 4.3 掛 pre-commit / CI
- [x] 4.3 掛 pre-commit / CI
- 服務:**G7**
- 驗收:`bash scripts/check-no-instance-names.sh` 在 CI 步驟中被呼叫,故意違規的 commit 被擋
@@ -240,25 +242,25 @@
> 前置條件:Phase 04 全部完成
- [ ] 5.1 CHANGELOG VERSION bump**兩處**`template/.claude/VERSION` `template/system-dev/VERSION`
- [x] 5.1 CHANGELOG VERSION bump**兩處**`template/.claude/VERSION` `template/system-dev/VERSION`
- 服務:全部
- 版號:1.18.0 → **1.19.0**(新功能、向下相容)
- 驗收:兩個 VERSION 檔內容一致;CHANGELOG 用用戶語言寫「這一版你會多出什麼」
- 注意:版本號是 leo 唯一的驗收介面——沒動=等於沒交付
- [ ] 5.2 乾淨環境雙 profile 安裝實測(含計時)
- [x] 5.2 乾淨環境雙 profile 安裝實測(含計時)
- 服務:**G4**
- 驗收:兩個全新空目錄各裝一次,**各記錄實際耗時**(分離 §八 預測①:各 < 10 分鐘),
貼安裝輸出 `ls -R` 檔案清單對照
- [ ] 5.3 七題 Gherkin 逐條實測並記錄三態
- [x] 5.3 七題 Gherkin 逐條實測並記錄三態
- 服務:**G1G7**
- 驗收:每題貼實測輸出並標 `✅ 通 / ◐ 半通(缺什麼)/ ❌ 斷`
- 注意:**G5 本波上限 `◐`**(插槽就位、政策包在 W3),標 ✅ 就是假綠;
G1 需要 root/journeys 有實內容才驗得到端到端 → 若實例尚未落地(W4),
以框架附的示範 fixture 驗,並在報告標明「以 fixture 驗,實例端到端待 W4」
- [ ] 5.4 回報總管:交付物、三態表、與規格假設不符的清單
- [x] 5.4 回報總管:交付物、三態表、與規格假設不符的清單
- 服務:全部
- 驗收:報告含 design §0 全部實查發現 + 本波實際落地的 hook 數(改既有 vs 新增)
+52
View File
@@ -0,0 +1,52 @@
#!/bin/bash
# check-all.sh — 框架的機械閘總入口(commit 前跑這一支就好)
#
# 為什麼要有總入口:三支閘分開跑,遲早有人只記得跑其中一支。
# 一個入口 = 一個習慣,而不是三個要記得的步驟。
#
# 掛法(版控在 .githooks/,跟著 repo 走,不必每台機器重設):
# git config core.hooksPath .githooks
#
# 為什麼不用 CI workflow:本組織的鐵律禁止在 repo 上掛自動化 workflow
#(歷史上正是「一個 push 觸發大量自動化」把帳號弄到被停權)。
# 閘要跑在**人的機器上、commit 的那一刻**,不是掛在雲端等事件。
set -uo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$REPO_ROOT"
FAIL=0
run() { # $1=名稱 $2...=命令
local name="$1"; shift
printf '── %s\n' "$name"
if "$@"; then :; else FAIL=1; fi
echo ""
}
echo "════════════════════════════════════════════════"
echo "🔎 框架機械閘(commit 前檢查)"
echo "════════════════════════════════════════════════"
run "框架不含實例資料" bash scripts/check-no-instance-names.sh
run "已發佈路徑只增不移" bash scripts/check-legacy-paths.sh
run "單一活性規格" bash system-dev/scripts/sdd-active-check.sh docs/3-specs
# 腳本語法(壞掉的 shell 推出去,實例的更新機制就跟著壞)
printf '── 腳本語法\n'
SYNTAX_BAD=0
for f in scripts/*.sh template/.claude/hooks/*.sh template/.claude/hooks/lib/*.sh \
template/profiles/*/hooks/*.sh template/scripts/*.sh; do
[ -f "$f" ] || continue
bash -n "$f" 2>/dev/null || { echo " ❌ 語法錯誤:$f"; SYNTAX_BAD=1; FAIL=1; }
done
[ $SYNTAX_BAD -eq 0 ] && echo " ✅ 全部通過"
echo ""
if [ $FAIL -ne 0 ]; then
echo "════════════════════════════════════════════════"
echo "❌ 有檢查沒過——先修,別 commit"
echo "════════════════════════════════════════════════"
exit 1
fi
echo "✅ 全部通過"
exit 0
+1 -1
View File
@@ -1 +1 @@
1.18.0
1.19.0
+1 -1
View File
@@ -1 +1 @@
1.18.0
1.19.0