Files
ISEP/docs/governance/worktree-placement.md
isep-hand 7cacfdcf11 一個 repo 只有一個資料夾:分身住 repo 裡面的 .worktrees/,收工由同一支閘收掉(inkstone/ISEP#147)
leo 2026-09-07:「一個 repo 只看得到一個資料夾」「禁止這樣產出一大堆資料夾」。
根因:line-needs-own-worktree.sh 教工人開在 repo 旁邊,「收工 remove」只寫在閘訊息裡、沒機制驗,
每條線留一份 ⇒ tech_projects/ 長出 ISEP-wt-117/InkStoneCo-wt-112…一排。規則在文字裡不在機器上。

- scripts/worktree(新):open/close/list/sweep 四個動詞。分身住 <repo>/.worktrees/<票 repo>-<N>
  (走 .git/info/exclude,不動被追蹤的檔);「推了沒」只有這一份判準(三態:有/沒有/問不到,
  問不到不當成沒推也不收);sweep 預設只列不動,--apply 只收「推了且乾淨」,--skip 是操作者點名。
- hooks/line-needs-own-worktree.sh:擋下時印 `scripts/worktree open`(絕對路徑,貼了就跑);
  同一支多掛 PostToolUse Agent|Task——從【工單】認出分身,推了收、沒推點名分支+路徑(exit 2),
  不 force、不刪。+0 支、+1 條(61 支/86 條,當場數的)。
- docs/governance/worktree-placement.md(新)+ principles 一行:禁令與閘互指。
- 測試:line-needs-own-worktree.test.sh 77→110(G 群:閘印的 open 那行原樣跑、旁邊不多任何東西;
  H 群:PostToolUse 推了收/沒推點名/安靜的方向);scripts/test-worktree.sh 42 條(七個分身的 fixture,
  名字照 leo 看到的那排)。舊閘跑新測試 90/110,紅的 20 條正是這次改到的行為。
- permissions-allow.json 加 worktree 四種形狀(出路在雲端被分類器擋就走不通)。
- README/plugin.json/hooks-inventory 的數字在這棵樹上實數:61 支、86 條、62 支腳本。

待總管定版(改了會被載入的東西)。沒碰 hooks/lib/mainline.py。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0178ef1fGw3XeZtpN7LaZrm4
2026-09-07 07:13:21 +00:00

71 lines
4.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 一個 repo 只有一個資料夾:分身住 `.worktrees/`,收工就被收(inkstone/ISEP#147
> leo 2026-09-07(兩則,一字不改):
> 「我看到的是一個 repo,你會產生大量的同一個頭不同尾巴的 repo,全部拆開就更亂了,
> 為什麼要產出新的 repo?這個 repo 的目的就是收納所有相關的內容,這樣散開造成凌亂,
> ISEP, Inkstoneco, Course Gen 這些都產出好多個資料夾,這要整理回去」
> 「另外要在 ISEP 裡寫明,禁止這樣產出一大堆資料夾」
## 規約(三句)
1. 🔴 **禁止在專案目錄旁邊產出分身資料夾。** `tech_projects/` 底下一個 repo 只能有一個資料夾;
`ISEP-wt-117``InkStoneCo-wt-112``course_gen-ticket-3-notes` 這種同頭不同尾的東西不准再長出來。
2. **一條線要隔離工作目錄,分身住 repo 裡面**`<repo>/.worktrees/<票的 repo 名>-<票號>`
Finder 看不到(點開頭)、`git status` 看不到(寫進 `.git/info/exclude`)、`git worktree list` 找得到。
3. **分身是借的,收工要還**:分支推上遠端且工作樹乾淨 ⇒ 收掉;沒推 ⇒ 點名分支與路徑,等人決定。
**絕不 force、絕不刪沒推的 commit。**
## 為什麼會長成那樣(根因,不是誰疏忽)
`hooks/line-needs-own-worktree.sh`inkstone/ISEP#109,08-29 立)擋下線在共用目錄切分支,教它
「開一份在 repo 旁邊、不要在 /tmp、收工時 `worktree remove`」。
那時比較的只有「旁邊 vs /tmp」——/tmp 會被系統清掉、登記簿說謊;旁邊的一份都沒掉。
**一份都沒掉,也一份都沒收**`remove` 那一步只寫在閘訊息裡,沒有任何機制驗。
每個工人留一份,`tech_projects/` 就長成那排。**規則在文字裡,不在機器上**
(同日 ISEP#109 comment 6629 是同一種病:出路寫在訊息裡,機器讀不到)。
## 機器上的兩端
| 端 | 在哪 | 做什麼 |
|---|---|---|
| 開 | `hooks/line-needs-own-worktree.sh`PreToolUse Bash | 擋下共用目錄裡的 checkout,印出 `scripts/worktree open …`(絕對路徑,貼了就能跑) |
| 收 | **同一支閘**多掛 PostToolUse `Agent\|Task` | 從派工單 `【工單】owner/repo#N` 認出分身名字,跑 `scripts/worktree close`:推了收、沒推點名(exit 2) |
| 工具 | `scripts/worktree` | `open``close``list``sweep` 四個動詞;「推了沒」只有這一份判準(三態:有/沒有/問不到,問不到不當成沒推) |
為什麼收的那一半不另開一支閘:教你開的和替你收的是同一件事的兩半,拆成兩支就又是「規則在兩個地方」
`countdown-guard.sh` 同一種形狀:注入與查核是一支閘掛兩個事件)。
為什麼掛 PostToolUse 不掛 SubagentStop:票號在派工單(Agent 的 `tool_input.prompt`)裡,SubagentStop 拿不到
`baton-handback-guard.sh` 檔頭那段實撞)。
## 工人怎麼用
```
python3 <plugin>/scripts/worktree open inkstone/ISEP#147 --repo <repo> -b feat/147-xxx # 開
cd <repo>/.worktrees/ISEP-147 # 在裡面做事
python3 <plugin>/scripts/worktree close inkstone/ISEP#147 --repo <repo> # 收(推了才收得掉)
```
忘了 `close` 也沒關係——線收工那一刻閘會替你跑;但**沒推的它不會替你收**,只會點名。
不要用 `git worktree add <repo>/../<repo>-wt-…` 這條老路;閘訊息已經不印它了。
## leo 在 Mac 上整理現場(一次)
```
python3 ~/.claude/plugins/cache/inkstone/isep/<版本>/scripts/worktree sweep ~/tech_projects # 只列,不動
python3 ~/.claude/plugins/cache/inkstone/isep/<版本>/scripts/worktree sweep ~/tech_projects --apply --skip course_gen
```
- 預設**只列不動**`--apply` 才收,而且只收「推了且乾淨」的。
- 沒推的、有未 commit 的、問不到遠端的、沒有任何 repo 登記它的:**全部列出來、一個都不動**,等他決定。
- `--skip <repo 名>` 是操作者點名不碰的 repo(09-07:`course_gen` 地端正在處理,列可以、不收不動)。
它是操作者的明示指令,不是判準——判準永遠是「這個目錄是不是某個 repo 的 worktree、分支推了沒、乾不乾淨」。
## 測試
- `hooks/tests/line-needs-own-worktree.test.sh` G 群(開在裡面、旁邊不多任何東西、閘印的那行原樣跑得動)
與 H 群(PostToolUse:推了收掉、沒推點名、沒工單/沒分身安靜)。
- `scripts/test-worktree.sh`:七個分身的 fixture(照 leo 09-07 看到的那排)跑 `sweep`——
dry-run 不動任何東西;`--apply` 只收已推的、`--skip` 的一根寒毛不動、沒推的印分支與路徑。