feat(worktree): 實作階段動程式碼前先從來源分支建立 worktree

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-25 11:04:33 +08:00
co-authored by Claude Opus 5
parent 518e5140a4
commit 87af245d54
2 changed files with 60 additions and 5 deletions
+42
View File
@@ -37,6 +37,48 @@
- 新分支名稱要可讀且不覆蓋既有分支;本地或遠端已存在同名分支時,換一個時間戳或短 hash。 - 新分支名稱要可讀且不覆蓋既有分支;本地或遠端已存在同名分支時,換一個時間戳或短 hash。
- 切換或建立分支屬不可忽略的狀態變更,要在輸出中講清楚原因與結果分支名稱。 - 切換或建立分支屬不可忽略的狀態變更,要在輸出中講清楚原因與結果分支名稱。
## 實作一律在 worktree 內進行
`implement` 動任何程式碼之前,先從**分析頁記錄的來源分支**建立 git worktree。所有修改都在 worktree 內,主工作目錄的分支與工作區完全不動。
### 路徑
```
{工作目錄}/.worktree/{分析頁 HASH}/{repo}
```
- `{分析頁 HASH}`:`ANALYZE_{HASH}` 的 HASH 部分,不含 `ANALYZE_` 前綴。
- `{repo}`:存取庫名稱,不含 owner(`HP/WebService.Buy` → `WebService.Buy`)。不同 owner 的同名存取庫同時出現時,才改用 `{owner}-{repo}` 避免蓋掉,並在輸出中說明。
- 一份分析涉及多個存取庫時,每個存取庫各一個 worktree,並列在同一個 HASH 目錄下。
### 建立前先問分支怎麼處理
依 `jsc-ask:ask` 的決策樹詢問,每個選項標明影響範圍。固定兩個選項:
| 選項 | 指令 | 影響 |
| --- | --- | --- |
| 以來源分支為基準開新工作分支 | `git worktree add -b {工作分支} {路徑} {來源分支}` | commit 落在新分支,來源分支不動 |
| 直接簽出來源分支 | `git worktree add {路徑} {來源分支}` | commit 直接進來源分支;同一分支不能同時簽出於兩處 |
**不得自行預設**,也不得跳過詢問。
### 建立時的鐵則
- **分支名與路徑一律加引號**:來源分支可能含中文、空白或多層斜線(例如 `feat/一址通/查地址/完整版/P2`),不加引號會被切斷。
- 找不到該存取庫的本地 clone → **停下來問使用者路徑**,不自行 clone、不臆測位置。
- 目標路徑已存在 → 不覆蓋。先確認它是不是同一份工作的 worktree(`git worktree list`),是就沿用,不是就回報並停止。
- 把 `.worktree/` 加進該存取庫的 `.git/info/exclude`(不動使用者的 `.gitignore`,那是專案共用檔)。
- 建立後在輸出中明確列出:worktree 路徑、簽出的分支、來源分支。
### 移除時機
**PR 建立成功後自動移除**:`git worktree remove {路徑}`。
- 只有 `jsc-git:pr` 回報 PR 建立成功才移除;PR 失敗就保留,讓使用者能接手處理。
- worktree 內還有未提交變更時**不移除**,回報並停止——那些變更沒有進 PR,移除等於丟掉。
- 移除後順手 `git worktree prune` 清掉殘留記錄。
- 同一份分析的多個 worktree 全部移除後,若 `.worktree/{HASH}/` 已空就一併刪掉那層目錄。
## 不破壞既有工作 ## 不破壞既有工作
- 工作區有未提交變更時,先提醒使用者 commit 或備份,**絕不**強制丟棄。 - 工作區有未提交變更時,先提醒使用者 commit 或備份,**絕不**強制丟棄。
+18 -5
View File
@@ -1,6 +1,6 @@
--- ---
name: implement name: implement
description: SDLC implementation stage. Gate on capability tags enforced in code by sdlc-gate (implement requires coding), confirm the target branch before writing any file, then claim a ready work package from ANALYZE_CONTENTS with a work ticket and complete its TDD todos one by one, updating the wiki after every item. A delivery package confirms its content type (API document or user-defined) before its first todo. Ends with jsc-review code-review, then always asks which delivery-document format to produce (DELIVER_{HASH} wiki page or Gitea issue comment) before an optional MAINTAIN_CONTENTS entry. Use when analysis is done and code must be written; not for planning or analysis. description: SDLC implementation stage. Gate on capability tags enforced in code by sdlc-gate (implement requires coding), confirm the target branch before writing any file, then claim a ready work package from ANALYZE_CONTENTS with a work ticket, create a worktree from the analysis page's source branch under .worktree/{分析頁 HASH}/{repo}, and complete its TDD todos one by one inside it, updating the wiki after every item. A delivery package confirms its content type (API document or user-defined) before its first todo. Ends with jsc-review code-review, opens the PR and only then removes the worktree, asks which delivery-document format to produce (DELIVER_{HASH} wiki page or Gitea issue comment), and optionally registers the project in MAINTAIN_CONTENTS. Use when analysis is done and code must be written; not for planning or analysis.
--- ---
# implement # implement
@@ -29,18 +29,31 @@ All wiki reads and writes go through `jsc-gitea:wiki`.
2. Chose API 文件 → follow `references/deliver-formats.md`: all parameters listed (not just the main ones), each with name, type, required flag, example, data source and new-versus-existing status; sample values take real sources first and are labelled `真實:{來源}` or `推論:無來源`; **an existing endpoint must mark new versus old parameters both ways** — the status column (🆕 新增 / ⚠️ 變更 / ❌ 移除 / blank for untouched) and a `diff` code block for colour. HTML `style` attributes get filtered by the wiki, so never rely on them. 2. Chose API 文件 → follow `references/deliver-formats.md`: all parameters listed (not just the main ones), each with name, type, required flag, example, data source and new-versus-existing status; sample values take real sources first and are labelled `真實:{來源}` or `推論:無來源`; **an existing endpoint must mark new versus old parameters both ways** — the status column (🆕 新增 / ⚠️ 變更 / ❌ 移除 / blank for untouched) and a `diff` code block for colour. HTML `style` attributes get filtered by the wiki, so never rely on them.
3. Chose 由使用者輸入 → produce exactly what the user described; do not force the API document layout onto it. 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. 4. Record the confirmed type in the analysis page's 交付型別 column and save it before starting the todos.
7. List every open item of the work package and implement them **one at a time**: 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.
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.**
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.
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). - 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. - After each item, flip its `[ ]` to `[x]` on the analysis page and save to the wiki before starting the next item.
8. When all items are done, call `jsc-review:code-review` and wait for the review; on failure, fix and re-review until it passes. 9. When all items are done, call `jsc-review:code-review` and wait for the review; on failure, fix and re-review until it passes.
9. **Delivery document** — a finished work package is a delivery, so **always ask before producing it; never pick a format silently and never skip this step**: 10. **Open the PR, then remove the worktree** — in that order, never the reverse:
1. Call `jsc-git:pr` with the target branch confirmed in step 2. Commits come from inside the worktree.
2. **Only after `jsc-git:pr` reports the PR was created successfully**, run `git worktree remove {路徑}` for each worktree, then `git worktree prune`. PR creation failed → keep the worktree so the user can take over.
3. Uncommitted changes still inside a worktree → **do not remove it**; report and stop. Those changes never reached the PR, and removing would throw them away.
4. Once every worktree of this analysis is gone and `.worktree/{HASH}/` is empty, delete that directory too.
11. **Delivery document** — a finished work package is a delivery, so **always ask before producing it; never pick a format silently and never skip this step**:
1. Ask per `jsc-ask:ask` rules which format to produce. The options are fixed: **a `DELIVER_{HASH}` wiki page** or **a Gitea issue comment**. State the impact scope on each (the wiki page lives beside the plan and analysis pages; the issue comment reaches whoever follows that issue). 1. Ask per `jsc-ask:ask` rules which format to produce. The options are fixed: **a `DELIVER_{HASH}` wiki page** or **a Gitea issue comment**. State the impact scope on each (the wiki page lives beside the plan and analysis pages; the issue comment reaches whoever follows that issue).
2. Both formats use the same structure — `templates/deliver-page.md`, in Traditional Chinese. Only the destination differs. 2. Both formats use the same structure — `templates/deliver-page.md`, in Traditional Chinese. Only the destination differs.
3. Wiki page: write `DELIVER_{HASH}` through `jsc-gitea:wiki`, where `{HASH}` comes from `jsc-gitea/tools/hash-id` over `{owner}/{repo}` plus the work package number (for example `plugins/sdlc#WP-01`), so each work package gets its own page instead of overwriting the previous one. A new page is added to `DELIVER_CONTENTS` per `templates/deliver-contents.md`. 3. Wiki page: write `DELIVER_{HASH}` through `jsc-gitea:wiki`, where `{HASH}` comes from `jsc-gitea/tools/hash-id` over `{owner}/{repo}` plus the work package number (for example `plugins/sdlc#WP-01`), so each work package gets its own page instead of overwriting the previous one. A new page is added to `DELIVER_CONTENTS` per `templates/deliver-contents.md`.
4. Issue comment: confirm the issue number with the user (propose the one referenced by the work package or the PR; never guess), then post via `gitea/tools/gitea.sh api POST /repos/{owner}/{repo}/issues/{n}/comments` with the body passed in as a UTF-8 file — real newlines, never a literal `\n`. 4. Issue comment: confirm the issue number with the user (propose the one referenced by the work package or the PR; never guess), then post via `gitea/tools/gitea.sh api POST /repos/{owner}/{repo}/issues/{n}/comments` with the body passed in as a UTF-8 file — real newlines, never a literal `\n`.
5. Sample values follow the analysis page's 資料來源 column: `真實:{來源}` for real sources, `推論:無來源` for reasoned ones. Personal data never goes in — keep the field and format, drop the value. 5. Sample values follow the analysis page's 資料來源 column: `真實:{來源}` for real sources, `推論:無來源` for reasoned ones. Personal data never goes in — keep the field and format, drop the value.
6. Completion condition: the chosen format has actually been produced, and you have reported where it landed (wiki page name, or the comment URL). 6. Completion condition: the chosen format has actually been produced, and you have reported where it landed (wiki page name, or the comment URL).
10. Ask per `jsc-ask:ask` rules whether to register this project for maintenance: append to `MAINTAIN_CONTENTS` with `templates/maintain-contents.md`. Required: repository `{owner}/{repo}`, maintenance method, start date. Optional: end date (NULL = maintain forever), last-maintained time. 12. Ask per `jsc-ask:ask` rules whether to register this project for maintenance: append to `MAINTAIN_CONTENTS` with `templates/maintain-contents.md`. Required: repository `{owner}/{repo}`, maintenance method, start date. Optional: end date (NULL = maintain forever), last-maintained time.
## Rules ## Rules