diff --git a/skills/herdr-issue/SKILL.md b/skills/herdr-issue/SKILL.md index 7c82c89..5de5716 100644 --- a/skills/herdr-issue/SKILL.md +++ b/skills/herdr-issue/SKILL.md @@ -7,6 +7,10 @@ description: "Run Gitea issues through Herdr: one Claude agent per issue in its 把 Gitea 議題交給 Herdr 裡的 Claude agent 實作。所有確定性的工作都在 `scripts/` 裡,你只在「要做決定」的時刻出手。腳本都要在該 repo 的 clone 裡執行;`S` 代表 `~/.claude/skills/herdr-issue/scripts`。 +## 使用者身分 + +Gitea 一律以 tea 的預設 login(`tea login list` 中 default 為 true 的那個)操作:`lib.sh` 會取出它並讓所有 tea 呼叫加上 `--login`,避免在 clone 裡 tea 依 remote URL 挑到別的帳號。`start.sh` 也會把該使用者的名稱與 email 設成 worktree 的 git commit 身分。要換人先 `tea login default `,或設 `HERDR_ISSUE_LOGIN`。 + ## 語言規則 本技能的所有回覆、提問、通知與輸出訊息一律使用繁體中文(程式碼、指令、識別字除外)。 diff --git a/skills/herdr-issue/scripts/lib.sh b/skills/herdr-issue/scripts/lib.sh index 70e0ca1..8d00082 100755 --- a/skills/herdr-issue/scripts/lib.sh +++ b/skills/herdr-issue/scripts/lib.sh @@ -11,6 +11,16 @@ SCRIPTS="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" die() { echo "herdr-issue: $*" >&2; exit 1; } +# tea 的預設使用者。在 clone 裡 tea 會依 remote URL 挑第一個符合的 login(可能不是預設的), +# 所以明確取 default 那個 login,所有 tea 呼叫都加 --login。可用 HERDR_ISSUE_LOGIN 覆寫。 +if [ -z "${HERDR_ISSUE_LOGIN:-}" ]; then + HERDR_ISSUE_LOGIN="$(tea login list --output json | python3 -c "import sys,json +print(next((l['name'] for l in json.load(sys.stdin) if str(l.get('default')).lower()=='true'),''))")" +fi +[ -n "$HERDR_ISSUE_LOGIN" ] || { echo "herdr-issue: tea 沒有預設 login,請先 tea login default " >&2; exit 1; } +export HERDR_ISSUE_LOGIN +tea() { command tea "$1" --login "$HERDR_ISSUE_LOGIN" "${@:2}"; } + # 從 stdin 讀 JSON,執行 python 片段,d 是解析後的物件。 jq_py() { python3 -c "import sys,json def find(o,k): diff --git a/skills/herdr-issue/scripts/prompt.txt b/skills/herdr-issue/scripts/prompt.txt index 96abd17..f26aadf 100644 --- a/skills/herdr-issue/scripts/prompt.txt +++ b/skills/herdr-issue/scripts/prompt.txt @@ -3,15 +3,16 @@ 你在分支 issue-{N} 的 worktree 裡,從 origin/main 建立,請在這裡實作,不要另外建 worktree。 {RESUME} 規則: -0. 所有回覆、commit 訊息、PR 標題與描述、議題留言一律使用繁體中文(程式碼與指令除外)。 +0. 一律以 tea 的預設使用者 {LOGIN} 操作 Gitea(tea 指令加 --login {LOGIN}),git commit 身分已設為同一人。 + 所有回覆、commit 訊息、PR 標題與描述、議題留言一律使用繁體中文(程式碼與指令除外)。 1. 議題的代辦項目是內文 Acceptance criteria 的核取方塊。每完成一項就執行 {S}/tick.sh {REPO} {N} <第幾項>(從第一個核取方塊數起,已勾的也算) 它會重新讀取最新內文再改,不要自己用 tea issues edit 重寫整段。 2. 全部完成後推送分支並建立 PR 回 main: - tea pulls create --repo {REPO} --base main --head issue-{N} --title "<標題>" --description "<摘要> + tea pulls create --login {LOGIN} --repo {REPO} --base main --head issue-{N} --title "<標題>" --description "<摘要> Closes #{N}" 3. 然後在背景執行 {S}/pr-wait.sh {REPO} {N},它會在 PR 有衝突、被關閉或合併時結束並印出原因: - conflict:git fetch origin && git merge origin/main,用 /mattpocock-skills:resolving-merge-conflicts 解決,跑測試,推送,再執行一次 pr-wait.sh。 - - closed:tea issues close --repo {REPO} {N},結束。 + - closed:tea issues close --login {LOGIN} --repo {REPO} {N},結束。 - merged 或 issue-closed:結束。 diff --git a/skills/herdr-issue/scripts/ready.py b/skills/herdr-issue/scripts/ready.py index 1d17307..f7b515a 100755 --- a/skills/herdr-issue/scripts/ready.py +++ b/skills/herdr-issue/scripts/ready.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """列出可執行的議題。輸入:open.json agents.json tabs.json owner/repo 阻擋關係只認 Gitea 原生 issue dependencies(tea api),不看議題內文。""" -import json, re, subprocess, sys +import os, json, re, subprocess, sys open_issues = json.load(open(sys.argv[1])) agents = json.load(open(sys.argv[2])) @@ -33,7 +33,7 @@ for t in find(tabs, "tabs") or []: def open_blockers(n): """擋住 #n 的 open 依賴。tea api 遇到 HTTP 錯誤仍 exit 0,所以回應不是陣列就當失敗,整個停下。""" - raw = subprocess.run(["tea", "api", "--repo", repo, f"/repos/{{owner}}/{{repo}}/issues/{n}/dependencies"], + raw = subprocess.run(["tea", "api", "--login", os.environ["HERDR_ISSUE_LOGIN"], "--repo", repo, f"/repos/{{owner}}/{{repo}}/issues/{n}/dependencies"], capture_output=True, text=True).stdout try: d = json.loads(raw) except Exception: d = None diff --git a/skills/herdr-issue/scripts/start.sh b/skills/herdr-issue/scripts/start.sh index df779c5..6db3fa3 100755 --- a/skills/herdr-issue/scripts/start.sh +++ b/skills/herdr-issue/scripts/start.sh @@ -56,8 +56,15 @@ if [ -f "$START_ERR" ]; then die "agent 啟動失敗,已回滾" fi +# git 身分:與 tea 預設使用者一致(只設在這個 worktree,不動 clone 的設定) +GIT_USER="$(command tea login list --output json | jq_py "print(next((l['user'] for l in d if l['name']=='$HERDR_ISSUE_LOGIN'),''))")" +GIT_EMAIL="$(tea api "/user" | jq_py 'print(d.get("email") or "")' 2>/dev/null || true)" +git -C "$CLONE" config extensions.worktreeConfig true +git -C "$WT" config --worktree user.name "$GIT_USER" +[ -z "$GIT_EMAIL" ] || git -C "$WT" config --worktree user.email "$GIT_EMAIL" + if $RESUMED; then RESUME_LINE="分支已有先前進度,先看 git log 和議題核取方塊再接續。"; else RESUME_LINE=""; fi -PROMPT="$(sed -e "s|{LINK}|$LINK|g" -e "s|{REPO}|$REPO|g" -e "s|{N}|$N|g" -e "s|{S}|$SCRIPTS|g" -e "s|{RESUME}|$RESUME_LINE|" "$SCRIPTS/prompt.txt")" +PROMPT="$(sed -e "s|{LINK}|$LINK|g" -e "s|{REPO}|$REPO|g" -e "s|{N}|$N|g" -e "s|{S}|$SCRIPTS|g" -e "s|{LOGIN}|$HERDR_ISSUE_LOGIN|g" -e "s|{RESUME}|$RESUME_LINE|" "$SCRIPTS/prompt.txt")" # 送出後必須觀察到 agent 進入 working 或 blocked;否則 Herdr 回非 0(agent_prompt_stalled、timeout、agent_blocked 等)。 PROMPT_ERR="$(mktemp)"