7cacfdcf11
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
51 lines
4.5 KiB
JSON
51 lines
4.5 KiB
JSON
{
|
||
"_what": "Claude Code 權限白名單(permissions.allow)的唯一清單——本機與雲端都從這裡讀,不各養一份(inkstone/ISEP#130)",
|
||
"_why": [
|
||
"leo 09-07 親手把四個 Gitea 正門工具(ticket/mainline/gate-ok/gitea-pr-merge)加進本機 InkStoneCo/.claude/settings.json,auto mode 的分類器才不擋。",
|
||
"雲端 session 沒有那四條,同樣的動作照樣被擋(09-04 progress-guard run log:permission_denials=6)。",
|
||
"薄殼 repo(GitHub)要 D20 開閘才推得動 ⇒ 白名單住 ISEP,`scripts/settings-allow-sync` 開工時寫進那台機器的 ~/.claude/settings.json。",
|
||
"以後加規則只改這個檔、出一版,雲端下一趟就有。",
|
||
"inkstone/ISEP#137:09-07 雲端對 stage 的三種寫入(`npx wrangler secret put`/`stage-deploy-artifacts.py`/curl POST 到 arcrun-yuga3bse)全被分類器擋——複合指令與任意 curl 對不上任何一條前綴。收成 `scripts/stage`(secret/api 兩個子命令,只寫 stage、值只從環境變數名讀)四種形狀,外加 Arcrun 自己那支 `scripts/stage-deploy-artifacts.py`(它已寫死只認 youlin 帳號 ID、不收 --account/--token)從 Arcrun repo 根目錄的相對形狀。不放 `Bash(npx *)`/`Bash(wrangler *)`/`Bash(curl *)`。",
|
||
"inkstone/ISEP#67:SessionStart 信標印的補法是 `python3 <plugin root>/scripts/release-ship vX.Y.Z`——那一行在雲端要是被分類器擋,出路就走不通(閘的價值是「擋下來+給一條走得通的路」)。release-ship 只 POST 一件事(建 release,tag 與 release 名寫死從 Gitea 讀);release-check 純讀。",
|
||
"inkstone/ISEP#147:worktree 閘印出來的出路是 `python3 <plugin>/scripts/worktree open …`/`close …`,收工那一半也是同一支工具;出路在雲端被分類器擋就是走不通的路(閘的價值是「擋下來+給一條走得通的路」)。它只碰 git worktree,不打網路寫入。"
|
||
],
|
||
"_rules": [
|
||
"開頭的 `~` 由 settings-allow-sync 換成那台機器的家目錄(本機 /Users/…、雲端 /root),其餘一字不改。",
|
||
"只放「正門工具」:每一條都要說得出它是哪支腳本的哪種呼叫形狀。不放 Bash(python3 *) 這種整類放行。",
|
||
"同一支工具幾種呼叫形狀就幾條(快取路徑/$CLAUDE_PLUGIN_ROOT/相對路徑)——權限規則是逐條完全比對,形狀差一個字就落在規則之外(scripts/gate-ok 檔頭記過這一課)。",
|
||
"別的 repo 的正門工具也可以進來(例 Arcrun 的 `scripts/stage-deploy-artifacts.py`),條件一樣:那支腳本自己把「只打哪台」寫死在程式裡,本清單放的是它從那個 repo 根目錄跑的相對形狀。"
|
||
],
|
||
"allow": [
|
||
"Bash(python3 ~/.claude/plugins/cache/inkstone/isep/*/scripts/ticket *)",
|
||
"Bash(python3 \"$CLAUDE_PLUGIN_ROOT/scripts/ticket\" *)",
|
||
"Bash(python3 \"$CLAUDE_PLUGIN_ROOT\"/scripts/ticket *)",
|
||
"Bash(python3 scripts/ticket *)",
|
||
"Bash(python3 ~/.claude/plugins/cache/inkstone/isep/*/scripts/mainline *)",
|
||
"Bash(python3 \"$CLAUDE_PLUGIN_ROOT/scripts/mainline\" *)",
|
||
"Bash(python3 \"$CLAUDE_PLUGIN_ROOT\"/scripts/mainline *)",
|
||
"Bash(python3 scripts/mainline *)",
|
||
"Bash(bash ~/.claude/plugins/cache/inkstone/isep/*/scripts/gate-ok *)",
|
||
"Bash(bash \"$CLAUDE_PLUGIN_ROOT/scripts/gate-ok\" *)",
|
||
"Bash(bash \"$CLAUDE_PLUGIN_ROOT\"/scripts/gate-ok *)",
|
||
"Bash(bash scripts/gate-ok *)",
|
||
"Bash(bash scripts/gitea-pr-merge.sh *)",
|
||
"Bash(python3 ~/.claude/plugins/cache/inkstone/isep/*/scripts/stage *)",
|
||
"Bash(python3 \"$CLAUDE_PLUGIN_ROOT/scripts/stage\" *)",
|
||
"Bash(python3 \"$CLAUDE_PLUGIN_ROOT\"/scripts/stage *)",
|
||
"Bash(python3 scripts/stage *)",
|
||
"Bash(python3 scripts/stage-deploy-artifacts.py *)",
|
||
"Bash(python3 ~/.claude/plugins/cache/inkstone/isep/*/scripts/release-ship *)",
|
||
"Bash(python3 \"$CLAUDE_PLUGIN_ROOT/scripts/release-ship\" *)",
|
||
"Bash(python3 \"$CLAUDE_PLUGIN_ROOT\"/scripts/release-ship *)",
|
||
"Bash(python3 scripts/release-ship *)",
|
||
"Bash(python3 ~/.claude/plugins/cache/inkstone/isep/*/scripts/release-check *)",
|
||
"Bash(python3 \"$CLAUDE_PLUGIN_ROOT/scripts/release-check\" *)",
|
||
"Bash(python3 \"$CLAUDE_PLUGIN_ROOT\"/scripts/release-check *)",
|
||
"Bash(python3 scripts/release-check *)",
|
||
"Bash(python3 ~/.claude/plugins/cache/inkstone/isep/*/scripts/worktree *)",
|
||
"Bash(python3 \"$CLAUDE_PLUGIN_ROOT/scripts/worktree\" *)",
|
||
"Bash(python3 \"$CLAUDE_PLUGIN_ROOT\"/scripts/worktree *)",
|
||
"Bash(python3 scripts/worktree *)"
|
||
]
|
||
}
|