From 543fd8c6956731dfc34ab0842c7177400f0b6512 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Tue, 25 Aug 2026 11:10:55 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=88=86=E6=94=AF=E5=9F=BA=E6=BA=96):=20?= =?UTF-8?q?=E5=8F=83=E8=80=83=E8=88=87=E4=BE=86=E6=BA=90=E5=88=86=E6=94=AF?= =?UTF-8?q?=E4=B8=80=E5=BE=8B=E5=8F=96=E9=81=A0=E7=AB=AF=20origin=EF=BC=8C?= =?UTF-8?q?=E5=8B=95=E4=BD=9C=E5=89=8D=E5=85=88=20fetch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5 (1M context) --- references/branch.md | 30 +++++++++++++++++++++++++----- skills/analyze/SKILL.md | 8 ++++---- skills/implement/SKILL.md | 8 ++++---- skills/maintain/SKILL.md | 2 +- templates/analyze-page.md | 2 +- 5 files changed, 35 insertions(+), 15 deletions(-) diff --git a/references/branch.md b/references/branch.md index db6787a..c90eb77 100644 --- a/references/branch.md +++ b/references/branch.md @@ -2,6 +2,24 @@ 分析要讀對分支的程式碼,實作要寫進對的分支。兩件事都不能從「目前 checkout 的分支」推定使用者的意圖。 +## 總則:一律以遠端為準,不吃本地分支 + +SDLC 各階段引用的參考分支與來源分支,**一律指遠端的 `origin/{分支}`**。本地分支不可作為基準。 + +理由:本地分支可能落後遠端、可能有沒推上去的 commit、也可能是別的工作留下的狀態。以本地為基準,分析會對著過時的程式碼做,實作會從錯誤的起點長出來,而且錯了不會有任何徵兆。 + +| 項目 | 規則 | +| --- | --- | +| 動作之前 | 先 `git fetch --prune origin`。**沒 fetch 就用 `origin/{分支}` 等於用快取**,遠端追蹤參照可能已經過時,連分支被刪掉都看不出來 | +| 列分支 | `git branch -r`,不看 `git branch` | +| 基準與比對 | 一律寫 `origin/{分支}`,例如 `git rev-list --count origin/master..origin/develop` | +| 建立 worktree | 從 `origin/{來源分支}` 建,不從本地同名分支建 | +| 判定預設分支 | `refs/remotes/origin/HEAD`(見〔判定遠端預設分支〕) | + +**本地與遠端不一致時一律停下回報**,不自行 `pull`、不自行 `reset`、不自行切換。要不要同步是使用者的決定。 + +`origin` 以外的遠端名稱(例如 `upstream`):先問使用者以哪個遠端為準,不臆測。 + ## 先確認,再動工 | 階段 | 要確認的分支 | 確認時機 | @@ -11,7 +29,7 @@ 確認方式: -1. 先把事實攤開:目前分支、工作區是否乾淨、遠端有哪些分支(`git branch -r`)、下節判定出的遠端預設分支。 +1. 先 `git fetch --prune origin`,再把事實攤開:目前分支、工作區是否乾淨、遠端有哪些分支(`git branch -r`,不看本地)、下節判定出的遠端預設分支。 2. 依 `jsc-ask:ask` 的決策樹詢問,每個選項都要標明影響範圍。分析錯分支會產出對不上程式碼的工作包;目標分支錯了則 PR 會開到錯的地方。 3. 把確認結果寫進產出(分析頁的來源分支欄、PR 的目標分支),後續步驟一律沿用同一個答案,不再自行改判。 4. 使用者沒回答就**不預設** `develop`/`master`;預設值只在使用者明確同意後才成立。 @@ -28,18 +46,20 @@ `analyze` 是 logic-only 階段: +- **工作目錄的 HEAD 必須與 `origin/{來源分支}` 指向同一個 commit**。落後、超前或分歧都代表讀到的不是遠端現況——停下來回報差距(`git rev-list --left-right --count origin/{來源分支}...HEAD`),請使用者自己處理。 - 需要換分支才能讀到正確現況時,**停下來請使用者自己切換**。 - 不代為 `switch`、不 `stash`、不動工作區、不建分支。 ## 實作階段的分支選擇 +- 判斷同名與否,兩邊都用遠端的分支名(`origin/{來源分支}` 與 `origin/{目標分支}`)。 - **只有來源分支與目標分支同名時才開新的工作分支**:同名就不可在該分支上直接 commit,改從已更新到最新的目標分支建立新工作分支,後續操作都以新分支為準。不同名就在目前分支處理。 - 新分支名稱要可讀且不覆蓋既有分支;本地或遠端已存在同名分支時,換一個時間戳或短 hash。 - 切換或建立分支屬不可忽略的狀態變更,要在輸出中講清楚原因與結果分支名稱。 ## 實作一律在 worktree 內進行 -`implement` 動任何程式碼之前,先從**分析頁記錄的來源分支**建立 git worktree。所有修改都在 worktree 內,主工作目錄的分支與工作區完全不動。 +`implement` 動任何程式碼之前,先 `git fetch --prune origin`,再從**分析頁記錄的來源分支的遠端版本**(`origin/{來源分支}`)建立 git worktree。所有修改都在 worktree 內,主工作目錄的分支與工作區完全不動。 ### 路徑 @@ -57,8 +77,8 @@ | 選項 | 指令 | 影響 | | --- | --- | --- | -| 以來源分支為基準開新工作分支 | `git worktree add -b {工作分支} {路徑} {來源分支}` | commit 落在新分支,來源分支不動 | -| 直接簽出來源分支 | `git worktree add {路徑} {來源分支}` | commit 直接進來源分支;同一分支不能同時簽出於兩處 | +| 以來源分支為基準開新工作分支 | `git worktree add -b {工作分支} {路徑} "origin/{來源分支}"` | commit 落在新分支,來源分支不動 | +| 直接簽出來源分支 | `git worktree add --track -b {來源分支} {路徑} "origin/{來源分支}"` | 建立追蹤遠端的本地分支再簽出;本地已存在同名分支時指令會失敗,此時先確認它與遠端一致才可改用 `git worktree add {路徑} {來源分支}`,不一致就停下回報 | **不得自行預設**,也不得跳過詢問。 @@ -68,7 +88,7 @@ - 找不到該存取庫的本地 clone → **停下來問使用者路徑**,不自行 clone、不臆測位置。 - 目標路徑已存在 → 不覆蓋。先確認它是不是同一份工作的 worktree(`git worktree list`),是就沿用,不是就回報並停止。 - 把 `.worktree/` 加進該存取庫的 `.git/info/exclude`(不動使用者的 `.gitignore`,那是專案共用檔)。 -- 建立後在輸出中明確列出:worktree 路徑、簽出的分支、來源分支。 +- 建立後在輸出中明確列出:worktree 路徑、簽出的分支、來源分支,以及 `origin/{來源分支}` 當下的 commit sha——那是這次實作的起點,要能事後追。 ### 移除時機 diff --git a/skills/analyze/SKILL.md b/skills/analyze/SKILL.md index 6554ff1..899488f 100644 --- a/skills/analyze/SKILL.md +++ b/skills/analyze/SKILL.md @@ -19,14 +19,14 @@ All wiki reads and writes go through `jsc-gitea:wiki`. 3. **Never claim a capability tag you have not verified with that script**, and never substitute your own judgement for its verdict. Non-zero exit = blocked: relay the script's message verbatim, stop the skill, do nothing else this turn. Do not run `unlock` to get past the gate; only the user may decide that. 4. Exit 0 means the stage is locked. From now until the next stage's gate runs, the sdlc-gate hook blocks every prompt whose model stops satisfying the tags. 2. **Confirm the source branch** — the branch whose code counts as the current state: - 1. Report the working directory's current branch, plus the remote branches available (`git branch -r`) and whether the working tree is clean. + 1. Run `git fetch --prune origin` first — without it, every `origin/...` reference is stale cache. Then report the working directory's current branch, the **remote** branches available (`git branch -r`; never `git branch`) and whether the working tree is clean. 2. Ask per `jsc-ask:ask` rules which branch the analysis reads from; state the impact scope on every option (analysing the wrong branch produces work packages for code that does not exist). - 3. When the chosen branch is not the current one, **stop and ask the user to switch**. This stage never switches branches, never stashes, and never touches the working tree — rules in `references/branch.md`. - 4. Record the confirmed branch and its head sha on the analysis page. Completion condition: the user has confirmed the branch explicitly; never infer it from the current checkout alone. + 3. **The current state is always the remote branch `origin/{來源分支}`, never the local one.** The working directory's HEAD must point at the same commit as `origin/{來源分支}`; behind, ahead or diverged all mean you would be analysing code that is not what the remote holds. Report the gap (`git rev-list --left-right --count origin/{來源分支}...HEAD`) and stop — this stage never switches branches, never stashes, never pulls and never touches the working tree. Rules in `references/branch.md`. + 4. Record the confirmed branch and the head sha **of `origin/{來源分支}`** on the analysis page. Completion condition: the user has confirmed the branch explicitly; never infer it from the current checkout alone. 3. Read `PLAN_CONTENTS` via `jsc-gitea:wiki` for plans whose status is the literal 「未分析」 (name and HASH), and read `ANALYZE_CONTENTS` for existing analyses. 4. Let the user choose per `jsc-ask:ask` rules: **extend an existing analysis** or **analyze a new plan**. State the impact scope on every option. 5. Analyze the plan page's user stories one by one against the **current state**, **questioning until consensus** per `references/consensus.md` (the single authority for both planning and analysis): every answer produces the next question, and consensus needs both no output-changing unknown **and** the user's explicit confirmation. Never assume a missing detail, and never start the WBS while any item is still open. Current state means: - 1. Every file in the working directory, on the branch confirmed in step 2. + 1. Every file in the working directory, at the commit `origin/{來源分支}` points to (verified in step 2). 2. **Reuse existing methods and endpoints whenever possible**: - Check the `REPO_{HASH}` inventory page first. Re-inventory when the feature or endpoint is missing, or when the recorded commit sha differs from the current one. - Re-inventory **MUST run as a sub agent**: analyze the repository's features and endpoints, attach the current commit sha, write back to `REPO_{HASH}` with `templates/repo-page.md`, and update `REPO_CONTENTS` per `templates/repo-contents.md`. diff --git a/skills/implement/SKILL.md b/skills/implement/SKILL.md index 5286232..ad481f8 100644 --- a/skills/implement/SKILL.md +++ b/skills/implement/SKILL.md @@ -16,7 +16,7 @@ All wiki reads and writes go through `jsc-gitea:wiki`. 3. **Never claim a capability tag you have not verified with that script**, and never substitute your own judgement for its verdict. Non-zero exit = blocked: relay the script's message verbatim, stop the skill, do nothing else this turn. Do not run `unlock` to get past the gate; only the user may decide that. 4. Exit 0 means the stage is locked. From now until the next stage's gate runs, the sdlc-gate hook blocks every prompt whose model stops satisfying the tags. 2. **Confirm the target branch** — do this **before writing any file**: - 1. Report the current branch, whether the working tree is clean, and which of `origin/develop` / `origin/master` exist, plus the remote default branch resolved per `references/branch.md`. + 1. Run `git fetch --prune origin` first — every `origin/...` reference is stale cache without it. Then report the current branch, whether the working tree is clean, which of `origin/develop` / `origin/master` exist, and the remote default branch resolved per `references/branch.md`. **Branches are always the remote ones; local branches are never the basis.** 2. Ask per `jsc-ask:ask` rules which branch this work merges into; state the impact scope on every option (the answer decides the PR target and, when it collides with the current branch, forces a new working branch). 3. Uncommitted changes in the working tree → warn first and let the user commit or back them up; never discard them. 4. Apply `references/branch.md` to the confirmed target: source branch and target branch sharing a name means creating a new working branch instead of committing on the target; report the resulting branch name. @@ -30,13 +30,13 @@ All wiki reads and writes go through `jsc-gitea:wiki`. 3. Chose 由使用者輸入 → produce exactly what the user described; do not force the API document layout onto it. 4. Record the confirmed type in the analysis page's 交付型別 column and save it before starting the todos. 7. **Create the worktree — before touching any code**. Full rules in `references/branch.md`: - 1. Read the **source branch** and the repositories involved from the analysis page. Every code change happens inside the worktree; the main working directory's branch and working tree stay untouched. + 1. Run `git fetch --prune origin`, then read the **source branch** and the repositories involved from the analysis page. The worktree is built from `origin/{來源分支}` — **never from a local branch of the same name**, which may be behind, ahead or diverged. Every code change happens inside the worktree; the main working directory's branch and working tree stay untouched. 2. Path: `{工作目錄}/.worktree/{分析頁 HASH}/{repo}` — the HASH without the `ANALYZE_` prefix, the repo name without its owner. One worktree per repository, all under the same HASH directory. - 3. **Ask per `jsc-ask:ask` rules how to handle the branch**, with the two fixed options: create a new working branch off the source branch (`git worktree add -b {工作分支} {路徑} {來源分支}`), or check the source branch out directly (`git worktree add {路徑} {來源分支}`). State the impact scope on each. **Never assume, never skip the question.** + 3. **Ask per `jsc-ask:ask` rules how to handle the branch**, with the two fixed options: create a new working branch off the remote source branch (`git worktree add -b {工作分支} {路徑} "origin/{來源分支}"`), or check the source branch out with remote tracking (`git worktree add --track -b {來源分支} {路徑} "origin/{來源分支}"`). State the impact scope on each. **Never assume, never skip the question.** 4. **Quote every branch name and path**: source branches carry Chinese characters, spaces and multiple slashes (for example `feat/一址通/查地址/完整版/P2`), and an unquoted argument gets split. 5. No local clone of that repository → stop and ask the user for its path; never clone on your own initiative and never guess the location. 6. Add `.worktree/` to that repository's `.git/info/exclude` — never edit the user's shared `.gitignore`. - 7. Report the worktree path, the checked-out branch and the source branch. Completion condition: every involved repository has a worktree and you have reported all of them. + 7. Report the worktree path, the checked-out branch, the source branch and the commit sha `origin/{來源分支}` pointed at — that sha is this implementation's starting point and must stay traceable. Completion condition: every involved repository has a worktree and you have reported all of them. 8. List every open item of the work package and implement them **one at a time**, **inside the worktree**: - Follow the TDD loop: red before green, one slice at a time; rules and anti-patterns in `references/tdd.md` (refactoring belongs to the review stage). - After each item, flip its `[ ]` to `[x]` on the analysis page and save to the wiki before starting the next item. diff --git a/skills/maintain/SKILL.md b/skills/maintain/SKILL.md index 92404e3..d0e96f7 100644 --- a/skills/maintain/SKILL.md +++ b/skills/maintain/SKILL.md @@ -17,7 +17,7 @@ All wiki reads and writes go through `jsc-gitea:wiki`. 4. Exit 0 means the stage is locked. Run this gate only when the stage changes; inside the maintenance stage the lock already covers every project, so never re-gate between projects. 2. Read `MAINTAIN_CONTENTS` via `jsc-gitea:wiki` and filter projects **still inside their maintenance window**: start date ≤ today, and (end date is NULL or ≥ today). 3. Every project **MUST run as a sub agent** with this flow: - 1. Switch the project to the `develop` branch, falling back to `master`, and pull to latest. + 1. Run `git fetch --prune origin`, then switch the project to `develop`, falling back to `master`, and bring it up to `origin/{該分支}` — the remote is the basis, never the local branch. Local and remote diverged → report and skip that project; never `pull --rebase`, `reset` or discard anything on your own. 2. Propose **at least five** maintenance methods and apply the ones that fit the project, for example: - dependency updates (reuse `jsc-pkg:pkg-update`) - security vulnerability scan and patching diff --git a/templates/analyze-page.md b/templates/analyze-page.md index eb8240c..5aa68bc 100644 --- a/templates/analyze-page.md +++ b/templates/analyze-page.md @@ -7,7 +7,7 @@ - HASH:`{HASH}` - 對應計畫:[PLAN_{HASH}]({PLAN 頁絕對網址}) - 存取庫:`{owner}/{repo}` -- 來源分支:`{使用者確認的分支}`(head sha:`{sha}`) +- 來源分支:`origin/{使用者確認的分支}`(head sha:`{sha}`,取自遠端) - 狀態:未完成 - 建立時間:{yyyy-MM-dd HH:mm:ss}