閘教的那條出路要真的走得通(inkstone/ISEP#112)
comment-carries-task-guard 擋下留言時教人跑 `scripts/ticket subtask …`,
而那一行跑不動。兩個獨立的原因,各自都足以害死它:
① 相對路徑對「貼上去那個人的 cwd」解析。總管的 cwd 是 InkStoneCo/,
那裡的 scripts/ticket 是停在 08-27 之前的舊複本(grep -c subtask → 0),
照著貼只印出它「四個動詞」的說明然後 exit 0。
② 用法是手抄的第二份,而它已經漂了:寫了 --assign 卻沒有 --next,
正本會因為「指派了人卻沒寫 --next」直接擋下(exit 2,在打 API 之前)。
修法是拿掉可以漂的那一格,不是把兩份對齊一次:
- 路徑 scripts/ticket 的 self_path()(__file__ 的絕對路徑)
⇒ 印指令的人與跑指令的人是同一個檔案
- 用法 USAGE / usage_text() 一份,閘去 `ticket usage subtask --example` 現要
- 內文模板 body_template() 由 REQUIRED_SECTIONS 現生,跟檢查同源
新增動詞 `ticket usage <verb> [--example] [--parent] [--draft]`。
閘的訊息改成整塊可貼可跑:腳本絕對路徑、母票已填、內文草稿附在同一塊裡,
只剩標題/目標/驗收條件三格是機器不可能知道的。
正本叫不動時 fail-open 的只有「訊息內容」(只指路,不補一份手抄用法),
擋不擋不受影響。
測試 scripts/test-comment-carries-task-guard.sh 22 → 29 條。
新增的 ⑮–㉑ 驗的是「出路走不走得通」,不是「有沒有擋」——
⑱ 把閘 stderr 裡那塊指令原樣抽出來、只填三格、真的執行一次,
離開碼必須是 1(走到網路才停);是 2 就代表這個病復發。
六個變異全部驗過會紅(相對路徑/閘自己抄用法/--assign 沒配 --next/
模板寫死少一段/fallback 補回手抄用法)。
版本:待總管定版(plugin update 比的是版本號不是內容)。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SP7DiGMfSkWjZ15CHMbPFE
This commit is contained in:
@@ -103,10 +103,64 @@ WARNED="/tmp/.comment-task-guard-warned-$SID"
|
||||
[ -f "$WARNED" ] && exit 0 # 同一 session 只擋一次,不鬼打牆
|
||||
date +%s > "$WARNED"
|
||||
|
||||
cat >&2 <<EOF
|
||||
# ── 出路要真的走得通(inkstone/ISEP#112)────────────────────────────────
|
||||
#
|
||||
# 這支閘 08-27 上線時印的是 `scripts/ticket subtask …`,而那一行**跑不動**,
|
||||
# 兩個獨立的原因(2026-08-31 實測,各自都足以害死它):
|
||||
#
|
||||
# ① 相對路徑對「貼上去那個人的 cwd」解析。總管的 cwd 是 `InkStoneCo/`,
|
||||
# 那裡的 `scripts/ticket` 是舊複本(`grep -c subtask` → 0),
|
||||
# 照著貼只會印出它「四個動詞」的說明然後 exit 0。
|
||||
# ② 用法是**手抄的第二份**,而它已經漂了:寫了 `--assign` 卻沒有 `--next`,
|
||||
# 而正本會因為「指派了人卻沒寫 --next」直接擋下。
|
||||
#
|
||||
# 票上的判決:「**當它教的做法不存在,它就從『幫你』變成『擋你』**——
|
||||
# 而且被擋的人當下正在做別的事,最可能的反應是找個理由繞過去。」
|
||||
#
|
||||
# 🔴 所以這裡**不准再抄一份用法**。整塊指令去正本要:
|
||||
# "$TICKET" usage subtask --example --parent <母票> --draft <草稿路徑>
|
||||
# 正本印的路徑是它自己的 `__file__`(絕對路徑)⇒ 印指令的人與跑指令的人
|
||||
# 是同一個檔案,沒有第二種可能。
|
||||
ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
|
||||
TICKET="$ROOT/scripts/ticket"
|
||||
|
||||
# 母票是誰:兩條路都認(走正門 `ticket say`,或直接打 API)。認不出來就留 <母票 …>,
|
||||
# 正本那邊會照樣印出可讀的樣板——**寧可少填一格,不要猜錯一張票**。
|
||||
PARENT=$(printf '%s' "$CMD" | python3 -c '
|
||||
import re, sys
|
||||
c = sys.stdin.read()
|
||||
m = re.search(r"/repos/([\w.-]+)/([\w.-]+)/issues/(\d+)/comments", c)
|
||||
if m:
|
||||
print("%s/%s#%s" % m.groups()); raise SystemExit
|
||||
m = re.search(r"\bticket\s+say\s+([\w.-]+)/([\w.-]+)#(\d+)", c)
|
||||
if m:
|
||||
print("%s/%s#%s" % m.groups())
|
||||
' 2>/dev/null)
|
||||
|
||||
DRAFT="/tmp/isep-subtask-$SID.md"
|
||||
EXAMPLE=$(python3 "$TICKET" usage subtask --example \
|
||||
${PARENT:+--parent "$PARENT"} --draft "$DRAFT" 2>/dev/null) || EXAMPLE=""
|
||||
MORE=$(python3 "$TICKET" usage subtask 2>/dev/null) || MORE=""
|
||||
|
||||
# fail-open 的**訊息**(不是閘):正本叫不動時仍然要擋,但不准在這裡補一份手抄用法
|
||||
# ——那樣就把剛拔掉的那個副本裝回來了。只指路,指到唯一那一份。
|
||||
LEAD="整段複製貼上就跑得動。腳本是絕對路徑、母票已經填好、必填段落已經在草稿裡,
|
||||
只剩三格是機器不可能知道的:標題、目標、驗收條件——改完那三格再送。
|
||||
(下面這塊**不要縮排**,\`<<'MD'\` 的結束標記要頂在行首。)"
|
||||
if [ -z "$EXAMPLE" ]; then
|
||||
LEAD="把它長成子票。**這台機器叫不動正本,所以下面只給路、不給整塊指令**
|
||||
——這裡刻意不補一份手抄的用法,那份副本正是 inkstone/ISEP#112 拔掉的東西。"
|
||||
EXAMPLE="python3 $TICKET usage subtask --example"
|
||||
MORE=""
|
||||
fi
|
||||
|
||||
# 🔴 訊息一律用 `<<'EOF'`(標記加引號)+ 事後用 python 換佔位符。
|
||||
# ISEP wiki mistakes.md 記過:不加引號的 heredoc 會把訊息裡的反引號當命令執行,
|
||||
# 而**閘照樣 exit 2,所以只看離開碼的測試完全看不出來**。
|
||||
MSG=$(cat <<'EOF'
|
||||
🎫 這則留言裡藏著一件**還沒做完的事**,而它現在只是文字。
|
||||
|
||||
命中的詞:$HIT
|
||||
命中的詞:__HIT__
|
||||
|
||||
【leo 2026-08-27】「**每個任務長出子票做為這張票的相依⋯⋯票沒完工可以察覺嗎?**」
|
||||
|
||||
@@ -115,18 +169,32 @@ cat >&2 <<EOF
|
||||
08-26 18-23 總管真的出貨了 ← 條件滿足,沒人知道
|
||||
08-27 11:xx leo 問「這 14 小時前的,你派了還是沒派?」 ← 才被撿起來
|
||||
|
||||
【怎麼做】把它長成子票,Gitea 原生相依會**硬擋**母票關閉(實測 412):
|
||||
【怎麼做】__LEAD__
|
||||
|
||||
scripts/ticket subtask <母票 owner/repo#N> \\
|
||||
--title "身為<誰>,我要<什麼>,我才<為什麼>" \\
|
||||
-F <內文檔> --label s/todo --assign <誰做>
|
||||
|
||||
⇒ 子票沒關,母票關不掉。**不是提醒,是平台保證。**
|
||||
__EXAMPLE__
|
||||
__MORE__
|
||||
⇒ 子票沒關,母票關不掉。**不是提醒,是平台保證**(Gitea 原生相依,實測 412)。
|
||||
|
||||
【粒度】leo 2026-08-27:「**小任務做完就關閉,不會讓池子爆掉,
|
||||
每個事情沒有歷史記錄才是大問題**」⇒ 判準是「這件事需要被記得嗎」,
|
||||
傾向**多開票**。不要用「會不會太多」當理由不開。
|
||||
|
||||
【真的不是待辦】在指令裡加 \`no-subtask: <一句理由>\` 重送(留痕)。
|
||||
【真的不是待辦】在指令裡加 `no-subtask: <一句理由>` 重送(留痕)。
|
||||
EOF
|
||||
)
|
||||
|
||||
MORE_BLOCK=""
|
||||
[ -n "$MORE" ] && MORE_BLOCK="
|
||||
還有哪些參數(指派給誰+下一步、旅程標籤、換 repo):
|
||||
$(printf '%s' "$MORE" | sed 's/^/ /; s/[[:space:]]*$//')
|
||||
"
|
||||
|
||||
HIT="$HIT" LEAD="$LEAD" EXAMPLE="$EXAMPLE" MORE_BLOCK="$MORE_BLOCK" MSG="$MSG" python3 -c '
|
||||
import os, sys
|
||||
m = os.environ["MSG"]
|
||||
for k in ("HIT", "LEAD", "EXAMPLE"):
|
||||
m = m.replace("__%s__" % k, os.environ.get(k, ""))
|
||||
m = m.replace("__MORE__", os.environ.get("MORE_BLOCK", ""))
|
||||
sys.stderr.write(m + "\n")
|
||||
'
|
||||
exit 2
|
||||
|
||||
Reference in New Issue
Block a user