docs(sdlc): 同步文件與參考資料
What:更新 README、AGENTS.md、templates 與 references,讓文件敘述與實際行為一致。 Why:稽核發現多處文件與程式行為分歧,違反「每個意義只有單一真實來源」。 How:以實際程式行為為準改寫敘述,重複的規則收成單一來源並以一行指引指過去。 Who:jsc-meta:skill-check 例行稽核(2026-08-25)。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+29
-21
@@ -4,22 +4,30 @@
|
||||
|
||||
## 總則:一律以遠端為準,不吃本地分支
|
||||
|
||||
SDLC 各階段引用的參考分支與來源分支,**一律指遠端的 `origin/{分支}`**。本地分支不可作為基準。
|
||||
SDLC 各階段引用的參考分支與來源分支,**一律指遠端的 `origin/{branch}`**。本地分支不可作為基準。
|
||||
|
||||
理由:本地分支可能落後遠端、可能有沒推上去的 commit、也可能是別的工作留下的狀態。以本地為基準,分析會對著過時的程式碼做,實作會從錯誤的起點長出來,而且錯了不會有任何徵兆。
|
||||
|
||||
| 項目 | 規則 |
|
||||
| --- | --- |
|
||||
| 動作之前 | 先 `git fetch --prune origin`。**沒 fetch 就用 `origin/{分支}` 等於用快取**,遠端追蹤參照可能已經過時,連分支被刪掉都看不出來 |
|
||||
| 動作之前 | 先 `git fetch --prune origin`。**沒 fetch 就用 `origin/{branch}` 等於用快取**,遠端追蹤參照可能已經過時,連分支被刪掉都看不出來 |
|
||||
| 列分支 | `git branch -r`,不看 `git branch` |
|
||||
| 基準與比對 | 一律寫 `origin/{分支}`,例如 `git rev-list --count origin/master..origin/develop` |
|
||||
| 建立 worktree | 從 `origin/{來源分支}` 建,不從本地同名分支建 |
|
||||
| 基準與比對 | 一律寫 `origin/{branch}`,例如 `git rev-list --count origin/master..origin/develop` |
|
||||
| 建立 worktree | 從 `origin/{source-branch}` 建,不從本地同名分支建 |
|
||||
| 判定預設分支 | `refs/remotes/origin/HEAD`(見〔判定遠端預設分支〕) |
|
||||
|
||||
**本地與遠端不一致時一律停下回報**,不自行 `pull`、不自行 `reset`、不自行切換。要不要同步是使用者的決定。
|
||||
|
||||
`origin` 以外的遠端名稱(例如 `upstream`):先問使用者以哪個遠端為準,不臆測。
|
||||
|
||||
### 來源分支在遠端找不到:停下回報,不退回預設分支
|
||||
|
||||
已指定的來源分支,`origin/{source-branch}` 在遠端不存在時,**回報並停止**。不改用 `develop`、不改用 `master`、不套用任何後備分支,也不自行建立同名分支。這條沒有例外。
|
||||
|
||||
理由:來源分支是那份分析的功能分支。悄悄退回 `develop`,單一工作包就會越過自己的功能分支直接進 `develop`,而且沒有任何徵兆看得出來。
|
||||
|
||||
**這是停止條件,不是後備條件。**〔判定遠端預設分支〕那節的後備順序只用在「還沒有指定分支、要挑一條基準」的情況;指定過的來源分支找不到,一律套用本節。
|
||||
|
||||
## 先確認,再動工
|
||||
|
||||
| 階段 | 要確認的分支 | 確認時機 |
|
||||
@@ -40,21 +48,23 @@ SDLC 各階段引用的參考分支與來源分支,**一律指遠端的 `origi
|
||||
2. 取不到時退而用 `git remote show origin`,找輸出中的 `HEAD branch:` 那行。
|
||||
3. 兩者都取不到 → 回報並停止,**不臆測** `master`/`main`。
|
||||
|
||||
需要基準或後備分支時(例如 PR 目標):`origin/develop` 存在就用 `develop`;否則 `origin/master` 存在就用 `master`;兩者皆無則回報並停止。
|
||||
還沒有指定分支、需要挑一條基準或後備分支時(例如維護階段要落腳的分支):`origin/develop` 存在就用 `develop`;否則 `origin/master` 存在就用 `master`;兩者皆無則回報並停止。
|
||||
|
||||
這條後備順序**不適用於已指定的來源分支**。指定過的來源分支在遠端找不到,一律回報並停止,見總則的〔來源分支在遠端找不到〕。
|
||||
|
||||
## 只讀階段不動工作區
|
||||
|
||||
`analyze` 是 logic-only 階段:
|
||||
|
||||
- **工作目錄的 HEAD 必須與 `origin/{來源分支}` 指向同一個 commit**。落後、超前或分歧都代表讀到的不是遠端現況——停下來回報差距(`git rev-list --left-right --count origin/{來源分支}...HEAD`),請使用者自己處理。
|
||||
- **工作目錄的 HEAD 必須與 `origin/{source-branch}` 指向同一個 commit**。落後、超前或分歧都代表讀到的不是遠端現況——停下來回報差距(`git rev-list --left-right --count origin/{source-branch}...HEAD`),請使用者自己處理。
|
||||
- 需要換分支才能讀到正確現況時,**停下來請使用者自己切換**。
|
||||
- 不代為 `switch`、不 `stash`、不動工作區、不建分支。
|
||||
|
||||
## 實作階段的分支選擇
|
||||
|
||||
實作在 worktree 內進行,工作分支從 `origin/{來源分支}` 長出來,做完再 PR 回同一條來源分支。
|
||||
實作在 worktree 內進行,工作分支從 `origin/{source-branch}` 長出來,做完再 PR 回同一條來源分支。
|
||||
|
||||
- **一個工作包一個 PR**,目標一律是 `origin/{來源分支}`。不把兩個完成的工作包併成一個 PR,也不把完成的工作包留到下一包一起送——拆工作包的意義就是各自能獨立審查。
|
||||
- **一個工作包一個 PR**,目標一律是 `origin/{source-branch}`。不把兩個完成的工作包併成一個 PR,也不把完成的工作包留到下一包一起送——拆工作包的意義就是各自能獨立審查。
|
||||
- 呼叫 `jsc-git:pr` 時**必須明確帶入來源分支當 base**。該 skill 在沒收到 base 時會自行退回 `develop`,那會讓單一工作包越過它所屬的功能分支直接進 develop。
|
||||
- 來源分支整條後續要進 `develop` 時,那是另一個獨立的 PR,不在本階段範圍。
|
||||
- 新分支名稱要可讀且不覆蓋既有分支;本地或遠端已存在同名分支時,換一個時間戳或短 hash。
|
||||
@@ -62,15 +72,15 @@ SDLC 各階段引用的參考分支與來源分支,**一律指遠端的 `origi
|
||||
|
||||
## 實作一律在 worktree 內進行
|
||||
|
||||
`implement` 動任何程式碼之前,先 `git fetch --prune origin`,再從**分析頁記錄的來源分支的遠端版本**(`origin/{來源分支}`)建立 git worktree。所有修改都在 worktree 內,主工作目錄的分支與工作區完全不動。
|
||||
`implement` 動任何程式碼之前,先 `git fetch --prune origin`,再從**分析頁記錄的來源分支的遠端版本**(`origin/{source-branch}`)建立 git worktree。所有修改都在 worktree 內,主工作目錄的分支與工作區完全不動。
|
||||
|
||||
### 路徑
|
||||
|
||||
```
|
||||
{工作目錄}/.worktree/{分析頁 HASH}/{repo}
|
||||
{cwd}/.worktree/{analysis-HASH}/{repo}
|
||||
```
|
||||
|
||||
- `{分析頁 HASH}`:`ANALYZE_{HASH}` 的 HASH 部分,不含 `ANALYZE_` 前綴。
|
||||
- `{analysis-HASH}`:`ANALYZE_{HASH}` 的 HASH 部分,不含 `ANALYZE_` 前綴。
|
||||
- `{repo}`:存取庫名稱,不含 owner(`HP/WebService.Buy` → `WebService.Buy`)。不同 owner 的同名存取庫同時出現時,才改用 `{owner}-{repo}` 避免蓋掉,並在輸出中說明。
|
||||
- 一份分析涉及多個存取庫時,每個存取庫各一個 worktree,並列在同一個 HASH 目錄下。
|
||||
|
||||
@@ -80,22 +90,23 @@ SDLC 各階段引用的參考分支與來源分支,**一律指遠端的 `origi
|
||||
|
||||
| 選項 | 指令 | 影響 |
|
||||
| --- | --- | --- |
|
||||
| 以來源分支為基準開新工作分支 | `git worktree add -b {工作分支} {路徑} "origin/{來源分支}"` | commit 落在新分支,來源分支不動 |
|
||||
| 直接簽出來源分支 | `git worktree add --track -b {來源分支} {路徑} "origin/{來源分支}"` | 建立追蹤遠端的本地分支再簽出;本地已存在同名分支時指令會失敗,此時先確認它與遠端一致才可改用 `git worktree add {路徑} {來源分支}`,不一致就停下回報 |
|
||||
| 以來源分支為基準開新工作分支 | `git worktree add -b {work-branch} {path} "origin/{source-branch}"` | commit 落在新分支,來源分支不動 |
|
||||
| 直接簽出來源分支 | `git worktree add --track -b {source-branch} {path} "origin/{source-branch}"` | 建立追蹤遠端的本地分支再簽出;本地已存在同名分支時指令會失敗,此時先確認它與遠端一致才可改用 `git worktree add {path} {source-branch}`,不一致就停下回報 |
|
||||
|
||||
**不得自行預設**,也不得跳過詢問。
|
||||
|
||||
### 建立時的鐵則
|
||||
|
||||
- **分支名與路徑一律加引號**:來源分支可能含中文、空白或多層斜線(例如 `feat/一址通/查地址/完整版/P2`),不加引號會被切斷。
|
||||
- **分支名與路徑一律加引號**:既有的來源分支可能含空白、多層斜線或非 ASCII 字元(例如 `feat/addr-lookup/query/full/P2` 這種多層命名,或更舊的分支帶空白),不加引號會被切斷。
|
||||
- **jsc 自己開的分支只用 ASCII**(`a-z0-9` 與 `/`、`-`)。中文標題先翻譯成英文短語,再 slug 化當分支名。
|
||||
- 找不到該存取庫的本地 clone → **停下來問使用者路徑**,不自行 clone、不臆測位置。
|
||||
- 目標路徑已存在 → 不覆蓋。先確認它是不是同一份工作的 worktree(`git worktree list`),是就沿用,不是就回報並停止。
|
||||
- 把 `.worktree/` 加進該存取庫的 `.git/info/exclude`(不動使用者的 `.gitignore`,那是專案共用檔)。
|
||||
- 建立後在輸出中明確列出:worktree 路徑、簽出的分支、來源分支,以及 `origin/{來源分支}` 當下的 commit sha——那是這次實作的起點,要能事後追。
|
||||
- 建立後在輸出中明確列出:worktree 路徑、簽出的分支、來源分支,以及 `origin/{source-branch}` 當下的 commit sha——那是這次實作的起點,要能事後追。
|
||||
|
||||
### 移除時機
|
||||
|
||||
**PR 合併之後才移除**:`git worktree remove {路徑}`,接著 `git worktree prune`。
|
||||
**PR 合併之後才移除**:`git worktree remove {path}`,接著 `git worktree prune`。
|
||||
|
||||
不是 PR 建立後就移除——審查留言可能要求修改,而修改要回到同一個 worktree、推到同一條工作分支(PR 會自己更新,不開第二個 PR)。先移除就得為了改一行重建整個 worktree。
|
||||
|
||||
@@ -105,12 +116,9 @@ SDLC 各階段引用的參考分支與來源分支,**一律指遠端的 `origi
|
||||
|
||||
### PR 未合併就不開下一個工作包
|
||||
|
||||
一個工作包的 PR 還沒合併,就不得開始下一包。每次要領工作包之前先確認:
|
||||
一個工作包的 PR 還沒合併,就不得開始下一包。修正一律回原 worktree、推同一條工作分支,**不為同一包開第二個 PR**。
|
||||
|
||||
1. `gitea.sh pr-status {owner}/{repo} {index}` 看 `{state} {merged} {mergeable}`。
|
||||
2. 未合併 → **同時**用 `gitea.sh pr-comments {owner}/{repo} {index}` 讀留言(issue 留言、審查評語、行內留言,含沒有文字的 `APPROVED`/`REQUEST_CHANGES`),原文轉述給使用者。
|
||||
3. 依 `jsc-ask:ask` 詢問:依留言修正(回原 worktree 改、推同一條工作分支)或先等待。**不自行決定,也不為同一包開第二個 PR。**
|
||||
4. 已關閉但未合併 → 回報並詢問,不得當成完成。
|
||||
查驗程序(查狀態、讀留言、詢問修正或等待、已關閉但未合併怎麼辦)由 `skills/implement/SKILL.md` 步驟 4 擁有,本檔不重複。
|
||||
|
||||
## 不破壞既有工作
|
||||
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
# 交付內容型別
|
||||
|
||||
交付/交接工作包開工時,先跟使用者確認這份交付要產出什麼內容。預設選項固定兩個,其餘由使用者輸入。
|
||||
詢問時機與鐵則(不得自行預設、不得跳過詢問)由 `skills/implement/SKILL.md` 步驟 7 擁有。本檔只定義每個選項要產出什麼內容。
|
||||
|
||||
| 選項 | 內容 |
|
||||
| --- | --- |
|
||||
| 1. API 文件 | 端點路徑、輸入參數(**全部**)、輸出參數(**全部**);見下節 |
|
||||
| 2. 由使用者輸入 | 使用者自己講要什麼內容;照使用者說的做,不套 API 文件格式 |
|
||||
|
||||
選項一律依 `jsc-ask:ask` 規則呈現,並標明影響範圍。**不得自行預設,也不得跳過詢問。**
|
||||
|
||||
## API 文件
|
||||
|
||||
### 必備欄位
|
||||
@@ -23,7 +21,7 @@
|
||||
|
||||
### 參數範例:真實資料優先
|
||||
|
||||
1. 先找真實來源:資料庫欄位與實際資料列、實際 API 回應、既有設定檔或 fixture、日誌。標成 `真實:{來源}`。
|
||||
1. 先找真實來源:資料庫欄位與實際資料列、實際 API 回應、既有設定檔或 fixture、日誌。標成 `真實:{source}`(`{source}` 換成實際來源名稱)。
|
||||
2. 找不到來源才由邏輯推理,標成 `推論:無來源`,讓接手者知道那個值還沒被驗證。
|
||||
3. **不得**編一個看起來合理的值當成真實資料。
|
||||
4. 範例只保留**結構與格式**。個資一律遮蔽或改寫成格式描述,不把真實個資寫進交付文件。
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# 模型閘門 — 各階段動工前的能力標籤判定
|
||||
|
||||
SDLC 每個階段動工前先過模型閘門。判定全在程式層,由 `jsc-hooks/hooks/sdlc-gate.sh` 執行;模型不得自評標籤。
|
||||
|
||||
## 執行順序
|
||||
|
||||
1. `jsc-cli/tools/model-tags.sh sync`:把 `jsc-cli/references/model-tags.md` 的標籤表同步到 `$JSC_HOME/model-tags.tsv`。
|
||||
2. `jsc-hooks/hooks/sdlc-gate.sh lock {stage}`:腳本從 transcript 讀出**實際**模型 id,比對該階段的必要標籤,相符才上鎖。
|
||||
|
||||
## 各階段必要標籤
|
||||
|
||||
| 階段 | 必要標籤 |
|
||||
| --- | --- |
|
||||
| `plan` | `reasoning-max` |
|
||||
| `analyze` | `reasoning-max` |
|
||||
| `implement` | `coding` |
|
||||
| `maintain` | 無。實際模型 id 可判定就通過 |
|
||||
|
||||
## 鐵則
|
||||
|
||||
| 項目 | 規則 |
|
||||
| --- | --- |
|
||||
| 標籤來源 | 只認腳本的判定。不得宣稱自己沒驗證過的標籤,也不得用自己的判斷取代腳本結論 |
|
||||
| 非零退出 | 一律視為阻擋:原文轉述腳本訊息、停止該技能、該回合不做別的事 |
|
||||
| `unlock` | 不得用來繞過閘門。要不要解鎖是使用者的決定 |
|
||||
| 回報 | **每次都要回報**:階段、必要標籤、腳本從 transcript 讀到的實際模型 id、判定結果。通過與阻擋都要講——安靜通過看起來跟跳過檢查一樣,而判定搬進程式層的理由就是「宣稱有檢查」不可信 |
|
||||
| 退出 0 | 該階段已上鎖。到下一階段的閘門重新上鎖之前,同一階段內把模型換成不合格的,下一輪提示會被 sdlc-gate hook 以 exit 2 擋下 |
|
||||
| 上鎖時機 | 只在階段變換時上鎖。同一階段內逐項或逐專案跑時不重新上鎖 |
|
||||
Reference in New Issue
Block a user