diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000..6a96f88 --- /dev/null +++ b/.githooks/pre-commit @@ -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 diff --git a/CHANGELOG.md b/CHANGELOG.md index ccfcb62..acda198 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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, diff --git a/docs/3-specs/jdd-dual-profile/tasks.md b/docs/3-specs/jdd-dual-profile/tasks.md index 86e6bac..720a3fd 100644 --- a/docs/3-specs/jdd-dual-profile/tasks.md +++ b/docs/3-specs/jdd-dual-profile/tasks.md @@ -4,8 +4,10 @@ > 規則:動手前標 [🔄],完成立刻標 [x],不批次更新。 > **每一項都標「服務哪條 Gherkin」**(G1–G7 定義見 `requirements.md` §四)。 > 🟢 **status: active(2026-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 1(manifest 定義了「範本區」) -- [ ] 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 0–4 全部完成 -- [ ] 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 逐條實測並記錄三態 - 服務:**G1–G7** - 驗收:每題貼實測輸出並標 `✅ 通 / ◐ 半通(缺什麼)/ ❌ 斷` - 注意:**G5 本波上限 `◐`**(插槽就位、政策包在 W3),標 ✅ 就是假綠; G1 需要 root/journeys 有實內容才驗得到端到端 → 若實例尚未落地(W4), 以框架附的示範 fixture 驗,並在報告標明「以 fixture 驗,實例端到端待 W4」 -- [ ] 5.4 回報總管:交付物、三態表、與規格假設不符的清單 +- [x] 5.4 回報總管:交付物、三態表、與規格假設不符的清單 - 服務:全部 - 驗收:報告含 design §0 全部實查發現 + 本波實際落地的 hook 數(改既有 vs 新增) diff --git a/scripts/check-all.sh b/scripts/check-all.sh new file mode 100755 index 0000000..9367c85 --- /dev/null +++ b/scripts/check-all.sh @@ -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 diff --git a/template/.claude/VERSION b/template/.claude/VERSION index 84cc529..815d5ca 100644 --- a/template/.claude/VERSION +++ b/template/.claude/VERSION @@ -1 +1 @@ -1.18.0 +1.19.0 diff --git a/template/system-dev/VERSION b/template/system-dev/VERSION index 84cc529..815d5ca 100644 --- a/template/system-dev/VERSION +++ b/template/system-dev/VERSION @@ -1 +1 @@ -1.18.0 +1.19.0